Compile a GCC cross compilation tool chain from scratch


In order to avoid coupling with the host compilation system, many SDKs and software that need to be associated with customers will provide their own tool chain or require the customer’s system to meet some tool chain requirements.

The advantages of an independent toolchain are as follows:

one   Don’t worry about the host operating system. Just download toolchain and compile it anytime, anywhere (provided that x86 Linux operating system and windows and arm linux can also be done, but it needs to be done separately. Each additional set will have more maintenance costs).
two   Some compiler patches may not be issued by the operating system. At this time, you need to patch toolchain separately. If you use the host compiler tool, you should consider the compatibility between the patch and the OS itself.
three   At present, the performance of arm is still much worse than that of X86, and the number of internal arm servers is limited, which requires cross compilation on X86 servers.  

1 installation package download

apt-get install libgmp-dev libmpfr-dev libmpc-dev  g++ make gawk

Download the source code package required for compilation (GMP, mpfr and MPC downloaded with apt command can also download the source code package for compilation. In order to save trouble, download the package installed on the source directly above)




If the three components are source code compiled, remember to establish a soft connection under the GCC compilation directory to facilitate the compiler to automatically search. Otherwise, you need to specify the code directory separately

ln -s ../mpfr-4.1.0 mpfr
ln -s ../gmp-6.2.1 gmp
ln -s ../mpc-1.2.1 mpc

Binutils can also get the latest version. It doesn’t matter:


GCC takes the latest versions of 7. X and 9. X Series on Ubuntu 18 and Ubuntu 20, or 11. X. generally speaking, the newer the version, the more powerful the function is:


Download this before the kernel version just to keep it consistent with the version on the host as much as possible, so that the matching relationship between the kernel version and glibc does not need to be explored by yourself. In fact, other matching combinations can also be:


Glibc version is very important. It determines the minimum supported version that the compiled version can run. If the glibc version on the target machine is older than this, it cannot run. 2.23 is the glibc version on Ubuntu 16:


  Why download the XZ version? Because it’s smaller than other versions. 


2 program cross compilation and execution process

The cross compilation tool chain of C and C + + is installed on the host server (assuming that the target system is aarch64). During the compilation process, C or C + + programs will be compiled into assembly temporary files, then compiled into target files by relying on the local assembler as, and then linked with the linker LD to generate executable files, but the format of this executable file is built according to the target system, Therefore, it cannot run on the host server.

The compiled executable files are released by version or copied to the target system downloaded, such as the simplest a.out applet. If the program depends on the C + + library, the C + + standard library will be dynamically linked during loading on the target system, and then the underlying C standard library will be linked (basically all programming languages are based on the C Standard Library), After loading, the kernel scheduler will run the program from the portal.


3 compilation process

3.0 compilation preparation

Unzip the package downloaded above.

Create the compilation target directory.

Many products of Suiyuan start with XXX. Although I don’t know what these three letters are abbreviations, I still use them. In fact, other pathnames can also be used.

If it is compiled directly on the host, try not to use the root user to operate, so as not to hang up the host operating system. If it is compiled in the container, it is optional. The root file system of the container is damaged. It is a big deal to delete the current container and restart one.

The directory should preferably contain GCC version number, glibc version number and target hardware architecture name to avoid guessing after entering:

mkdir -p /opt/xxx/xxx_aarch64_gcc9.4.0_glibc2.23linux 


Update the path global variable to ensure that the tools used in the subsequent compilation process are newly compiled, not on the host:

export PATH=/opt/xxx/xxx_aarch64_gcc9.4.0_glibc2.23linux/bin:$PATH


3.1 compiling binutils

Before formally compiling GCC, you need to compile a tool for compiling GCC, that is, binutils package.

cd binutils-2.28.1

mkdir xxx_aarch64_gcc9.4.0_glibc2.23linux_build

cd xxx_aarch64_gcc9.4.0_glibc2.23linux_build

–Disable multilib means that the compatibility under the same series of hardware architectures does not need to be considered. For example, the target function of aarch64 runs. Do you need to run on aarch32? x86_ Whether 64 programs need to run on i586, etc. generally, there should be no such demand.

../configure --prefix=/opt/xxx/xxx_aarch64_gcc9.4.0_glibc2.23linux --target=aarch64-linux-gnu --disable-multilib

