How hard is it to build your own toolchain?
To build a toolchain is not that hard, but the tricky part starts when you have to prove that it is working and to find out what flags you need to use to make sure that it is optimal for your platform. Therefor most users take the easy way (and frankly the most sensible route), and download a pre fixed toolchain like this one from CodeSourcery (Sourcery G++ Lite for ARM EABI). But this is described on the next page called "CodeSourcery gcc".
But since that is not as much fun as doing it your self, and getting some gray hair, this is why I created this page.
First out it is good to know that this guide is quite close to that project so you could probably use a lot of the documentation that exists there and just apply it here, http://www.codesourcery.com/sgpp/lite/arm/portal/release1033.
The basic prototype for this guide is more or less what those guys did, and described at this pages:
But I had to improvise and add some patches to get it to work, and I also focused on using versions:
Then I created some simple scripts to the work. The scripts just goes from top to bottom, and if anything fails it stops and you have to fix the problem manually and restart again. When you read the script this break function is called did_it_work, and more or less just checks what the last command returned as exit status. That is why this script is filled with those did_it_work lines.
To make the scripts more available I put them into a github repo, so let's install some git sw, clone that repo and get going.
sudo aptitude install git-core git-doc git-gui gitk mkdir -p ~/stm32/ cd ~/stm32/ git clone git://github.com/jsiei97/FunTechCortexMX_gcc.git FunTechCortexMX_gcc cd FunTechCortexMX_gcc
Then we follow the instructions in the README file.
chmod 755 setup.sh ./setup.sh
But before you execute this script, make sure that you take a couple of minutes and read what it is about to do with your pc since it is never a good idea to execute random scripts you find on the internet without understanding what they do.
After this point I will show a snapshot in time from the github repo, so the repo could have been improved. So please use the github one when you build.
But let's have a look at what is in there. The first one is setup.sh, and there is not much fun here. It just calls install.sh and stores a log file.
Filename: setup.sh
#!/bin/bash source include.sh date=`date +"%F_%H%M%S"` chmod 755 *.sh did_it_work $? ./install.sh 2>&1 | tee log_stm32_build_$date.log
install.sh will then call all of the other scripts one by one.
Filename: install.sh
#!/bin/bash source include.sh echo "Install some packages..." ./solve_dependencies.sh did_it_work $? echo "Create the work dirs" ./create_dirs.sh did_it_work $? echo "Build binutils" ./build_00_binutils.sh did_it_work $? echo "Build gcc and newlib" ./build_01_gcc_newlib.sh did_it_work $? echo "Build Insight" ./build_02_insight.sh did_it_work $? echo "Build GDB" ./build_03_gdb.sh did_it_work $? echo "Modify .bashrc" echo "Add a file to modify the PATH..." ./add_rc_files.sh did_it_work $? echo "Done:"$0 exit 0
But at the top of all the files we include always include a script called include.sh. And this is where we store the installation paths, and other things that shall be available from all the other scripts.
Filename: include.sh
#!/bin/bash function did_it_work { code=$1 if [ ! $code = 0 ] then echo "Error failure: code $code " exit 1 fi } stm_dir=~/stm32/ stm_dir_bin=$stm_dir"/bin" stm_dir_tools=$stm_dir"/stm32-tools" stm_dir_install=/usr/local/stm32 export TOOLPATH_STM32=$stm_dir_install export PATH=$TOOLPATH_STM32/bin:$PATH export PARALLEL=-j`getconf _NPROCESSORS_ONLN`
Then there is two scripts that will install some packages that the installation depends on, and create the dirs where we install the stuff. Those scripts are also the only scripts that call sudo, so if you are doing this on a pc where you don't have the rights to run sudo this is the place to look for alternative solutions.
Filename: solve_dependencies.sh
#!/bin/bash source include.sh echo "Install some depends (sudo may ask for your passwd)" sudo aptitude install build-essential flex bison \ libgmp3-dev libmpfr-dev autoconf \ texinfo libncurses5-dev libexpat1 libexpat1-dev \ tk tk8.4 tk8.4-dev did_it_work $? echo "Done:"$0 exit 0
Filename: create_dirs.sh
#!/bin/bash source include.sh echo "Dirs" echo " work = "$stm_dir_tools echo " install = "$stm_dir_install echo "" sudo mkdir -p $stm_dir_install did_it_work $? sudo chown $USER.users $stm_dir_install did_it_work $? mkdir -p $stm_dir_bin did_it_work $? mkdir -p $stm_dir_tools did_it_work $? echo "Done:"$0 exit 0
And finally we start to build binutils, gcc and gdb.
Filename: build_00_binutils.sh
#!/bin/bash source include.sh arch_url=http://ftp.gnu.org/gnu/binutils/binutils-2.20.tar.bz2 arch_dir=binutils-2.20 arch_name=binutils-2.20.tar.bz2 cd $stm_dir_tools did_it_work $? if [ -f $arch_name ]; then echo file exists - $arch_name else wget $arch_url did_it_work $? fi if [ -d $arch_dir ]; then echo old dir exists - rm -rf $arch_dir rm -rf $arch_dir did_it_work $? fi tar -xvjf $arch_name did_it_work $? #Get patch/patches... patch_file=binutils-2.20_tc-arm.c.patch if [ -f $patch_file ]; then echo file exists - $patch_file else wget http://fun-tech.se/stm32/gcc/binutils-2.20_tc-arm.c.patch did_it_work $? fi patch $arch_dir/gas/config/tc-arm.c $patch_file did_it_work $? cd $arch_dir did_it_work $? mkdir build did_it_work $? cd build did_it_work $? ../configure --target=arm-none-eabi \ --prefix=$TOOLPATH_STM32 \ --enable-interwork \ --enable-multilib \ --with-gnu-as \ --with-gnu-ld \ --disable-nls did_it_work $? make $PARALLEL did_it_work $? make install did_it_work $? echo "Done:"$0 exit 0
Filename: build_01_gcc_newlib.sh
#!/bin/bash source include.sh ################# ### GCC ######### ################# arch_url=ftp://ftp.sunet.se/pub/gnu/gcc/releases/gcc-4.4.4/gcc-4.4.4.tar.bz2 arch_dir=gcc-4.4.4 arch_name=gcc-4.4.4.tar.bz2 cd $stm_dir_tools did_it_work $? if [ -f $arch_name ]; then echo file exists - $arch_name else wget $arch_url did_it_work $? fi if [ -d $arch_dir ]; then echo old dir exists - rm -rf $arch_dir rm -rf $arch_dir did_it_work $? fi tar -xvjf $arch_name did_it_work $? cd $arch_dir did_it_work $? mkdir build did_it_work $? cd build did_it_work $? ../configure --target=arm-none-eabi \ --prefix=$TOOLPATH_STM32 \ --enable-interwork \ --enable-multilib \ --enable-languages="c,c++" \ --with-newlib \ --without-headers \ --disable-shared \ --with-gnu-as \ --with-float=soft \ --with-cpu=cortex-m3 \ --with-tune=cortex-m3 \ --with-mode=thumb \ --disable-libssp \ --with-gnu-ld did_it_work $? make $PARALLEL all-gcc did_it_work $? make install-gcc did_it_work $? ################# ## NewLib ####### ################# arch_url=ftp://sources.redhat.com/pub/newlib/newlib-1.18.0.tar.gz arch_dir=newlib-1.18.0 arch_name=newlib-1.18.0.tar.gz cd $stm_dir_tools did_it_work $? if [ -f $arch_name ]; then echo file exists - $arch_name else wget $arch_url did_it_work $? fi if [ -d $arch_dir ]; then echo old dir exists - rm -rf $arch_dir rm -rf $arch_dir did_it_work $? fi tar -xvzf $arch_name did_it_work $? cd $arch_dir did_it_work $? mkdir build did_it_work $? cd build did_it_work $? ../configure --target=arm-none-eabi \ --prefix=$TOOLPATH_STM32 \ --enable-interwork \ --disable-newlib-supplied-syscalls \ --with-gnu-ld \ --with-gnu-as \ --disable-shared did_it_work $? # http://gcc.gnu.org/gcc-4.4/changes.html # GCC now supports the VFPv3 variant with 16 double-precision # registers with -mfpu=vfpv3-d16. The option -mfpu=vfp3 has been # renamed to -mfpu=vfpv3. # GCC now supports the -mfix-cortex-m3-ldrd option to work around # an erratum on Cortex-M3 processors. # http://www.codesourcery.com/sgpp/lite/arm/portal/kbentry27 # Use the compiler options -mfpu=vfp -mfloat-abi=softfp to enable VFP instructions. # If you have a VFPv3 target you may use -mfpu=vfp3 -mfloat-abi=softfp i # to enable VFPv3 instructions. # Using -mfloat-abi=hard generates code that is not ABI-compatible with # other floating-point options. #-mabi=aapcs \ make $PARALLEL CFLAGS_FOR_TARGET="-ffunction-sections \ -fdata-sections \ -DPREFER_SIZE_OVER_SPEED \ -D__OPTIMIZE_SIZE__ \ -Os \ -fomit-frame-pointer \ -mcpu=cortex-m3 \ -mthumb \ -mfix-cortex-m3-ldrd \ -mfloat-abi=softfp \ -D__thumb2__ \ -D__BUFSIZ__=256" \ CCASFLAGS="-mcpu=cortex-m3 \ -mthumb \ -mfix-cortex-m3-ldrd \ -D__thumb2__" did_it_work $? make install did_it_work $? ################# ### More GCC #### ################# cd $stm_dir_tools did_it_work $? cd gcc-4.4.4/build did_it_work $? make $PARALLEL CFLAGS="-mcpu=cortex-m3 -mthumb" \ CXXFLAGS="-mcpu=cortex-m3 -mthumb" \ LIBCXXFLAGS="-mcpu=cortex-m3 -mthumb" \ all did_it_work $? make install did_it_work $? echo "Done:"$0 exit 0
Filename: build_02_insight.sh
#!/bin/bash source include.sh ################# ### insight ##### ################# arch_url=ftp://sourceware.org/pub/insight/releases/insight-6.8-1.tar.bz2 arch_dir=insight-6.8-1 arch_name=insight-6.8-1.tar.bz2 gdb_ver=6.8 cd $stm_dir_tools did_it_work $? if [ -f $arch_name ]; then echo file exists - $arch_name else wget $arch_url did_it_work $? fi if [ -d $arch_dir ]; then echo old dir exists - rm -rf $arch_dir rm -rf $arch_dir did_it_work $? fi tar -xvjf $arch_name did_it_work $? cd $arch_dir did_it_work $? mkdir build did_it_work $? cd build did_it_work $? ../configure --target=arm-none-eabi \ --prefix=$TOOLPATH_STM32 \ --enable-languages=c,c++ \ --enable-thumb \ --enable-interwork \ --enable-multilib \ --enable-tui \ --with-newlib \ --disable-werror \ --disable-libada \ --disable-libssp \ --with-expat did_it_work $? make $PARALLEL did_it_work $? make install did_it_work $? cd $TOOLPATH_STM32/bin did_it_work $? mv arm-none-eabi-gdb arm-none-eabi-gdb-$gdb_ver did_it_work $? mv arm-none-eabi-gdbtui arm-none-eabi-gdbtui-$gdb_ver did_it_work $? mv arm-none-eabi-run arm-none-eabi-run-$gdb_ver did_it_work $? echo "Done:"$0 exit 0
Filename: build_03_gdb.sh
#!/bin/bash source include.sh ################# ### gdb ######### ################# arch_url=http://ftp.gnu.org/gnu/gdb/gdb-7.2.tar.bz2 arch_dir=gdb-7.2 arch_name=gdb-7.2.tar.bz2 gdb_ver=7.2 cd $stm_dir_tools did_it_work $? if [ -f $arch_name ]; then echo file exists - $arch_name else wget $arch_url did_it_work $? fi if [ -d $arch_dir ]; then echo old dir exists - rm -rf $arch_dir rm -rf $arch_dir did_it_work $? fi tar -xvjf $arch_name did_it_work $? cd $arch_dir did_it_work $? mkdir build did_it_work $? cd build did_it_work $? ../configure --target=arm-none-eabi \ --prefix=$TOOLPATH_STM32 \ --enable-languages=c,c++ \ --enable-thumb \ --enable-interwork \ --enable-multilib \ --enable-tui \ --with-newlib \ --disable-werror \ --disable-libada \ --disable-libssp did_it_work $? make $PARALLEL did_it_work $? make install did_it_work $? cd $TOOLPATH_STM32/bin did_it_work $? mv arm-none-eabi-gdb arm-none-eabi-gdb-$gdb_ver did_it_work $? mv arm-none-eabi-gdbtui arm-none-eabi-gdbtui-$gdb_ver did_it_work $? mv arm-none-eabi-run arm-none-eabi-run-$gdb_ver did_it_work $? ln -s arm-none-eabi-gdb-$gdb_ver arm-none-eabi-gdb did_it_work $? ln -s arm-none-eabi-gdbtui-$gdb_ver arm-none-eabi-gdbtui did_it_work $? ln -s arm-none-eabi-run-$gdb_ver arm-none-eabi-run did_it_work $? echo "Done:"$0 exit 0
Filename: add_rc_files.sh
#!/bin/bash source include.sh cat >> ~/.bashrc << EOF # STM32 BEGIN #Multi process build export PARALLEL=-j\`getconf _NPROCESSORS_ONLN\` #STM32 gcc... export TOOLPATH_STM32=`echo $stm_dir_install` #export PATH=\${TOOLPATH_STM32}/bin:\$PATH # STM32 END EOF did_it_work $? cat > $stm_dir_bin/stm32_setup.sh << EOF #Autogen do not edit... export PATH=${TOOLPATH_STM32}/bin:\$PATH EOF did_it_work $? echo "Done:"$0 exit 0
That's it.
Since I kind of like vim, I always makes sure that vim is installed, and I also always install some other good dev tools.
sudo aptitude install vim vim-full vim vim-scripts vim-doc vim-gui-common vim-gnome \ exuberant-ctags cscope \ okteta ghex \ meld kompare
The last two is some graphical diff program and those are hard to live without, in Ubuntu 8.04 I use kdiff3 but in Ubuntu 9.04 I mostly use meld instead (but kompare is also nice).
Then you can decide if you always would like to have this toolchain in the path, if so then add this to your ~/.bashrc.
echo '#STM32 gcc...' >> ~/.bashrc echo 'export PATH=${TOOLPATH_STM32}/bin:$PATH' >> ~/.bashrc echo '' >> ~/.bashrc
Otherwise you can add it when you need it by running this.
source ~/stm32/bin/stm32_setup.shFatal error: Uncaught Error: Call to a member function link_ext() on null in /customers/9/b/5/fun-tech.se/httpd.www/stm32/class.page.php:62 Stack trace: #0 /customers/9/b/5/fun-tech.se/httpd.www/stm32/gcc/index.php(227): page->getFoot() #1 {main} thrown in /customers/9/b/5/fun-tech.se/httpd.www/stm32/class.page.php on line 62