Combined tree build of GCC, Binutils and Libraries


, , , , , ,

GCC supports two types of builds: combined-tree and separate-tree.

A combined-tree consists of all the source trees of gcc and binutils/gdb/newlib/pre-requisite libraries. This can be created by simply merging all the source trees in the respective order.

GCC, binutils etc., share the same top-level configure script and Makefile. However, in order to create a combined-tree, one must use sources from the same date, as there are various shared directories (include, libiberty), and they have to be the same. If you try to mix source trees from different dates, such as from different official releases, build may fail. You have been warned.

For a separate-tree build, you build the different components separately.

Our Scope : We will now look at a native combined-tree bootstrap build of gcc, binutils, GMP, MPFR, MPC, ISL, CLOOG on i686-pc-linux-gnu and testing the default testsuite of C,C++ using dejagnu test framework after the successful build.

The source archives used:

GCC 4.8.3 (gcc-4.8.3.tar.bz2), Binutils (binutils-2.24.tar.bz2), GMP (gmp-5.1.3.tar.bz2), MPFR (mpfr-3.1.2.tar.bz2), MPC (mpc-1.0.1.tar.bz2), ISL (isl-0.12.2.tar.bz2), CLOOG(cloog-0.18.1.tar.gz).

Combined-tree build:

Download all the source archives into a directory.

$ mkdir localbuild-gcc-4-8-3

Un-tar all the archives in this directory.

$ cd localbuild-gcc-4-8-3
localbuild-gcc-4-8-3$ tar -jxf gcc-4.8.3.tar.bz2
localbuild-gcc-4-8-3$ tar -jxf binutils-2.24.tar.bz2
localbuild-gcc-4-8-3$ tar -jxf gmp-5.1.3.tar.bz2
localbuild-gcc-4-8-3$ tar -jxf mpfr-3.1.2.tar.bz2
localbuild-gcc-4-8-3$ tar -jxf mpc-1.0.1.tar.bz2
localbuild-gcc-4-8-3$ tar -jxf isl-0.12.2.tar.bz2
localbuild-gcc-4-8-3$ tar -xzf cloog-0.18.1.tar.gz

Create a dir ‘combined’ where symlinks to the source trees to be created

localbuild-gcc-4-8-3$ mkdir combined && cd combined

