I spent quite a while trying to get an installation of MinGW32, so I thought I’d write a small guide for those that would like to cross compile win32 binaries on Linux.
For those that don’t know, MinGW is a free program that can compile Windows programs on the Linux platform (and I’m sure others). You can read more about it http://www.mingw.org. However, there are a lot of files to download and a lot of choices to make about your installation, and it is no light undertaking.
I found a wonderful resource on the internet for a very easy automated MinGW installation. The code for it is as follows:
build-cross.sh
#!/bin/sh
# This is my script for building a complete cross-compiler toolchain.
# It is based partly on Ray Kelm's script, which in turn was built on
# Mo Dejong's script for doing the same, but with some added fixes.
# The intent with this script is to build a cross-compiled version
# of the current MinGW environment.
#
# Updated by Sam Lantinga <slouken@libsdl.org>
# what flavor are we building?
TARGET=i586-mingw32msvc
# uncomment or add entries here
# where does it go? (your cross tools install directory)
#PREFIX=/usr/local/cross-tools
# if the prefix you are using needs root to access it please uncomment this
# (if you are using the above default prefix most likely you need this
#DO_SU=1
# your favorite downloader (pick one)
#DOWNLOADER="wget -c"
#DOWNLOADER="curl -#OLC -"
#DOWNLOADER="proz -rf"
# your platform specific optimisation flags. This is so that the compiler is optimised. This does not affect the win32 binaries in any way.
# CFLAGS="-O3 -march=pentium"
# your favorite mirror (pick one)
# austria
#MINGW_URL=ftp://gd.tuwien.ac.at/gnu/mingw
#MINGW_URL=http://gd.tuwien.ac.at/gnu/mingw
# Dublin, Ireland Europe
#MINGW_URL=http://heanet.dl.sourceforge.net/sourceforge/mingw
#Chapel Hill, NC North America
#MINGW_URL=http://unc.dl.sourceforge.net/sourceforge/mingw
# Minneapolis, MN North America
#MINGW_URL=http://umn.dl.sourceforge.net/sourceforge/mingw
# Reston, VA North America
#MINGW_URL=http://aleron.dl.sourceforge.net/sourceforge/mingw
# you probably don't need to change anything from here down
TOPDIR=`pwd`
SRCDIR="$TOPDIR/source"
# These are the files from the MinGW 1.1 release
GCC_VERSION=3.3.1-20030804-1
GCC=gcc-$GCC_VERSION
GCC_CORE=gcc-core-$GCC_VERSION
GCC_CORE_ARCHIVE=$GCC_CORE-src.tar.gz
GCC_GPP=gcc-g++-$GCC_VERSION
GCC_GPP_ARCHIVE=$GCC_GPP-src.tar.gz
GCC_PATCH=""
BINUTILS=binutils-2.13.90-20030111-1-src
BINUTILS_ARCHIVE=$BINUTILS.tar.gz
MINGW=mingw-runtime-3.2
MINGW_ARCHIVE=$MINGW.tar.gz
W32API=w32api-2.4
W32API_ARCHIVE=$W32API.tar.gz
# These are the files from the SDL website
SDL_URL=http://www.libsdl.org/extras/win32/common
# don't use the directx and opengl headers from SDL website, they are outdated and don't work with clanlib
# the opengl headers included in w32api-2.4 is better
# as for directx you need directx 8 for clanlib to work
#OPENGL_ARCHIVE=opengl-devel.tar.gz
#DIRECTX_ARCHIVE=directx-devel.tar.gz
# need install directory first on the path so gcc can find binutils
PATH="$PREFIX/bin:$PATH"
check_envars()
{
echo "checking envars..."
echo "If we bail out here, please edit this script to fix problems."
if test -z $PREFIX; then
echo "PREFIX not set, please set PREFIX to /usr/local/cross-tools or where-ever you want your cross tools"
echo "Note that you will also need to set DO_SU=1 if your install path needs root access"
exit 1
fi
if test -z $DOWNLOADER; then
echo "DOWNLOADER not set, please set DOWNLOADER to your favorite download program like wget, curl..."
exit 1
fi
if test -z $MINGW_URL; then
echo "MINGW_URL not set, please set MINGW_URL to your favorite mirror"
fi
echo "done checking envars"
}
#
# download a file from a given url, only if it is not present
#
download_file()
{
cd "$SRCDIR"
# if test ! -f $1 ; then
echo "Downloading $1"
$DOWNLOADER "$2/$1"
if test ! $? || test ! -f $1 ; then
echo "Could not download $1"
exit 1
fi
# else
# echo "Found $1 in the srcdir $SRCDIR"
# fi
cd "$TOPDIR"
}
download_files()
{
mkdir -p "$SRCDIR"
# Make sure wget is installed
if test "x`which wget`" = "x" ; then
echo "You need to install wget."
exit 1
fi
download_file "$GCC_CORE_ARCHIVE" "$MINGW_URL"
download_file "$GCC_GPP_ARCHIVE" "$MINGW_URL"
download_file "$BINUTILS_ARCHIVE" "$MINGW_URL"
download_file "$MINGW_ARCHIVE" "$MINGW_URL"
download_file "$W32API_ARCHIVE" "$MINGW_URL"
# download_file "$OPENGL_ARCHIVE" "$SDL_URL"
# download_file "$DIRECTX_ARCHIVE" "$SDL_URL"
}
install_libs()
{
echo "Installing cross libs and includes"
cat >install_libs.sh<<INSTALL_LIBS
mkdir -p "$PREFIX/$TARGET"
cd "$PREFIX/$TARGET"
gzip -dc "$SRCDIR/$MINGW_ARCHIVE" | tar xf -
gzip -dc "$SRCDIR/$W32API_ARCHIVE" | tar xf -
# gzip -dc "$SRCDIR/$OPENGL_ARCHIVE" | tar xf -
# gzip -dc "$SRCDIR/$DIRECTX_ARCHIVE" | tar xf -
INSTALL_LIBS
if test $DO_SU; then
su -c 'sh install_libs.sh'
else
sh install_libs.sh
fi
rm -f install_libs.sh
cd "$TOPDIR"
}
extract_binutils()
{
cd "$SRCDIR"
rm -rf "$BINUTILS"
echo "Extracting binutils"
gzip -dc "$SRCDIR/$BINUTILS_ARCHIVE" | tar xf -
cd "$TOPDIR"
}
configure_binutils()
{
cd "$TOPDIR"
rm -rf "binutils-$TARGET"
mkdir "binutils-$TARGET"
cd "binutils-$TARGET"
echo "Configuring binutils"
"$SRCDIR/$BINUTILS/configure" --prefix="$PREFIX" --target=$TARGET &> configure.log
cd "$TOPDIR"
}
build_binutils()
{
cd "$TOPDIR/binutils-$TARGET"
echo "Building binutils"
make &> make.log
if test $? -ne 0; then
echo "make failed - log available: binutils-$TARGET/make.log"
exit 1
fi
cd "$TOPDIR"
}
install_binutils()
{
cd "$TOPDIR/binutils-$TARGET"
echo "Installing binutils"
if test $DO_SU; then
su -c 'make install &> make-install.log'
else
make install &> make-install.log
fi
if test $? -ne 0; then
echo "install failed - log available: binutils-$TARGET/make-install.log"
exit 1
fi
cd "$TOPDIR"
}
extract_gcc()
{
cd "$SRCDIR"
rm -rf "$GCC"
echo "Extracting gcc"
gzip -dc "$SRCDIR/$GCC_CORE_ARCHIVE" | tar xf -
gzip -dc "$SRCDIR/$GCC_GPP_ARCHIVE" | tar xf -
cd "$TOPDIR"
}
patch_gcc()
{
if [ "$GCC_PATCH" != "" ]; then
echo "Patching gcc"
cd "$SRCDIR/$GCC"
patch -p1 < "$SRCDIR/$GCC_PATCH"
cd "$TOPDIR"
fi
}
configure_gcc()
{
cd "$TOPDIR"
rm -rf "gcc-$TARGET"
mkdir "gcc-$TARGET"
cd "gcc-$TARGET"
echo "Configuring gcc"
"$SRCDIR/$GCC/configure" -v \
--prefix="$PREFIX" --target=$TARGET \
--with-headers="$PREFIX/$TARGET/include" \
--with-gnu-as --with-gnu-ld \
--without-newlib --disable-multilib &> configure.log
cd "$TOPDIR"
}
build_gcc()
{
cd "$TOPDIR/gcc-$TARGET"
echo "Building gcc"
make LANGUAGES="c c++" &> make.log
if test $? -ne 0; then
echo "make failed - log available: gcc-$TARGET/make.log"
exit 1
fi
cd "$TOPDIR"
}
install_gcc()
{
cd "$TOPDIR/gcc-$TARGET"
echo "Installing gcc"
if test $DO_SU; then
su -c 'make LANGUAGES="c c++" install &> make-install.log'
else
make LANGUAGES="c c++" install &> make-install.log
fi
if test $? -ne 0; then
echo "install failed - log available: gcc-$TARGET/make-install.log"
exit 1
fi
cd "$TOPDIR"
}
final_tweaks()
{
echo "Finalizing installation"
cat >final_tweaks.sh<<FINAL_TWEAKS
# remove gcc build headers
rm -rf "$PREFIX/$TARGET/sys-include"
# Add extra binary links
if [ ! -f "$PREFIX/$TARGET/bin/objdump" ]; then
ln "$PREFIX/bin/$TARGET-objdump" "$PREFIX/$TARGET/bin/objdump"
fi
if [ ! -f "$PREFIX/$TARGET/bin/dllwrap" ]; then
ln "$PREFIX/bin/$TARGET-dllwrap" "$PREFIX/$TARGET/bin/dllwrap"
fi
if [ ! -f "$PREFIX/$TARGET/bin/windres" ]; then
ln "$PREFIX/bin/$TARGET-windres" "$PREFIX/$TARGET/bin/windres"
fi
# make cc and c++ symlinks to gcc and g++
if [ ! -f "$PREFIX/$TARGET/bin/g++" ]; then
ln "$PREFIX/bin/$TARGET-g++" "$PREFIX/$TARGET/bin/g++"
fi
if [ ! -f "$PREFIX/$TARGET/bin/cc" ]; then
ln -s "gcc" "$PREFIX/$TARGET/bin/cc"
fi
if [ ! -f "$PREFIX/$TARGET/bin/c++" ]; then
ln -s "g++" "$PREFIX/$TARGET/bin/c++"
fi
# strip all the binaries
ls "$PREFIX"/bin/* "$PREFIX/$TARGET"/bin/* | egrep -v '.dll$' |
while read file; do
strip "$file"
done
FINAL_TWEAKS
if test $DO_SU; then
su -c 'sh final_tweaks.sh'
else
sh final_tweaks.sh
fi
rm -f final_tweaks.sh
echo "Installation complete!"
}
check_envars
download_files
install_libs
extract_binutils
configure_binutils
build_binutils
install_binutils
extract_gcc
patch_gcc
configure_gcc
build_gcc
install_gcc
final_tweaks
Copy and paste that into a file called build-cross.sh. You will need root access on the machine you are trying to install this on. Make a temporary directory and drop this file into then. With your favorite editor, edit the top portion of the script, following the existing instructions. You will semi-customize your installation with this. Once you are done, save it, and run the script:
sh build-cross.sh
Assuming you followed the instructions in the file, the program will start to download/compile.
A problem I ran into is that on my Linux distro, Bison and Flex were not installed by default. If you get an error during the binutils compilation, you might trying to check that those two programs are in fact installed, and if not, install them.
Once MinGW is installed, you will need to edit one more file to get your cross compiling going. Find the cross-scons.sh file in your ETSDK/src directory. You will need to edit two lines.
PREFIX=/usr/local/cross-tools
TARGET=i386-mingw32msvc
Assuming you left the install directory as the default one in the script, you can leave the PREFIX line alone. You will need to change the TARGET directory though, to:
TARGET=i586-mingw32msvc
You’re done! Go ahead and give it a try with
sh cross-scons.sh BUILD=release