This is a worked example of cross-compiling gcc 4.8.3 for AArch64 port on Ubuntu 12.04.3 LTS.
NOTE:
(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 libc.so
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:
Pre-requisites for configuring and building GCC : https://gcc.gnu.org/install/prerequisites.html
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:
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 https://www.gnu.org/software/autoconf/manual/autoconf-2.65/html_node/Specifying-Target-Triplets.html 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 https://gcc.gnu.org/install/configure.html
#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://svn.eglibc.org/trunk 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 libc.so to link with libgcc_s.so
crossbuild/eglibc/build$ $prefix/bin/$target-gcc -nostdlib -nostartfiles -shared -x c /dev/null -o $sysroot/usr/lib/libc.so
#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 libstdc++.so* files also
crossbuild$ cp -d $prefix/$target/lib64/libgcc_s.so* $sysroot/lib64
crossbuild$ cp -d $prefix/$target/lib64/libstdc++.so* $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
i686-pc-linux-gnu
crossbuild$ ./install/bin/aarch64-linux-gnu-gcc -v
Using built-in specs.
COLLECT_GCC=../../install/bin/aarch64-linux-gnu-gcc
COLLECT_LTO_WRAPPER=/home/user1/aarch64-crossbuild-gcc4.8.3/install/libexec/gcc/aarch64-linux-gnu/4.8.3/lto-wrapper
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
Testing:
$ cd ..
$ mkdir aarch64-examples && cd aarch64-examples
aarch64-examples$ vi hello.c
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/ld-linux-aarch64.so.1]
...