#Create symlinks to the gcc source tree - Files in the gcc tree are master copy.
#So, maintain the following order without fail.  
localbuild-gcc-4-8-3/combined$ ln -s ../gcc-4.8.3/* .

#Create symlinks to the binutils source tree. Ignore several complaints from ln about existing links
localbuild-gcc-4-8-3/combined$ ln -s ../binutils-2.24/* .

#Create symlinks to GMP,MPFR,MPC,ISL,CLOOG source trees without version numbers in links
localbuild-gcc-4-8-3/combined$ ln -s ../gmp-5.1.3 gmp 
localbuild-gcc-4-8-3/combined$ ln -s ../mpfr-3.1.2 mpfr 
localbuild-gcc-4-8-3/combined$ ln -s ../mpc-1.0.1 mpc 
localbuild-gcc-4-8-3/combined$ ln -s ../isl-0.12.2 isl 
localbuild-gcc-4-8-3/combined$ ln -s ../cloog-0.18.1 cloog 

Combined tree is ready now.

Create a ‘build’ dir outside the combined-tree source. Configure & Build GCC from ‘build’ dir

localbuild-gcc-4-8-3/combined$ cd .. 
localbuild-gcc-4-8-3$ mkdir build && cd build  

#Export build environment variables. For native build, host=build=target

#To know host info, use config.guess script 
localbuild-gcc-4-8-3/build$ ../combined/config.guess

localbuild-gcc-4-8-3/build$ export host=i686-pc-linux-gnu
localbuild-gcc-4-8-3/build$ export build=$host
localbuild-gcc-4-8-3/build$ export target=$host
localbuild-gcc-4-8-3/build$ export prefix=/usr/local/gcc-4-8-3 

#Configure - Enabling 'C','C++' languages
#Configuring combined-tree - Since it includes binutils, --enable-shared NOT to be used. Build fails in stage2 if this option is used. You have been warned.
localbuild-gcc-4-8-3/build$ ../combined/configure --host=$host --build=$build --target=$target --prefix=/usr/local/gcc-4-8-3 --disable-nls --disable-werror --disable-multilib --enable-__cxa_atexit --enable-c99 --enable-long-long --enable-threads=posix --enable-checking=release --enable-libstdcxx-time --enable-languages=c,c++

#Parallel Build
localbuild-gcc-4-8-3/build$ make -j 2

Combined-tree build of gcc,binutils should succeed now.

Testing and Installing
To test the testsuites of C,C++ present in the source tree, dejagnu test framework should be installed.
dejagnu test framework requirements: tcl, expect, dejagnu, autogen

Run the testsuites

#make -j N is for parallel build
#make -k check. This is to instruct - DO NOT stop, even if some errors are encountered during testing.
localbuild-gcc-4-8-3/build$ make -j 2 -k check

#Running the testsuites will take a long time (~2 hrs).

#While running the testsuite, DejaGnu might emit some harmless messages resembling ‘WARNING: Couldn't find the global #config file.’ or ‘WARNING: Couldn't find tool init file’ that can be ignored.

#Install the toolchain
localbuild-gcc-4-8-3/build$ make install 

Test Results:

#To check test results, use 'contrib/test_summary' shell script present in combined-tree.
#This should be run in 'build' dir.
localbuild-gcc-4-8-3/build$ ../combined/contrib/test_summary

All the test results will be displayed on the shell.


Cross-compiling gcc 4.8.3 for AArch64 port


, , , , , ,

This is a worked example of cross-compiling gcc 4.8.3 for AArch64 port on Ubuntu 12.04.3 LTS.


(i) Cross-compiling GCC : Full credit to GRC-IITB Team for the GCC config & build guide. I followed the instructions in this guide and changed a few config & build options where necessary.

(ii) QEMU’s aarch64 system emulation mode : Full credit to Alex for his wonderful and easy to follow article on Running Linux in QEMU’s aarch64 system emulation mode

Building/Cross compiling gcc 4.8.3 for ARM64(AArch64) port on linux:

The outline of cross compiling gcc is:

1. crossgcc1 : Build a stage1 cross compiler with certain facilities disabled

2. Initial Library(EGLIBC): Configure the C library using crossgcc1. Build some
specified C run-time object files, but not rest of the library. Install the
library’s header files and run-time object file, and create dummy

3. crossgcc2: Build a stage2 cross-compiler, using the header files and object
files installed in step 2

4. Final Library: Configure, build and install fresh C library, using crossgcc2

5. crossgcc: Build a full & final cross compiler, based on the C library built in step 4


Pre-requisites for configuring and building GCC :
However, it is recommended to install the latest version of these important libraries in respective order : GMP, MPFR, MPC, ISL, CLooG

To enable C++ language in GCC toolchain, GMP library must be configured as below:

#GMP Library configure options
$ CPPFLAGS=-fexceptions ../configure --enable-cxx  --prefix=/usr/local --build=i686-pc-linux-gnu

Source Tarballs:

Tar File Name Download URL
Latest revision of EGLIBC svn co svn:// eglibc


Setting Up the Environment for Cross Compilation:

#parent directory for sources and binaries of cross-compiler
$ mkdir crossbuild 

$ cd crossbuild

#Downloaded source tarballs should be put in respective folders
$ mkdir gcc binutils eglibc

#cross-compiler toolchain will be installed in this dir
$ mkdir install

#complete EGLIBC, header files, library files and startup C files for target will be installed in this dir
$ mkdir sysroot

#My PC linux version info:
$ uname -a
Linux linux 3.8.0-29-generic #42~precise1-Ubuntu SMP Wed Aug 14 15:31:16 UTC 2013 i686 i686 i386 GNU/Linux

#Set the environment variables to generalize the later steps for cross build:

#<path to crossbuild>/install
$ export prefix=/home/user1/crossbuild/install/

#<path to crossbuild>/sysroot
$ export sysroot=/home/user1/crossbuild/sysroot/

# Refer for more info.

#This is my host info. Specify your host info
$ export host=i686-pc-linux-gnu

#host = build in our case for cross compiling.
$ export build=i686-pc-linux-gnu

#target is same for us, since our goal is to cross compile for aarch64 target.
$ export target=aarch64-linux-gnu

#architecture target info required to build linux kernel.
$ export linuxarch=arm64

$ export PATH=$prefix/bin:$PATH

#Including '/usr/local/lib' in library search path since libraries GMP,MPFR,MPC etc., are installed here.
$ export LD_LIBRARY_PATH=/usr/local/lib

1.1> Building Binutils for AArch64 port

#Start at parent directory 'crossbuild'

crossbuild$ cd binutils

crossbuild/binutils$ tar -jxf binutils-2.24.tar.bz2

crossbuild/binutils$ mkdir build && cd build

crossbuild/binutils/build$ ../binutils-2.24/configure --target=$target --prefix=$prefix --with-sysroot=$sysroot

#parallel build --> make -j n --> Here, n is number of processor cores on your system
crossbuild/binutils/build$ make -j 2

crossbuild/binutils/build$ make install

#Move to parent directory 'crossbuild'
crossbuild/binutils/build$ cd ../../

1.2> cross compile – gcc stage1

crossbuild$ cd gcc

crossbuild/gcc$ tar -jxf gcc-4.8.3.tar.bz2

crossbuild/gcc$ mkdir build && cd build

# --with-gmp, --with-mpfr options etc., are required if the corresponding libraries are not in the library search path
# On my system, I have installed all these libraries in /usr/local. For more info, refer

#Enable 'C' language only in stage1
crossbuild/gcc/build$ ../gcc-4.8.3/configure --target=$target --prefix=$prefix --with-gmp=/usr/local --with-mpfr=/usr/local --with-mpc=/usr/local --with-isl=/usr/local --with-cloog=/usr/local --without-headers --with-newlib --disable-shared --disable-threads --disable-libssp --disable-libgomp --disable-libmudflap --disable-multilib --disable-libatomic --disable-libitm --disable-libsanitizer --disable-libquadmath --disable-target-libiberty --enable-languages=c

#Install gcc in the install folder:

crossbuild/gcc/build$ PATH=$prefix/bin:$PATH make all-gcc -j 2

crossbuild/gcc/build$ PATH=$prefix/bin:$PATH make install-gcc

#Move to parent directory 'crossbuild'
crossbuild/gcc/build$ cd ../../

2.1> Install Linux Kernel Headers

#Place 'linux-3.14.6.tar.xz' package in 'crossbuild' directory

crossbuild$ tar -xf linux-3.14.6.tar.xz

crossbuild$ cd linux-3.14.6

#Install Linux Kernel headers into sysroot directory
crossbuild/linux-3.14.6$ PATH=$prefix/bin:$PATH make headers_install CROSS_COMPILE=$target- INSTALL_HDR_PATH=$sysroot/usr ARCH=$linuxarch

#Move to parent directory 'crossbuild'
crossbuild/linux-3.14.6$ cd ../ 

2.2> Installing EGLIBC Headers and Preliminary Objects

crossbuild$ cd eglibc

#check out trunk from EGLIBC svn directory

crossbuild/eglibc$ svn co svn:// eglibc

crossbuild/eglibc$ mkdir build && cd build

# libc_cv_forced_unwind=yes, libc_cv_c_cleanup=yes, libc_cv_ctors_header=yes are passed to configure script so that the tests for force-unwind support is skipped,
# C cleanup handling support and gcc constructor support are configured respectively.

crossbuild/eglibc/build$ BUILD_CC=gcc CC=$prefix/bin/$target-gcc AR=$prefix/bin/$target-ar RANLIB=$prefix/bin/$target-ranlib ../eglibc/libc/configure --prefix=/usr --with-headers=$sysroot/usr/include --build=$build --host=$target --disable-profile --without-gd --without-cvs --enable-add-ons libc_cv_forced_unwind=yes libc_cv_c_cleanup=yes  libc_cv_ctors_header=yes

crossbuild/eglibc/build$ make install-headers install_root=$sysroot install-bootstrap-headers=yes

#Install shared libraries manually

crossbuild/eglibc/build$ mkdir -p $sysroot/usr/lib

crossbuild/eglibc/build$ make csu/subdir_lib

crossbuild/eglibc/build$ cp csu/crt1.o csu/crti.o csu/crtn.o $sysroot/usr/lib

#creating a dummy to link with

crossbuild/eglibc/build$ $prefix/bin/$target-gcc -nostdlib -nostartfiles -shared -x c /dev/null -o $sysroot/usr/lib/

#Move to parent directory 'crossbuild'

crossbuild/eglibc/build$ cd ../../

3> cross compile – gcc stage2

#Change the working directory to build directory inside gcc folder

crossbuild$ cd gcc/build

#Clean the build folder for stage2 build

crossbuild/gcc/build$ rm -rf *

crossbuild/gcc/build$ ../gcc-4.8.3/configure --target=$target --prefix=$prefix --with-sysroot=$sysroot --with-gmp=/usr/local --with-mpfr=/usr/local --with-mpc=/usr/local --with-isl=/usr/local --with-cloog=/usr/local --disable-libssp --disable-libgomp --disable-libmudflap --disable-multilib --disable-libatomic --disable-libitm --disable-libsanitizer --disable-libquadmath --disable-target-libiberty --enable-languages=c

#parallel build
crossbuild/gcc/build$ PATH=$prefix/bin:$PATH make -j 2

crossbuild/gcc/build$ PATH=$prefix/bin:$PATH make install

#Move to parent directory 'crossbuild'
crossbuild/gcc/build$ cd ../../ 

4> Building Complete EGLIBC

#Change the working directory to the build directory inside eglibc folder.

crossbuild$ cd eglibc/build

#Clean the build folder for building EGLIBC completely

crossbuild/eglibc/build$ rm -rf *

crossbuild/eglibc/build$ BUILD_CC=gcc CC=$prefix/bin/$target-gcc AR=$prefix/bin/$target-ar RANLIB=$prefix/bin/$target-ranlib ../eglibc/libc/configure --prefix=/usr --with-headers=$sysroot/usr/include --build=$build --host=$target --disable-profile --without-gd --without-cvs --enable-add-ons libc_cv_forced_unwind=yes libc_cv_c_cleanup=yes  libc_cv_ctors_header=yes

crossbuild/eglibc/build$ PATH=$prefix/bin:$PATH make -j 2

#Install the libraries in sysroot

crossbuild/eglibc/build$ PATH=$prefix/bin:$PATH make install install_root=$sysroot

#Move to parent directory 'crossbuild'
crossbuild/eglibc/build$ cd ../../ 

5> Building fully Cross-compiled GCC – stage3

#Change the working directory to build directory inside gcc folder

crossbuild$ cd gcc/build

#Clean the build folder for stage3/final build

crossbuild/gcc/build$ rm -rf *

#Enable languages 'C','C++' in stage3
crossbuild/gcc/build$ ../gcc-4.8.3/configure --target=$target --prefix=$prefix --with-sysroot=$sysroot --with-gmp=/usr/local --with-mpfr=/usr/local --with-mpc=/usr/local --with-isl=/usr/local --with-cloog=/usr/local --disable-nls --disable-static --disable-multilib --enable-shared --enable-__cxa_atexit --enable-c99 --enable-long-long --enable-threads=posix  --enable-checking=release --enable-libstdcxx-time --enable-languages=c,c++

crossbuild/gcc/build$ PATH=$prefix/bin:$PATH make -j 2

#Install the final gcc in the install folder:

crossbuild/gcc/build$ PATH=$prefix/bin:$PATH make install

#Move to parent directory 'crossbuild'
crossbuild/gcc/build$ cd ../../ 

6> Maintaining $sysroot Folder

#Manually copy a few libraries into sysroot. If c++ is enabled, copy the* files also

crossbuild$ cp -d $prefix/$target/lib64/* $sysroot/lib64  

crossbuild$ cp -d $prefix/$target/lib64/* $sysroot/usr/lib64

DONE!!! We now have a cross-compiled toolchain for AArch64 in $prefix. Also, EGLIBC installation in $sysroot.

In $prefix/bin, we should have aarch64-linux-gnu-gcc, aarch64-linux-gnu-as, aarch64-linux-gnu-ld etc.,

BuildStat Info

crossbuild$ ./config.guess

crossbuild$ ./install/bin/aarch64-linux-gnu-gcc -v
Using built-in specs.
Target: aarch64-linux-gnu
Configured with: ../gcc-4.8.3/configure --target=aarch64-linux-gnu --prefix=/home/user1/aarch64-crossbuild-gcc4.8.3/install/ --with-sysroot=/home/user1/aarch64-crossbuild-gcc4.8.3/sysroot/ --with-gmp=/usr/local --with-mpfr=/usr/local --with-mpc=/usr/local --disable-libssp --disable-libgomp --disable-libmudflap --disable-multilib --disable-libatomic --disable-libitm --disable-libsanitizer --disable-libquadmath --disable-target-libiberty --enable-languages=c
Thread model: posix
gcc version 4.8.3 (GCC)

crossbuild$ uname -a 
Linux linux 3.8.0-29-generic #42~precise1-Ubuntu SMP Wed Aug 14 15:31:16 UTC 2013 i686 i686 i386 GNU/Linux 

crossbuild$ dpkg -l libc6
 Name           Version        Description
 libc6          2.15-0ubuntu10 Embedded GNU C Library: Shared libraries


$ cd ..
$ mkdir aarch64-examples && cd aarch64-examples

aarch64-examples$ vi hello.c


#include <stdio.h>

int main(void)
  printf("I successfully built GCC 4.8.3 for ARM 64 port. Welcome All. \n");
  return 0;

#Build an ELF output file

aarch64-examples$ ../crossbuild/install/bin/aarch64-linux-gnu-gcc -o hello hello.c

#Verify - Use readelf to verify whether the executable is indeed for aarch64:

aarch64-examples$ ../crossbuild/install/bin/aarch64-linux-gnu-readelf -hl hello

ELF Header:
  Magic:   7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 
  Class:                             ELF64
  Data:                              2's complement, little endian
  Version:                           1 (current)
  OS/ABI:                            UNIX - System V
  ABI Version:                       0
  Type:                              EXEC (Executable file)
  Machine:                           AArch64
  Version:                           0x1
Program Headers:
     [Requesting program interpreter: /lib/]