The following number corresponds to the maximum number of processes running the make program according to the number of cores of the server. If the number of cores of the server is very large, it can be configured to be larger. In fact, during the compilation process, due to file dependency, so many processes cannot be run most of the time:

make -j20
make install
cd ../../


3.2 compiling Linux kernel headers

If the Linux kernel version (software and running hardware) of the target machine is exactly the same as the host, you can download it directly with apt command. If it is not exactly the same, you need to recompile the header file.

cd linux-4.15.1/
make ARCH=arm64 INSTALL_HDR_PATH=/opt/xxx/xxx_aarch64_gcc9.4.0_glibc2.23linux/aarch64-linux-gnu/ headers_install
cd ..


The hardware system name in the kernel is different from GCC. For example, aarch64 here is still called arm64 in the Linux kernel. Another parameter points to the directory where the header file is to be installed.

3.3 compiling C / C + + compilers

Compile the compiler first.

cd gcc-9.4.0
mkdir xxx_aarch64_gcc9.4.0_glibc2.23linux_build
cd xxx_aarch64_gcc9.4.0_glibc2.23linux_build
../configure  --prefix=/opt/xxx/xxx_aarch64_gcc9.4.0_glibc2.23linux --target=aarch64-linux-gnu --with-glibc-version=2.23 --enable-languages=c,c++ --disable-multilib  --with-protoc
make -j20 all-gcc
make install-gcc
cd ..


3.4 compiling standard C library headers and startup files

cd glibc-2.23
mkdir xxx_aarch64_gcc9.4.0_glibc2.23linux_build
cd xxx_aarch64_gcc9.4.0_glibc2.23linux_build
../configure --prefix=/opt/xxx/xxx_aarch64_gcc9.4.0_glibc2.23linux/aarch64-linux-gnu --build=$MACHTYPE --host=aarch64-linux-gnu --target=aarch64-linux-gnu --disable-multilib
make install-bootstrap-headers=yes install-headers
make -j20 csu/subdir_lib
install csu/crt1.o csu/crti.o csu/crtn.o /opt/xxx/xxx_aarch64_gcc9.4.0_glibc2.23linux/aarch64-linux-gnu/lib
aarch64-linux-gcc -nostdlib -nostartfiles -shared -x c /dev/null -o /opt/xxx/xxx_aarch64_gcc9.4.0_glibc2.23linux/aarch64-linux-gnu/lib/
touch /opt/xxx/xxx_aarch64_gcc9.4.0_glibc2.23linux/aarch64-linux-gnu/include/gnu/stubs.h
cd ..

CSU / CRT1. O CSU / CrTi. O CSU / CRTN. O these library files need to be compiled later, but they are not installed automatically.libc.soAnd stubs. H are required in step 3.5, but will be regenerated in step 3.6.

3.5 libraries needed to compile GCC

cd gcc-9.4.0/xxx_aarch64_gcc9.4.0_glibc2.23linux_build
make -j20 all-target-libgcc
make install-target-libgcc
cd ../../

3.6 compiling glibc Library

cd glibc-2.23/xxx_aarch64_gcc9.4.0_glibc2.23linux_build
make -j20
make install
cd ../../


3.7 compiling C + + Libraries

cd gcc-9.4.0/xxx_aarch64_gcc9.4.0_glibc2.23linux_build
make -j20
make install
cd ../../


4 compilation problems encountered

There is an error in the GCC source code of 9.4, reporting path_ Max is undefined. After searching the definition in the header file, the maximum is 4096. After manually changing it to 4096, it is compiled and passed:

