.

This is the bash shell script that I use to build a MinGW cross compiler on Linux. Edit the macros in the "user settings" section at the beginning to tailor it to your needs.

Remember to update the names of the archive files downloaded to reflect the current versions of the various components (or whichever versions you want to use); it is set the build gcc 3.4.2 (the "current" version the last time this was updated). And remember to run it as "root" if the install directory you selected requires root access.

I've used this script on Mandrake and RedHat Linux distributions.

Igor

Note: I've also used this script on Debian, adjusted for 3.4.4. I don't use 3.4.2 as it has a bug with its threading: http://thread.gmane.org/gmane.comp.gnu.mingw.user/16766

Note also: The specified version of binutils did not build for me (on neither Debian amd64 nor i386), whereas binutils-2.16.91-20050827-1-src.tar.gz built fine on both.

Same for me too -- the exact error was: (from binutils-mingw32/make.log)

ar.o: In function `mri_emul': ar.c:(.text+0x23): undefined reference to `yyparse' collect2: ld returned 1 exit status

This might have resulted from:

Extracting binutils tar: A lone zero block at 147446

In my humble opinion, the error you both mention does not follow from the zero block in the tar-file. In most cases, it is solvable by installing bison, flex and m4.

If you're interested in gcc 4, you might want to look at the note at the bottom of build a Win32 x-compiler for Linux.

To what degree has this been superceded (or not) by the "Cross-Hosted MinGW Build Tool"?


#! /bin/bash

# This is my script for building a complete MinGW cross-compiler toolchain
# that runs under Linux to produce executables that run under Windows.  It
# probably works (or can easily be adapted to work) under any unix system.
#
# It is based in large part on Sam Lantinga's script, which in turn was
# 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.
#
# My changes:
#       1. Adapted the script to the new packaging of MinGW GCC, which is
#          currently split into core and auxiliary components.
#       2. The script now determines the GCC and BINUTILS directory name
#          directly from the tar file contents.  This gets around common
#          problems due to the directory names not always following the
#          expected patterns.
#       3. Grouped together and simplified the macros that users need to
#          define.
#       4. Made optional components truly optional -- leave the
#          corresponding archive names blank and they will be ignored.
#       5. Included an option to purge the installation directory before
#          installing the current cross-compiler.
#
# NOTE: If you choose a destination directory for the installation (set
# in the macro PREFIX) for which you do not have write access, you will
# need to run this script with root (or equivalent) privileges.
#
#
# Updated by Igor Mikolic-Torreira <igormt@alumni.caltech.edu>



#-----------------------------------------------------
#
# BEGIN USER SETTINGS
#
# You need to review and adjust the macros that follow
#
#-----------------------------------------------------


# What flavor of GCC cross-compiler are we building?

TARGET=mingw32

# What directory will the cross-compiler be built in?
# This is the directory into which source archives will
# be downloaded, expanded, compiled, etc.  You need to
# have write-access to this directory.  If you leave it
# blank, it defaults to the current directory.

BUILDDIR=

# Where does the cross-compiler go?
# This should be the directory into which your cross-compiler
# will be installed.  Remember that if you set this to a directory
# that only root has write access to, you will need to run this
# script as root.

PREFIX=/usr/local/mingw32

# Purge anything and everything already in the $PREFIX
#(also known as the destination or installation) directory?
# Set to "Y" to purge, any other value omits the purge step.

PURGE_DIR="Y"


# Set the following to the files from the current MinGW release
# (or whichever MinGW release you wish to build and install)
# You need to set both the URL they will be downloaded from
# and the exact name of the individual component files.

MINGW_URL="http://heanet.dl.sourceforge.net/sourceforge/mingw"

# GCC_CORE is required; the other components are optional.
# Set any you don't want to "".  You need binutils,
# mingw runtime and w32api; do not ever set those to "".

GCC_CORE_ARCHIVE="gcc-core-3.4.2-20040916-1-src.tar.gz"
GCC_GPP_ARCHIVE="gcc-g++-3.4.2-20040916-1-src.tar.gz"
GCC_G77_ARCHIVE="gcc-g77-3.4.2-20040916-1-src.tar.gz"
GCC_OBJC_ARCHIVE="gcc-objc-3.4.2-20040916-1-src.tar.gz"
GCC_JAVA_ARCHIVE="gcc-java-3.4.2-20040916-1-src.tar.gz"
GCC_ADA_ARCHIVE=""
GCC_PATCH=""

BINUTILS_ARCHIVE="binutils-2.15.91-20040904-1-src.tar.gz"

MINGW_ARCHIVE="mingw-runtime-3.7.tar.gz"

W32API_ARCHIVE="w32api-3.2.tar.gz"


