Build a MinGW Hosted Cross Compiler for Other Platforms

 

TODO: Formatting -- I think I (Keith) got it right; please fix any errors.

FIXME: Software versions described are outdated; please update as appropriate, for current versions.

Building a MinGW Hosted Cross Compiler

To compile and link executables for an embedded target under windows you require a cross compiler for your required processor. This is almost as easy with a properly configured MSYS/MinGW installation as it is with a GNU/Linux machine, merely requiring a few patches for some things that aren't available in a windows native environment.

First you'll need a basic compiler setup -- MinGW and MSYS -- in order to run the configuration scripts. bison and flex are also required in order to build a GCC toolchain from source. Additionally you will need the MSYS Developer Toolkit

Now you will need the source packages.

For an embedded target you require a C library of some description -- newlib is the usual choice.

Extract the archives to a convenient place, binutils and newlib have their own folders, the 3 GCC packages should all be extracted to the same directory. The example shell scripts given here can just be saved to the build directory and run directly from the MSYS shell. Although they specify an arm-elf target they should be suitable for any cross compiler if you change the target variable to suit your chosen processor.

The --enable-interwork and --enable-multilib options are specific to the ARM compiler and should, in most cases be removed and specify --disable-multilib instead.

Building and Installing the Binutils Package

Here's a sample shell script for building arm-elf cross tools - this should be run from a build directory outside the source directory. In this example absolute paths are specified, you should edit the SRCDIR and prefix variables to reflect your own system.

#---------------------------------------------------------------------------------
# Source and Install directories
#---------------------------------------------------------------------------------

SRCDIR=/c/gcc-source/binutils-2.15.90-20040222-1    # the source code dir for binutils
prefix=/c/cross-gcc/arm-elf                         # installation directory

#---------------------------------------------------------------------------------
# set the target and compiler flags
#---------------------------------------------------------------------------------

target=arm-elf

export CFLAGS='-O2 -pipe'
export CXXFLAGS='-O2 -pipe'
export LDFLAGS='-s'
export DEBUG_FLAGS=''

#---------------------------------------------------------------------------------
# Build and install binutils
#---------------------------------------------------------------------------------

mkdir -p $target/binutils
cd $target/binutils

$SRCDIR/configure --prefix=$prefix --target=$target \ 
    --disable-nls --disable-shared --enable-debug --disable-threads \ 
    --with-gcc --with-gnu-as --with-gnu-ld --with-stabs \ 
    --enable-interwork --enable-multilib \ 
    2>&1 | tee binutils_configure.log

make    all 2>&1 | tee binutils_make.log
make    install 2>&1 | tee binutils_install.log

Building and Installing the C Compiler

Again, an example shell script for compiling and installing an arm-elf cross. In this case edit the SRCDIR and prefix variables as before but also edit the path to point to the bin directory of the binutils installation we've just built. When configuring GCC we must use a relative path or gengtype will fail.

You will also need to modify the gcc/fixinc/mkfixinc.sh script. This is true for at least version GCC-3.4.2. For example, in this package the script would be under gcc-3.4.2-20040916-1/gcc/fixinc. Apparently MinGW doesn't support fixinc in versions of GCC pre-dating 4.0 (mainline CVS.) Therefore, you must disable it. In the version I used (gcc-3.4.2-20040916-1) and targetting for i386-elf, I changed the following:

Right after line 47, which contains:

i?86-*-mingw32* | \ 

I inserted:

i?86-*-elf* | \ 

which tells the shell not to generate a fixinc script for that target.

Another important option to include is --without--headers. If you are retargetting GCC to cross-compile for your own OS and you don't have a complete set of C libraries and/or headers, this option lets you make a freestanding cross-compiler. It can make your life a lot easier.

The make targets all-gcc and install-gcc are used here to prevent the build process from attempting to build and install the C++ compiler and libraries before we have the base C libraries built and installed. The libraries and headers provided by the C library (newlib) are required for that part.

#---------------------------------------------------------------------------------
# Source and Install directories
#---------------------------------------------------------------------------------