libtool: compile: /home/ronghua.zhou/zrh/gcc-9.4.0/xxx_aarch64_gcc9.4.0_glibc2.23linux_build/./gcc/xgcc -shared-libgcc -B/home/ronghua.zhou/zrh/gcc-9.4.0/xxx_aarch64_gcc9.4.0_glibc2.23linux_build/./gcc -nostdinc++ -L/home/ronghua.zhou/zrh/gcc-9.4.0/xxx_aarch64_gcc9.4.0_glibc2.23linux_build/aarch64-linux-gnu/libstdc++-v3/src -L/home/ronghua.zhou/zrh/gcc-9.4.0/xxx_aarch64_gcc9.4.0_glibc2.23linux_build/aarch64-linux-gnu/libstdc++-v3/src/.libs -L/home/ronghua.zhou/zrh/gcc-9.4.0/xxx_aarch64_gcc9.4.0_glibc2.23linux_build/aarch64-linux-gnu/libstdc++-v3/libsupc++/.libs -B/opt/xxx/xxx_aarch64_gcc9.4.0_glibc2.23linux/aarch64-linux-gnu/bin/ -B/opt/xxx/xxx_aarch64_gcc9.4.0_glibc2.23linux/aarch64-linux-gnu/lib/ -isystem /opt/xxx/xxx_aarch64_gcc9.4.0_glibc2.23linux/aarch64-linux-gnu/include -isystem /opt/xxx/xxx_aarch64_gcc9.4.0_glibc2.23linux/aarch64-linux-gnu/sys-include -D_GNU_SOURCE -D_DEBUG -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -DASAN_HAS_EXCEPTIONS=1 -DASAN_NEEDS_SEGV=1 -DCAN_SANITIZE_UB=0 -I. -I../../../../libsanitizer/asan -I.. -I ../../../../libsanitizer/include -I ../../../../libsanitizer -Wall -W -Wno-unused-parameter -Wwrite-strings -pedantic -Wno-long-long -fPIC -fno-builtin -fno-exceptions -fno-rtti -fomit-frame-pointer -funwind-tables -fvisibility=hidden -Wno-variadic-macros -fno-ipa-icf -I../../libstdc++-v3/include -I../../libstdc++-v3/include/aarch64-linux-gnu -I../../../../libsanitizer/../libstdc++-v3/libsupc++ -std=gnu++11 -g -O2 -D_GNU_SOURCE -MT asan_poisoning.lo -MD -MP -MF .deps/asan_poisoning.Tpo -c ../../../../libsanitizer/asan/ -fPIC -DPIC -o .libs/asan_poisoning.o
../../../../libsanitizer/asan/ In function 'void __asan::AsanCheckIncompatibleRT()':
../../../../libsanitizer/asan/ error: 'PATH_MAX' was not declared in this scope
216 | char filename[PATH_MAX];
| ^~~~~~~~
../../../../libsanitizer/asan/ error: 'filename' was not declared in this scope; did you mean 'fileno'?
217 | MemoryMappedSegment segment(filename, sizeof(filename));
| ^~~~~~~~
| fileno
Makefile:599: recipe for target 'asan_linux.lo' failed
make[4]: *** [asan_linux.lo] Error 1
make[4]: *** Waiting for unfinished jobs....


5 how to use?

The compiled result / opt / xxx / xxx_ aarch64_ gcc9.4.0_ Glibc2.23 Linux / copy to any x86_ 64 on the Linux compiler (glibc version of the environment must be higher than version 2.23), replace the GCC / G + + and other programs of the compiled command with / opt / xxx / xxx_ aarch64_ gcc9.4.0_ Glibc2.23 corresponding program in Linux / bin, and add the search path of link library / opt / xxx / xxx_ aarch64_ gcc9.4.0_ Glibc2.23linux/lib, add header file search path / opt / xxx / xxx_ aarch64_ gcc9.4.0_ Glibc2.23 Linux / include can be compiled normally. For example:

/opt/xxx/xxx_aarch64_gcc9.4.0_glibc2.23linux/bin/xxx_aarch64_gcc9.4.0_glibc2.23linuxg++ -I/opt/xxx/xxx_aarch64_gcc9.4.0_glibc2.23linux/include   ~/zrh/test.cpp 

The compiled result a.out can be copied to Feiteng server for running:

PS C:\Users\ronghua.zhou> ssh [email protected]
Authorized users only. All activities may be monitored and reported.
[email protected] password:

Authorized users only. All activities may be monitored and reported.
Web console: https://localhost:9090/ or

Last login: Wed Jul 21 16:12:49 2021 from
[[email protected] ~]$ uname -a
Linux localhost.localdomain 4.19.90-17.5.ky10.aarch64 #1 SMP Fri Aug 7 13:35:33 CST 2020 aarch64 aarch64 aarch64 GNU/Linux
[[email protected] ~]$ ./a.out
sz=3, sz1=8


6 related codes

Support one click downloading source code from the Internet, compiling and installing cross tool chain

zhouronghua/CCC: the Compiler of the Cross Compiler (