# These are the files from the SDL website
# These are optional, set them to "" if you don't want them)

SDL_URL="http://www.libsdl.org/extras/win32/common"

OPENGL_ARCHIVE="opengl-devel.tar.gz"
DIRECTX_ARCHIVE="directx-devel.tar.gz"



#-----------------------------------------------------
#
# END USER SETTINGS
#
# The remainder of the script should not neet any edits
#
#-----------------------------------------------------



# Make sure these are initialized as we want them

GCC_CORE=""
BINUTILS=""
GCC_LANGS="c"


# Set our build directory and where our sources will go

if [ "x$BUILDDIR" = "x" ]; then
        # Default to the current directory
        BUILDDIR=$(pwd)
fi
SRCDIR="$BUILDDIR/source"


# Need install directory first on the path so gcc can find binutils

PATH="$PREFIX/bin:$PATH"



#-----------------------------------------------------
#
# Functions that do most of the work
#
#-----------------------------------------------------


function download_files
{
        # Download a file from a given url, only if it is not present
        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"
        if [ "x$GCC_GPP_ARCHIVE" != "x" ]; then
                download_file "$GCC_GPP_ARCHIVE" "$MINGW_URL"
        fi
        if [ "x$GCC_G77_ARCHIVE" != "x" ]; then
                download_file "$GCC_G77_ARCHIVE" "$MINGW_URL"
        fi
        if [ "x$GCC_OBJC_ARCHIVE" != "x" ]; then
                download_file "$GCC_OBJC_ARCHIVE" "$MINGW_URL"
        fi
        if [ "x$GCC_JAVA_ARCHIVE" != "x" ]; then
                download_file "$GCC_JAVA_ARCHIVE" "$MINGW_URL"
        fi
        if [ "x$GCC_ADA_ARCHIVE" != "x" ]; then
                download_file "$GCC_ADA_ARCHIVE" "$MINGW_URL"
        fi

        download_file "$BINUTILS_ARCHIVE" "$MINGW_URL"
        download_file "$MINGW_ARCHIVE" "$MINGW_URL"
        download_file "$W32API_ARCHIVE" "$MINGW_URL"

        if [ "x$OPENGL_ARCHIVE" != "x" ]; then
                download_file "$OPENGL_ARCHIVE" "$SDL_URL"
        fi
        if [ "x$DIRECTX_ARCHIVE" != "x" ]; then
                download_file "$DIRECTX_ARCHIVE" "$SDL_URL"
        fi
}


function download_file
{
        cd "$SRCDIR"
        if test ! -f $1 ; then
                echo "Downloading $1"
                wget "$2/$1"
                if test ! -f $1 ; then
                        echo "Could not download $1"
                        exit 1
                fi
        else
                echo "Found $1 in the srcdir $SRCDIR"
        fi
        cd "$BUILDDIR"
}


function purge_existing_install
{
        echo "Purging the existing files in $PREFIX"
        if cd "$PREFIX"; then
                rm -rf *
        fi
        cd "$BUILDDIR"
}


function install_libs
{
        echo "Installing cross libs and includes"
        mkdir -p "$PREFIX/$TARGET"
        cd "$PREFIX/$TARGET"

        tar -xzf "$SRCDIR/$MINGW_ARCHIVE"
        tar -xzf "$SRCDIR/$W32API_ARCHIVE"

        if [ "x$OPENGL_ARCHIVE" != "x" ]; then
                tar -xzf "$SRCDIR/$OPENGL_ARCHIVE"
        fi

        if [ "x$DIRECTX_ARCHIVE" != "x" ]; then
                tar -xzf "$SRCDIR/$DIRECTX_ARCHIVE"
        fi

        cd "$BUILDDIR"
}


function extract_binutils
{
        cd "$SRCDIR"
        BINUTILS=`tar -tzf "$SRCDIR/$BINUTILS_ARCHIVE" | head -n 1`
        rm -rf "$BINUTILS"
        echo "Extracting binutils"
        tar -xzf "$SRCDIR/$BINUTILS_ARCHIVE"
        cd "$BUILDDIR"
}


function configure_binutils
{
        cd "$BUILDDIR"
        rm -rf "binutils-$TARGET"
        mkdir "binutils-$TARGET"
        cd "binutils-$TARGET"
        echo "Configuring binutils"
        "$SRCDIR/$BINUTILS/configure" --prefix="$PREFIX" --target=$TARGET --disable-nls \
                --with-gcc --with-gnu-as --with-gnu-ld --disable-shared &> configure.log
        cd "$BUILDDIR"
}