SRCDIR=../../gcc-3.4.0-20040501-1            # the sourcecode dir for gcc
                                             # This *must* be specified in the format shown here
                                             # as one of the tools built during the process will fail
                                             # if absolute paths are specified
                                             # the example here assumes that the gcc source directory
                                             # is at the same level as the script

prefix=c:/cross-gcc/arm-elf                  # installation directory
                                             # This *must* be specified in the format shown here
                                             # or gcc won't be able to find it's libraries and includes
                                             # if you move the installation

#---------------------------------------------------------------------------------
# set the path for the installed binutils
#---------------------------------------------------------------------------------

export PATH=${PATH}:/c/cross-gcc/arm-elf/bin

#---------------------------------------------------------------------------------
# set the target and compiler flags
#---------------------------------------------------------------------------------

target=arm-elf

export CFLAGS='-O2 -pipe'
export CXXFLAGS='-O2 -pipe'
export LDFLAGS='-s'
export DEBUG_FLAGS=''

#---------------------------------------------------------------------------------
# build and install just the c compiler
#---------------------------------------------------------------------------------

mkdir -p $target/gcc
cd $target/gcc

$SRCDIR/configure \ 
    --enable-languages=c,c++ \ 
    --with-cpu=arm7tdmi \ 
    --enable-interwork --enable-multilib \ 
    --with-gcc --with-gnu-ld --with-gnu-as --with-stabs \ 
    --disable-shared --disable-threads --disable-win32-registry --disable-nls \ 
    --target=$target \ 
    --with-newlib \                                      # Alternatively use --without-headers here
    --prefix=$prefix -v \ 
    2>&1 | tee gcc_configure.log

make all-gcc | tee make-c-only.log 2>&1
make install-gcc | tee install-c-only.log 2>&1

Building and Installing Newlib

Now we have a C compiler we need a set of standard C libraries. As for the C compiler stage, edit the SRCDIR, prefix and path variables.

#---------------------------------------------------------------------------------
# Source and Install directories
#---------------------------------------------------------------------------------

SRCDIR=/c/gcc-source/newlib-1.12.0   # the sourcecode dir for newlib
prefix=/c/cross-gcc/arm-elf          # installation directory
#---------------------------------------------------------------------------------
# set the path for the installed binutils and C compiler
#---------------------------------------------------------------------------------

export PATH=${PATH}:/c/cross-gcc/arm-elf/bin

#---------------------------------------------------------------------------------
# set target and compiler flags
#---------------------------------------------------------------------------------

target=arm-elf

export CFLAGS='-O2 -pipe'
export CXXFLAGS='-O2 -pipe'
export LDFLAGS='-s'
export DEBUG_FLAGS=''

#---------------------------------------------------------------------------------
# Build and install newlib
#---------------------------------------------------------------------------------

mkdir -p $target/newlib
cd $target/newlib

$SRCDIR/configure \ 
    --target=$target --prefix=$prefix \ 
    2>&1 | tee newlib_configure.log

make all 2>&1 | tee newlib_make.log
make install 2>&1 | tee newlib_install.log

At this point you will have a working C compiler for your chosen target, if you don't wish to use C++ you need do nothing further but update your path for the new toolchain. In the case of the example arm-elf tools this would be c:\cross-gcc\arm-elf\bin.

Building and Installing the C++ Compiler

Now we have the base C compiler we can go back and complete the build for C++ and it's libraries. At this stage we only need to specify the path to the installed tools, the GCC build has already been configured and knows where to find the sources.

#---------------------------------------------------------------------------------
# set the path for the installed binutils
#---------------------------------------------------------------------------------

export PATH=${PATH}:/c/cross-gcc/arm-elf/bin

#---------------------------------------------------------------------------------
# set the target and compiler flags
#---------------------------------------------------------------------------------

target=arm-elf

export CFLAGS='-O2 -pipe'
export CXXFLAGS='-O2 -pipe'
export LDFLAGS='-s'
export DEBUG_FLAGS=''

#---------------------------------------------------------------------------------
# Finish build and install process
#---------------------------------------------------------------------------------

cd $target/gcc

make all | tee final_make.log 2>&1
make install | tee final_install.log 2>&1

Site Status

Site maintenance completed May 25th, 2012 at 12:38 UTC