14 September 2005
Cross GCC on a Win32 platform
Here is a document that outlines the process needed to build a GCC cross compiling system that is hosted on a Windows computer using Cygwin. Many developers would like to use the GNU tools but are constrained by the fact that either their employers will not provide them with another unix-like computer or they have no desire to learn another operating system for one task. There are solutions that allow you to use free software to do embedded development, but they are poorly documented from the Win32 user's perspective. My goal is to provide clarification on these issues and to point the user in the right direction as to where to get help when things go wrong.
Comments:
<< Home
I have a build script that automates the tool building process. As of today, it works with the following tools.
Binutils - Snapshot on or after 5 Sept 2005.
GCC - 4.0.2
Newlib - 1.14.0
The current binutils (2.16) has a bug in the m68k code that causes trouble with some instructions. It may work fine for other architectures.
Anyway, here it is...
#!/bin/sh
# Build an embedded development toolchain
# assume that archives are in source/archive directory (relative to this one)
DIRECTORY=`pwd`
SOURCEDIR=$DIRECTORY/source
ARCHIVES=$SOURCEDIR/archive
PREFIX=$DIRECTORY
TARGET=m68k-rtems
TIMEFILE=$DIRECTORY/totaltime.txt
EXT=.exe
# The last known configuration known to work
# BINUTILS_VER=050930 (pre 2.17)
# GCC_VER=4.0.2
# NEWLIB_VER=1.13.0
#
BINUTILS_VER=050930
BINUTILS_ARCHIVE=$ARCHIVES/binutils-$BINUTILS_VER.tar.bz2
GCC_VER=4.0.2
GCC_ARCHIVE=$ARCHIVES/gcc-$GCC_VER.tar.bz2
NEWLIB_VER=1.14.0
NEWLIB_ARCHIVE=$ARCHIVES/newlib-$NEWLIB_VER.tar.gz
RTEMS_VER=012906
RTEMS_ARCHIVE=$ARCHIVES/rtems-$RTEMS_VER.tar.bz2
RTEMS_BSP=mcf5206elite
# Backup the last file
if [ -x $TIMEFILE ]; then
mv $TIMEFILE $TIMEFILE.old
fi
echo Building Binutils and GCC for $TARGET
echo =============================================================
echo " " > $TIMEFILE
echo "----------------- Build Report -----------------" >> $TIMEFILE
date >> $TIMEFILE
echo -n "Building Cross compiler for $TARGET on " >> $TIMEFILE
uname -sm >> $TIMEFILE
echo "------------------------------------------------" >> $TIMEFILE
echo "DIRECTORY=$DIRECTORY" >> $TIMEFILE
echo "SOURCEDIR=$SOURCEDIR" >> $TIMEFILE
echo "ARCHIVES=$ARCHIVES" >> $TIMEFILE
echo "PREFIX=$PREFIX" >> $TIMEFILE
echo "TARGET=$TARGET" >> $TIMEFILE
echo "TIMEFILE=$TIMEFILE" >> $TIMEFILE
echo "------------------------------------------------" >> $TIMEFILE
# Builds are in the source directory
cd $SOURCEDIR
if [ ! -x build ]; then
mkdir build
fi
# ---------------------- Unpack everything if needed
UNPACKING_TIME=`date`
if [ ! -x binutils-$BINUTILS_VER ]; then
tar -xjvpf $BINUTILS_ARCHIVE
fi
if [ ! -x newlib-$NEWLIB_VER ]; then
tar -xzvpf $NEWLIB_ARCHIVE
fi
if [ ! -x gcc-$GCC_VER ]; then
tar -xjvpf $GCC_ARCHIVE
fi
# ------- Make the newlib link
if [ ! -x gcc-$GCC_VER/newlib ]; then
cd gcc-$GCC_VER
ln -s ../newlib-$NEWLIB_VER/newlib .
cd ..
fi
# echo Extracting RTEMS $RTEMS_VER sources
# tar -xjvpf $RTEMS_ARCHIVE
# ---------------------- Build binutils
echo ==================== BUILDING binutils-$BINUTILS_VER ====================
BINUTILS_TIME=`date`
cd build
if [ ! -x binutils ]; then
# Configure
mkdir binutils
cd binutils
../../binutils-$BINUTILS_VER/configure --target=$TARGET --prefix=$PREFIX
else
# Already configured, just (re)make it
cd binutils
fi
make
make install
PATH=$PREFIX/bin:${PATH}
# Check that the assembler is installed correctly in $PREFIX/bin
if [ -x $PREFIX/bin/$TARGET-as$EXT ]
then
echo "==================== BINUTILS complete ========================="
ASSEMBLER=$PREFIX/bin/$TARGET-as$EXT
LINKER=$PREFIX/bin/$TARGET-ld$EXT
echo "ASSEMBLER=$ASSEMBLER" >> $TIMEFILE
echo "LINKER=$LINKER" >> $TIMEFILE
else
echo "Unable to find $PREFIX/bin/$TARGET-as$EXT"
exit 1
fi
cd ../..
# ---------------------- Build the bootstrap GCC for building newlib
# We need to build a stripped down GCC configured for the target that
# we will use to build newlib. Once newlib is built, then GCC will be
# rebuilt and will use newlib as the default C library.
echo ==================== BUILDING gcc-$GCC_VER ====================
GCC1_TIME=`date`
cd build
if [ ! -x gcc ]; then
# Configure
mkdir gcc
cd gcc
../../gcc-$GCC_VER/configure --with-newlib --without-headers --target=$TARGET --prefix=$PREFIX --with-as=$ASSEMBLER --with-ld=$LINKER
else
# Already configured, just make it
cd gcc
fi
make all-gcc && make install-gcc
cd ../..
echo ==================== BUILDING Newlib-$NEWLIB_VER ====================
NEWLIB_TIME=`date`
cd build
if [ ! -x newlib ]; then
# Configure
mkdir newlib
cd newlib
../../newlib-$NEWLIB_VER/configure --target=$TARGET --prefix=$PREFIX
else
# Already configured, just (re)make it
cd newlib
fi
make && make install
cd ../..
echo ==================== BUILDING gcc-$GCC_VER ====================
GCC2_TIME=`date`
cd build
# gcc folder should already be there from the previous build. Reconfigure
# and rebuild with the custom newlib support
if [ ! -x gcc ]; then
mkdir gcc
cd gcc
else
cd gcc
fi
../../gcc-$GCC_VER/configure --with-newlib --enable-threads --target=$TARGET --prefix=$PREFIX --with-as=$ASSEMBLER --with-ld=$LINKER
make all-gcc && make install-gcc
# Check that the compiler is installed correctly in $PREFIX/bin
if [ -x $PREFIX/bin/$TARGET-gcc$EXT ]
then
echo "==================== GCC build complete ========================"
COMPILER=$PREFIX/bin/$TARGET-gcc$EXT
echo "COMPILER=$COMPILER" >> $TIMEFILE
else
echo "==================== ERROR building GCC ========================"
echo "COMPILER=" >> $TIMEFILE
exit 1
fi
cd ../..
echo " " >> $TIMEFILE
echo "------------------------------------------------" >> $TIMEFILE
# Test the toolchain by creating a small file and compiling it.
echo " "
echo "------------------------- TESTING THE TOOLS -------------------------"
echo " "
if [ ! -x test ]; then
mkdir test
fi
cd test
echo " " > test.c
echo "#include <stdio.h>" >> test.c
echo " " >> test.c
echo "void _start(void) { foo(5); };" >> test.c
echo " " >> test.c
echo "int foo( int x )" >> test.c
echo "{" >> test.c
echo " return x+1;" >> test.c
echo "}" >> test.c
# $PREFIX/bin should be in the path to allow this to execute
# - Just compile for now.
echo ASSEMBLER=$ASSEMBLER > output.txt
echo LINKER=$LINKER >> output.txt
echo COMPILER=$COMPILER >> output.txt
echo INCLUDE=$INCLUDE >> output.txt
echo "------------------------------------------------------" >> output.txt
$COMPILER -I$INCLUDE -c -o test.o test.c >> output.txt
if [ ! -x test.o ]; then
# Error! unable to build test code.
echo "------------ Test Build Failed ----------------------"
echo
cat output.txt
else
echo "------------ Test Build Successful ------------------"
rm test.o test.c output.txt
fi
cd ..
# ----------------------- Done!
echo "------------------------------------------------" >> $TIMEFILE
echo " " >> $TIMEFILE
echo Start times >> $TIMEFILE
echo "Unpack..........$UNPACKING_TIME" >> $TIMEFILE
echo "Binutils........$BINUTILS_TIME" >> $TIMEFILE
echo "Pre-GCC.........$GCC1_TIME" >> $TIMEFILE
echo "Newlib..........$NEWLIB_TIME" >> $TIMEFILE
echo "GCC.............$GCC2_TIME" >> $TIMEFILE
echo -n "Finished........" >> $TIMEFILE
date >> $TIMEFILE
cat $TIMEFILE
echo buildit.sh ended
Post a Comment
Binutils - Snapshot on or after 5 Sept 2005.
GCC - 4.0.2
Newlib - 1.14.0
The current binutils (2.16) has a bug in the m68k code that causes trouble with some instructions. It may work fine for other architectures.
Anyway, here it is...
#!/bin/sh
# Build an embedded development toolchain
# assume that archives are in source/archive directory (relative to this one)
DIRECTORY=`pwd`
SOURCEDIR=$DIRECTORY/source
ARCHIVES=$SOURCEDIR/archive
PREFIX=$DIRECTORY
TARGET=m68k-rtems
TIMEFILE=$DIRECTORY/totaltime.txt
EXT=.exe
# The last known configuration known to work
# BINUTILS_VER=050930 (pre 2.17)
# GCC_VER=4.0.2
# NEWLIB_VER=1.13.0
#
BINUTILS_VER=050930
BINUTILS_ARCHIVE=$ARCHIVES/binutils-$BINUTILS_VER.tar.bz2
GCC_VER=4.0.2
GCC_ARCHIVE=$ARCHIVES/gcc-$GCC_VER.tar.bz2
NEWLIB_VER=1.14.0
NEWLIB_ARCHIVE=$ARCHIVES/newlib-$NEWLIB_VER.tar.gz
RTEMS_VER=012906
RTEMS_ARCHIVE=$ARCHIVES/rtems-$RTEMS_VER.tar.bz2
RTEMS_BSP=mcf5206elite
# Backup the last file
if [ -x $TIMEFILE ]; then
mv $TIMEFILE $TIMEFILE.old
fi
echo Building Binutils and GCC for $TARGET
echo =============================================================
echo " " > $TIMEFILE
echo "----------------- Build Report -----------------" >> $TIMEFILE
date >> $TIMEFILE
echo -n "Building Cross compiler for $TARGET on " >> $TIMEFILE
uname -sm >> $TIMEFILE
echo "------------------------------------------------" >> $TIMEFILE
echo "DIRECTORY=$DIRECTORY" >> $TIMEFILE
echo "SOURCEDIR=$SOURCEDIR" >> $TIMEFILE
echo "ARCHIVES=$ARCHIVES" >> $TIMEFILE
echo "PREFIX=$PREFIX" >> $TIMEFILE
echo "TARGET=$TARGET" >> $TIMEFILE
echo "TIMEFILE=$TIMEFILE" >> $TIMEFILE
echo "------------------------------------------------" >> $TIMEFILE
# Builds are in the source directory
cd $SOURCEDIR
if [ ! -x build ]; then
mkdir build
fi
# ---------------------- Unpack everything if needed
UNPACKING_TIME=`date`
if [ ! -x binutils-$BINUTILS_VER ]; then
tar -xjvpf $BINUTILS_ARCHIVE
fi
if [ ! -x newlib-$NEWLIB_VER ]; then
tar -xzvpf $NEWLIB_ARCHIVE
fi
if [ ! -x gcc-$GCC_VER ]; then
tar -xjvpf $GCC_ARCHIVE
fi
# ------- Make the newlib link
if [ ! -x gcc-$GCC_VER/newlib ]; then
cd gcc-$GCC_VER
ln -s ../newlib-$NEWLIB_VER/newlib .
cd ..
fi
# echo Extracting RTEMS $RTEMS_VER sources
# tar -xjvpf $RTEMS_ARCHIVE
# ---------------------- Build binutils
echo ==================== BUILDING binutils-$BINUTILS_VER ====================
BINUTILS_TIME=`date`
cd build
if [ ! -x binutils ]; then
# Configure
mkdir binutils
cd binutils
../../binutils-$BINUTILS_VER/configure --target=$TARGET --prefix=$PREFIX
else
# Already configured, just (re)make it
cd binutils
fi
make
make install
PATH=$PREFIX/bin:${PATH}
# Check that the assembler is installed correctly in $PREFIX/bin
if [ -x $PREFIX/bin/$TARGET-as$EXT ]
then
echo "==================== BINUTILS complete ========================="
ASSEMBLER=$PREFIX/bin/$TARGET-as$EXT
LINKER=$PREFIX/bin/$TARGET-ld$EXT
echo "ASSEMBLER=$ASSEMBLER" >> $TIMEFILE
echo "LINKER=$LINKER" >> $TIMEFILE
else
echo "Unable to find $PREFIX/bin/$TARGET-as$EXT"
exit 1
fi
cd ../..
# ---------------------- Build the bootstrap GCC for building newlib
# We need to build a stripped down GCC configured for the target that
# we will use to build newlib. Once newlib is built, then GCC will be
# rebuilt and will use newlib as the default C library.
echo ==================== BUILDING gcc-$GCC_VER ====================
GCC1_TIME=`date`
cd build
if [ ! -x gcc ]; then
# Configure
mkdir gcc
cd gcc
../../gcc-$GCC_VER/configure --with-newlib --without-headers --target=$TARGET --prefix=$PREFIX --with-as=$ASSEMBLER --with-ld=$LINKER
else
# Already configured, just make it
cd gcc
fi
make all-gcc && make install-gcc
cd ../..
echo ==================== BUILDING Newlib-$NEWLIB_VER ====================
NEWLIB_TIME=`date`
cd build
if [ ! -x newlib ]; then
# Configure
mkdir newlib
cd newlib
../../newlib-$NEWLIB_VER/configure --target=$TARGET --prefix=$PREFIX
else
# Already configured, just (re)make it
cd newlib
fi
make && make install
cd ../..
echo ==================== BUILDING gcc-$GCC_VER ====================
GCC2_TIME=`date`
cd build
# gcc folder should already be there from the previous build. Reconfigure
# and rebuild with the custom newlib support
if [ ! -x gcc ]; then
mkdir gcc
cd gcc
else
cd gcc
fi
../../gcc-$GCC_VER/configure --with-newlib --enable-threads --target=$TARGET --prefix=$PREFIX --with-as=$ASSEMBLER --with-ld=$LINKER
make all-gcc && make install-gcc
# Check that the compiler is installed correctly in $PREFIX/bin
if [ -x $PREFIX/bin/$TARGET-gcc$EXT ]
then
echo "==================== GCC build complete ========================"
COMPILER=$PREFIX/bin/$TARGET-gcc$EXT
echo "COMPILER=$COMPILER" >> $TIMEFILE
else
echo "==================== ERROR building GCC ========================"
echo "COMPILER=" >> $TIMEFILE
exit 1
fi
cd ../..
echo " " >> $TIMEFILE
echo "------------------------------------------------" >> $TIMEFILE
# Test the toolchain by creating a small file and compiling it.
echo " "
echo "------------------------- TESTING THE TOOLS -------------------------"
echo " "
if [ ! -x test ]; then
mkdir test
fi
cd test
echo " " > test.c
echo "#include <stdio.h>" >> test.c
echo " " >> test.c
echo "void _start(void) { foo(5); };" >> test.c
echo " " >> test.c
echo "int foo( int x )" >> test.c
echo "{" >> test.c
echo " return x+1;" >> test.c
echo "}" >> test.c
# $PREFIX/bin should be in the path to allow this to execute
# - Just compile for now.
echo ASSEMBLER=$ASSEMBLER > output.txt
echo LINKER=$LINKER >> output.txt
echo COMPILER=$COMPILER >> output.txt
echo INCLUDE=$INCLUDE >> output.txt
echo "------------------------------------------------------" >> output.txt
$COMPILER -I$INCLUDE -c -o test.o test.c >> output.txt
if [ ! -x test.o ]; then
# Error! unable to build test code.
echo "------------ Test Build Failed ----------------------"
echo
cat output.txt
else
echo "------------ Test Build Successful ------------------"
rm test.o test.c output.txt
fi
cd ..
# ----------------------- Done!
echo "------------------------------------------------" >> $TIMEFILE
echo " " >> $TIMEFILE
echo Start times >> $TIMEFILE
echo "Unpack..........$UNPACKING_TIME" >> $TIMEFILE
echo "Binutils........$BINUTILS_TIME" >> $TIMEFILE
echo "Pre-GCC.........$GCC1_TIME" >> $TIMEFILE
echo "Newlib..........$NEWLIB_TIME" >> $TIMEFILE
echo "GCC.............$GCC2_TIME" >> $TIMEFILE
echo -n "Finished........" >> $TIMEFILE
date >> $TIMEFILE
cat $TIMEFILE
echo buildit.sh ended
<< Home