function build_binutils
{
        cd "$BUILDDIR/binutils-$TARGET"
        echo "Building binutils"
        make CFLAGS="-O2 -fno-exceptions" LDFLAGS="-s" &> make.log
        if test $? -ne 0; then
                echo "make of binutils failed - log available: binutils-$TARGET/make.log"
                exit 1
        fi
        cd "$BUILDDIR"
}


function install_binutils
{
        cd "$BUILDDIR/binutils-$TARGET"
        echo "Installing binutils"
        make install &> make-install.log
        if test $? -ne 0; then
                echo "install of binutils failed - log available: binutils-$TARGET/make-install.log"
                exit 1
        fi
        cd "$BUILDDIR"
}


function extract_gcc
{
        cd "$SRCDIR"
        GCC=`tar -tzf "$SRCDIR/$GCC_CORE_ARCHIVE" | head -n 1`
        rm -rf "$GCC"
        echo "Extracting gcc"
        tar -xzf "$SRCDIR/$GCC_CORE_ARCHIVE"
        if [ "x$GCC_GPP_ARCHIVE" != "x" ]; then
                GCC_LANGS=${GCC_LANGS}",c++"
                tar -xzf "$SRCDIR/$GCC_GPP_ARCHIVE"
        fi
        if [ "x$GCC_G77_ARCHIVE" != "x" ]; then
                GCC_LANGS=${GCC_LANGS}",f77"
                tar -xzf "$SRCDIR/$GCC_G77_ARCHIVE"
        fi
        if [ "x$GCC_OBJC_ARCHIVE" != "x" ]; then
                GCC_LANGS=${GCC_LANGS}",objc"
                tar -xzf "$SRCDIR/$GCC_OBJC_ARCHIVE"
        fi
        if [ "x$GCC_JAVA_ARCHIVE" != "x" ]; then
                GCC_LANGS=${GCC_LANGS}",java"
                tar -xzf "$SRCDIR/$GCC_JAVA_ARCHIVE"
        fi
        if [ "x$GCC_ADA_ARCHIVE" != "x" ]; then
                GCC_LANGS=${GCC_LANGS}",ada"
                tar -xzf "$SRCDIR/$GCC_ADA_ARCHIVE"
        fi
        cd "$BUILDDIR"
}


function patch_gcc
{
        if [ "$GCC_PATCH" != "" ]; then
                echo "Patching gcc"
                cd "$SRCDIR/$GCC"
                patch -p1 < "$SRCDIR/$GCC_PATCH"
                cd "$BUILDDIR"
        fi
}


function configure_gcc
{
        cd "$BUILDDIR"
        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-gcc --with-gnu-ld --with-gnu-as \
                --enable-threads --disable-nls --enable-languages=$GCC_LANGS \
                --disable-win32-registry --disable-shared --enable-sjlj-exceptions --enable-libgcj \
                --disable-java-awt --without-x --enable-java-gc=boehm --disable-libgcj-debug \
                --enable-interpreter --enable-hash-synchronization --enable-libstdcxx-debug \
                &> configure.log
        cd "$BUILDDIR"
}


function build_gcc
{
        cd "$BUILDDIR/gcc-$TARGET"
        echo "Building gcc"
        make CFLAGS="-O2" CXXFLAGS="-O2" GCJFLAGS="-O2" LDFLAGS="-s" DEBUG_FLAGS="-g0" &> make.log
        if test $? -ne 0; then
                echo "make of gcc failed - log available: gcc-$TARGET/make.log"
                exit 1
        fi
        if [ "x$GCC_ADA" != "x" ]; then
                cd gcc
                make "CFLAGS=-O2" "LDFLAGS=-s" gnatlib_and_tools &> make-gnatlib.log
                if test $? -ne 0; then
                        echo "make of gnatlib and tools failed - log available: gcc-$TARGET/make-gnatlib.log"
                        exit 1
                fi
        fi
        cd "$BUILDDIR"
}


function install_gcc
{
        cd "$BUILDDIR/gcc-$TARGET"
        echo "Installing gcc"
        make install &> make-install.log
        if test $? -ne 0; then
                echo "install of gcc failed - log available: gcc-$TARGET/make-install.log"
                exit 1
        fi
        cd "$BUILDDIR"
}


function final_tweaks
{
        echo "Finalizing installation"

        # 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

        # 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$' | egrep -v 'gccbug$' |
        while read file; do
                strip "$file"
        done

        echo "Installation complete!"
}



#
# Main part of the script
#

download_files

if [ "x$PURGE_DIR" = "xY" ]; then
        purge_existing_install
fi

install_libs

extract_binutils
configure_binutils
build_binutils
install_binutils

extract_gcc
patch_gcc
configure_gcc
build_gcc
install_gcc

final_tweaks


#
# End
#