#!/bin/bash # # We force bash, because csh/ash # may not work with the variables # # make.sh: All-in-One Single-Pass Cross-Compiler Build Script Doohickey # # (c) 2000-2003, David A. Desrosiers # hacker at gnu dash designs dot com # ################## # # License # ################## # # This script is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the Free # Software Foundation; either version 2 of the License, or (at your option) # any later version. # # This script is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for # more details. # # You should have received a copy of the GNU General Public License along # with this program; if not, write to the Free Software Foundation, Inc., 59 # Temple Place - Suite 330, Boston, MA 02111-1307, USA. # ################### # # Portions of this script were taken from a similar script I found on the # web awhile back, but have long since forgotten where, author unknown. If # anybody knows, please email me so I can give proper credit. # # This script can be run as a normal user (or root if you want to install # the packages to a non-standard path), and will completely build a # cross-development toolchain, plus kernel (alternately), for *-linux in # general. The target arm-linux was used in testing, though any other # architecture is possible here, and the basic flow holds for building any # other cross-build environment. # # This script only very weakly depends on the host system, as long as it has # a halfway-working gcc and gmake or make. This script was tested on # i686-unknown-linux-gnu, Sparc E3500, kernel-2.4.20-pre10, gcc-3.2.1, make # and gmake-3.80, glibc-2.3 # # Many different HOWTO documents were read, digested, tested, corrected, and # discarded in the process of developing this script. You can find some of # them by using your favorite search engine, or follow the following links # to see some good examples: # # http://www.armlinux.org/docs/toolchain/toolchHOWTO/x183.html # http://handhelds.org/z/wiki/HOWTO%20Build%20a%20Cross%20Toolchain%20in%20Brief # http://bytesex.org/cross-compiler.html # http://www.objsw.com/CrossGCC/FAQ-4.html # http://www.macbsd.com/macbsd/howto/cc-HOWTO # http://www.xraylith.wisc.edu/~khan/software/gnu-win32/cygwin-cross-howto.txt # http://www.xraylith.wisc.edu/~khan/software/gnu-win32/mingw-cross-howto.txt # http://www.multimania.com/pmandin/en/howto/cross295.html # http://www.delorie.com/howto/djgpp/linux-x-djgpp.html # # After days of frustration following these and similar other documents and # HOWTOs, and asking dozens of people in various irc channels and email, I # got frustrated and decided to start scripting this all out in one fell # swoop. I picked up that old script I had lying around here, and touched it # up quite a bit to get it working for this process. Originally I was using # it to build prc-tools (cross-gcc for Palm applications), but this is just # as applicable. # # It's purposely over-commented, because I already get too much email, but # if you find a bug, I DO want to hear about it. Send me patches, or bug # reports as necessary. # ################## # # ChangeLog # ################## # # 2002-12-9 David A. Desrosiers # # * After almost a year away from this, I've updated it to handle # fetching, gdb cross builds, and the latest glibc, binutils, gcc, as # well as cleaned up a few other bugs. Patches are welcome! # # 2001-12-31 David A. Desrosiers # # * Wow, what a bonehead. I left one space between each var, not allowed. # Fixed. # # 2001-08-29 David A. Desrosiers # # * Oops! My bad, fixed a bug in the indenting of the declared variables. # I'm so used to making things line up in perl, that I forgot you can't # do that in shell. Fixed. # # 2001-08-29 David A. Desrosiers # # * From a Linuxworld BOF on Embedded Linux, I have some more ideas for # this to make it a bit more robust, smarter, and fault-tolerant. # Anyone who cares to update this please let me know, and send me a # patch! # # 2001-06-24 David A. Desrosiers # # * The script needs to be a bit smarter than it is at the moment. When # you abort the script and run it again, it should clean up and # restart, instead of error out. # ############################################################################# set -e ############################################################################# # # Set some basic variables here for architecture, path, install prefix and # others. # # HOST = what architecture is THIS build process running # on? We use config.guess in this case, because it is the most # accurate. The latest copy of this can be found at the following # url: ftp://ftp.gnu.org/pub/gnu/config/ # ############################################################################# ARCH=arm THISDIR=/tmp/cross WORKROOT=/tmp/test WORKDIR=$WORKROOT/work BUILD=$WORKROOT/build TARGET=$ARCH-linux PREFIX=/usr/local/cross KERNELHOME=/usr/local/arm HEADERS=$KERNELHOME/include MD5FILE=$THISDIR/source.md5 PATH=$PREFIX/bin:$PATH source funcs.cf wherebe MD5SUM md5sum wherebe TAR tar wherebe GUNZIP gunzip wherebe WGET wget wherebe MKDIR mkdir wherebe RM rm wherebe MAKE make echo "" if [ ! -d $WORKROOT ]; then echo "FATAL ERROR: WORKROOT ($WORKROOT) did not exist, exiting now.." echo "" echo "Please make sure to set the WORKROOT value properly in the script The other" echo "necessary directories will be created automagically if they do not already" echo "exist. All of the building will be done inside the directory you set here." echo "" exit fi if [ ! -d $WORKDIR ]; then echo "ERROR: BUILD ($BUILD) did not exist.. creating now." $MKDIR $BUILD echo "ERROR: WORKDIR ($WORKDIR) did not exist.. creating now." $MKDIR $WORKDIR echo "" if [ ! -f "config.guess" ]; then echo "Fetching config.guess from gnu.org into $WORKDIR" $WGET ftp://ftp.gnu.org/pub/gnu/config/config.guess &>/dev/null fi cp config.guess $WORKDIR HOST=`sh $WORKDIR/config.guess` echo "HOST is now set to set to $HOST" else HOST=`sh $WORKDIR/config.guess` fi if [ -d $WORKROOT ]; then if [ -d $WORKDIR ]; then if [ -d $BUILD ]; then if [ -d $WORKDIR ]; then if [ -f $WORKDIR/config.guess ]; then HOST=`sh $WORKDIR/config.guess` fi fi # end $WORKDIR fi # end $BUILD fi # end $WORKDIR fi # end $WORKROOT ############################################################################# # # Set your versions here, without this, everything below will fail in # wonderfully-undesirable ways. This is basically the version number # directly from the tarball itself, minus the '.tar.gz' part, so if # you have 'gcc-3.2.1.tar.gz', you'd put 'gcc-3.2.1' for GCC below. # # Sources: # # Binutils.......: ftp://ftp.gnu.org/pub/gnu/binutils/binutils-2.13.1.tar.gz # gcc............: ftp://ftp.gnu.org/pub/gnu/gcc/gcc-3.2.1.tar.gz # glibc..........: ftp://ftp.gnu.org/pub/gnu/glibc/glibc-2.3.tar.gz # linuxthreads...: ftp://ftp.gnu.org/pub/gnu/glibc/glibc-linuxthreads-2.3.1.tar.gz # gdb............: ftp://ftp.gnu.org/pub/gnu/gdb/gdb-5.2.tar.gz # config.guess...: ftp://ftp.gnu.org/pub/gnu/config/config.guess # ############################################################################# BINUTILS=binutils-2.13.1 GCC=gcc-3.2.1 LINUXTHREADS=glibc-linuxthreads-2.3.1 GLIBC=glibc-2.3 GDB=gdb-5.2 # Yes, I'm sure I could compress this into a function also, but # "It Works(tm)", patches are welcome. ################################################################ # # GNU Binary Utilities # ################################################################ if [ ! -f $BINUTILS.tar.gz ]; then $WGET ftp://ftp.gnu.org/pub/gnu/binutils/binutils-2.13.1.tar.gz echo "Fetching GNU Binary Utilities ($BINUTILS) into $WORKROOT" else if [ -f $BINUTILS.tar.gz ]; then if [ ! -d $WORKDIR/$BINUTILS ]; then echo "" if [ ! -z "$BINUTILS.tar.gz" ]; then md5check $BINUTILS.tar.gz fi else MD5_TMP=`grep $BINUTILS.tar.gz ${MD5FILE}` BINDESC=`echo $MD5_TMP | awk '{print $3, $4, $5}'` echo "$BINDESC source tree found.. no need to unpack" fi fi fi ################################################################ # # GNU Compiler Collection # ################################################################ if [ ! -f $GCC.tar.gz ]; then $WGET ftp://ftp.gnu.org/pub/gnu/gcc/gcc-3.2.1.tar.gz echo "Fetching GNU Compiler Collection ($GCC) into $WORKROOT" else if [ -f $GCC.tar.gz ]; then if [ ! -d $WORKDIR/$GCC ]; then echo "" if [ ! -z "$GCC.tar.gz" ]; then md5check $GCC.tar.gz fi else MD5_TMP=`grep $GCC.tar.gz ${MD5FILE}` BINDESC=`echo $MD5_TMP | awk '{print $3, $4, $5}'` echo "$BINDESC source tree found.. no need to unpack" fi fi fi ################################################################ # # GNU Libraries # ################################################################ if [ ! -f $GLIBC.tar.gz ]; then $WGET ftp://ftp.gnu.org/pub/gnu/glibc/glibc-2.3.tar.gz echo "Fetching GNU Libraries ($GLIBC) into $WORKROOT" else if [ -f $GLIBC.tar.gz ]; then if [ ! -d $WORKDIR/$GLIBC ]; then echo "" if [ ! -z "$GLIBC.tar.gz" ]; then md5check $GLIBC.tar.gz fi else MD5_TMP=`grep $GLIBC.tar.gz ${MD5FILE}` BINDESC=`echo $MD5_TMP | awk '{print $3, $4, $5}'` echo "$BINDESC source tree found.. no need to unpack" fi fi fi ################################################################ # # GNU Linux Threads Package # ################################################################ if [ ! -f $LINUXTHREADS.tar.gz ]; then $WGET ftp://ftp.gnu.org/pub/gnu/glibc/glibc-linuxthreads-2.3.1.tar.gz echo "Fetching GNU Linux Threads ($LINUXTHREADS) into $WORKROOT" else if [ -f $LINUXTHREADS.tar.gz ]; then if [ ! -d $WORKDIR/$LINUXTHREADS ]; then echo "" if [ ! -z "$LINUXTHREADS.tar.gz" ]; then md5check $LINUXTHREADS.tar.gz mv $WORKDIR/linuxthreads $WORKDIR/$GLIBC mv $WORKDIR/linuxthreads_db $WORKDIR/$GLIBC fi else MD5_TMP=`grep $LINUXTHREADS.tar.gz ${MD5FILE}` BINDESC=`echo $MD5_TMP | awk '{print $3, $4, $5}'` echo "$BINDESC source tree found.. no need to unpack" fi fi fi ln -s $WORKDIR/linuxthreads $WORKDIR/$GLIBC/linuxthreads ################################################################ # # GNU Debugger # ################################################################ if [ ! -f $GDB.tar.gz ]; then $WGET ftp://ftp.gnu.org/pub/gnu/gdb/gdb-5.2.tar.gz echo "Fetching GNU Debugger ($GDB) into $WORKROOT" else if [ -f $GDB.tar.gz ]; then if [ ! -d $WORKDIR/$GDB ]; then echo "" if [ ! -z "$GDB.tar.gz" ]; then md5check $GDB.tar.gz fi else MD5_TMP=`grep $GDB.tar.gz ${MD5FILE}` BINDESC=`echo $MD5_TMP | awk '{print $3, $4, $5}'` echo "$BINDESC source tree found.. no need to unpack" fi fi echo "" fi echo "Summary" echo "----------------------." echo "Binutils version......: $BINUTILS" echo "GCC version...........: $GCC" echo "GNU Libc version......: $GLIBC" echo "GNU Debugger version..: $GDB" echo "Work root.............: $WORKROOT" echo "Pristine directory....: $WORKDIR" echo "Build directory.......: $BUILD" echo "Work directory........: $WORKDIR" echo "Building on...........: $HOST" echo "Target architecture...: $TARGET" echo "Installation prefix...: $PREFIX" echo "" echo "Please review the above, and make sure it is correct. If not, hit ^C to Quit" echo "and correct the errors, or wait to continue onto the build process.. This" echo "build will consume rougly 1,020 megabytes of disk space, and take quite" echo "awhile. You might want to go grab a movie and wait until it completes.." echo "" echo "Pausing for 30 seconds.." # pause 30 ############################################################################# # # configure, build, and install binutils # ############################################################################# echo "#################################################" echo "### building $BINUTILS"; date echo "#################################################" cd $BUILD if [ ! -d $BINUTILS-$ARCH ]; then $MKDIR $BINUTILS-$ARCH else if [ -f $BINUTILS-$ARCH/config.cache ]; then $RM -Rf $BINUTILS-$ARCH/* fi fi cd $BINUTILS-$ARCH $WORKDIR/$BINUTILS/configure --prefix=$PREFIX --target=$TARGET --with-headers=$HEADERS $MAKE echo "Installing GNU Binary Utilities ($BINUTILS) into $PREFIX" $MAKE install ############################################################################# # # configure the kernel for the target architecture # ############################################################################# # echo "#################################################" # echo "### configuring kernel for $TARGET-linux"; date # echo "#################################################" # cd $KERNELHOME # Currently commented out while testing # make mrproper # make oldconfig # $PREFIX/$TARGET/include was created by the install of binutils Should we # "cp -a" instead of "ln -s"? certainly not now, because it doesn't include # version.h yet. # # gcc config (coming up) will look for $PREFIX/$TARGET/sys-include/limits.h, # to decide whether or not to chain its limits.h via #include_next. We need # that test to succeed. # #( cd $PREFIX/$TARGET # $MKDIR -p include # ln -s include sys-include # cd include # ln -s $KERNELHOME/include/asm-$ARCH asm # ln -s $KERNELHOME/include/linux linux #) ############################################################################# # # configure and build the first pass of gcc, we will need two of these. The # first one is built without threads or glibc support. It is then used to # build glibc itself, then gcc is built a second time, but this time with # glibc and thread support. # ############################################################################# echo "#################################################" echo "### configuring $GCC without glib"; date echo "#################################################" # consider using a path such as $GCC-$ARCH-nolibc, which should be totally # separate from the second build directory and structure. Not necessary, # just being anal. ############################################################################# # patch gcc/Make-target and gcc/Makefile for the first compile phase, that # happens without use of glibc. The Makefiles really ought to leave a # better hook for this step. I tried overriding the variables from the # command line, but they don't propagate to make in the gcc subdir. ############################################################################# cd $WORKDIR/$GCC perl -pi -e 's/^(TARGET_LIBGCC2_CFLAGS.*)/$1 -Dinhibit_libc -D__gthr_posix_h/' gcc/config/arm/t-linux echo 'T_CFLAGS = -Dinhibit_libc -D__gthr_posix_h' >> gcc/config/arm/t-linux cd $BUILD if [ ! -d $GCC-$ARCH ]; then $MKDIR $GCC-$ARCH else if [ -f $GCC-$ARCH/config.cache ]; then $RM -Rf $GCC-$ARCH/* fi fi cd $GCC-$ARCH $WORKDIR/$GCC/configure --target=$TARGET --prefix=$PREFIX --enable-languages=c --disable-threads --disable-shared --enable-static --with-inhibit-libc --with-headers=$HEADERS --with-cpu=strongarm110 --without-fp --with-softfloat-support=internal --with-newlib $MAKE ############################################################################# # # Q: Why do we get... # # checking whether the C compiler (/src/compiling/cross/build/gcc-2.95.3-arm/gcc/xgcc -B/src/compiling/cross/build/gcc-2.95.3-arm/gcc/ -B/usr/local/cross/arm-linux/bin/ -g -O2 ) works... no # configure: error: installation or configuration problem: C compiler cannot create executables. # # ...near the end of that last "make"? # # A: ld: cannot open crt1.o: No such file or directory # # Check the config.log in the $GCC/gcc directory for the exact error, it # should be obvious and will be one of two things, either a missing # crt1.o (or a path which it searched for was wrong), or missing headers # (again, a broken path). # ############################################################################# $MAKE install ############################################################################# # # Actually go through the steps and build the linux kernel for the target # architecture, using the configured sources built several steps up # ############################################################################# # # See below: This has to happen before glibc build, and therefore also # before the second stage of the gcc build. # echo "#################################################" # echo "### building the linux kernel now"; date # echo "#################################################" # cd $KERNELHOME # make dep # make zImage ############################################################################# # # configure, build, and install glibc +crypt +linuxthreads # # If we're using glibc 2.1.x or earlier, you will need to add 'crypt' to the # enable-add-ons line. Since we're using 2.2.3 in this script, and crypt is # now part of glibc, we no longer need to statically declare it (and doing # so will cause ./configure to throw an error) # ############################################################################# echo "#################################################" echo "### building $GLIBC now"; date echo "#################################################" cd $WORKDIR/$GLIBC perl -pi -e 's/i386/arm*)\n\tlibc_cv_gcc_unwind_find_fde=yes\n\tarch_minimum_kernel=2.0.10\n\t;;\n i386/' sysdeps/unix/sysv/linux/configure cd $BUILD if [ ! -d $GLIBC-$ARCH ]; then $MKDIR $GLIBC-$ARCH else if [ -f $GLIBC-$ARCH/config.cache ]; then $RM -Rf $GLIBC-$ARCH/* fi fi cd $GLIBC-$ARCH # The following step needs to find , so it has to happen # after a real build of the kernel. Or, as the glibc FAQ 1.8 suggests, # after `make include/linux/version.h'. CC=$TARGET-gcc $WORKDIR/$GLIBC/configure --host=$HOST --build=$HOST --prefix=$PREFIX/$TARGET --with-headers=$HEADERS --enable-add-ons $MAKE exit $MAKE install ############################################################################# # # Now we can go back and re-build gcc with glibc, g++, and threads support # ############################################################################# echo "#################################################" echo "### building $GCC second pass"; date echo "#################################################" cd $BUILD/$GCC-$ARCH $WORKDIR/$GCC/configure --target=$TARGET --prefix=$PREFIX --enable-languages=c,c++ --with-headers=$HEADERS --with-cpu=strongarm110 $MAKE clean $MAKE $MAKE install echo "#################################################" echo "### DONE! Congratulations!!!"; date echo "#################################################" ##### # EOT # David A. Desrosiers