Building GCC as a cross compiler for Raspberry Pi
Posted on May 6, 2018 by Paul
Updated 10 May 2020
In this article, I will show you how to build GCC 10 as a cross compiler for Raspberry Pi. A cross compiler is a compiler that runs on an operating system and produces executables for another. This is really useful when you want to use your beefy computer to build a library or other large piece of code for Raspberry Pi. As a practical example, at the end of the article, I will show you how to use the cross compiler to build GCC itself as a native Raspberry Pi application.
An advantage of the approach presented in this article is that you can use the cross compiler to build RPi Zero and up executables. With the official crossbuild-essential-armhf from Debian you can build only Raspberry Pi 2 and up binaries.
Part of this article is a compilation of what I’ve learned reading other people posts. Here is a list of the sources I’ve used:
From the above list, the first article is the one that is the most complete and, if you follow it, you end up with a cross compiler that partially works. To be fair, the article wasn’t written for Raspberry Pi. I recommend that you read it if you want to see a more in depth explanation of certain steps of the process.
To build and host the cross compiler, I’ve used Debian 10, but a similar procedure should work on other Linux distributions.
First, make sure your system is updated and install the required prerequisites:
At the time of this writing, Raspbian comes with GCC 8.3.0, Binutils 2.31 and Glibc 2.28. It is really important that we build our cross compiler using the same Glibc version as the one from Raspbian. This will allow us to integrate nicely with the OS. If you are from the future and read this article, you can check the versions of the above software with these commands:
This is what I see on my Raspberry Pi:
If you are trying to build Glibc 2.28 with a more modern GCC, like 9.x or 10.x, you are going to get a lot of errors. Easiest approach is to build Glibc with GCC 8.3.0 and later use it with the latest and greatest GCC, which at this time is 10.1.
In the next instructions I’ll assume that you are doing all the steps in a separate folder and that you keep the same Terminal session open until everything is done. For example, you can create a working folder in your home:
Let’s download the software that we’ll use for building the cross compiler:
Next, extract the archives and erase them:
GCC also needs some prerequisites which we can download inside the source folder:
Next, create a folder in which we’ll put the cross compiler and add it to the path:
Copy the kernel headers in the above folder, see Raspbian documentation for more info about the kernel:
Next, let’s build Binutils:
GCC and Glibc are interdependent, you can’t fully build one without the other, so we are going to do a partial build of GCC, a partial build of Glibc and finally build GCC and Glibc. You can read more about this in Preshing’s article.
Now, let’s partially build Glibc:
Back to GCC:
Finish building Glibc:
Finish building GCC 8.3.0:
Optionally, write a small C or C++ test program, you can build the code with:
The resulting executable, test, from above was built with our first cross compiler and will run on your Pi. You can check that using the file command:
An even better test would be to transfer the above created binary to your RPi and see if you can run it.
At this point, you have a full cross compiler toolchain with GCC 8.3.0. Make a backup, in case something goes wrong, before proceeding with the next step:
Edit gcc-10.1.0/libsanitizer/asan/asan_linux.cpp. You will need to define PATH_MAX if it is not defined. Add the next piece of code after about line 66:
save and close the file.
Next, we are going to use the above built Glibc to build a more modern cross compiler that will overwrite GCC 8.3:
At this point, you can use GCC 10.1 to cross compile any C, C++ or Fortran code for your Raspberry Pi. You can invoke any of the cross compilers by using the prefix:
examples: arm-linux-gnueabihf-gcc, arm-linux-gnueabihf-g++, arm-linux-gnueabihf-gfortran.
In order to stress test our cross compiler, let’s use it to cross compile itself for the Pi:
You should end up with a a native ARM GCC in your /opt/gcc-10.1.0 folder.
As a side note, building GCC 10.1 with the above cross compiler took about 30 minutes on a Debian 10 x86-64 machine. Compare this with the 5 hours I needed to build GCC 8.1 directly on my Pi 3 in the past and you will see the advantage of having a cross compiler on your main machine. Someone told me that compiling GCC 7 on a Raspberry Pi Zero took about 5 days!
If you want to permanently add the cross compiler to your path, use something like:
You can now, optionally, safely erase the build folder. Assuming you’ve followed my advice, from your home folder use the next command:
Let’s archive the native GCC ARM compiler and save it to our home folder:
Copy gcc-10.1.0-armhf-raspbian.tar.bz2 to your RPi. For the remaining of this article I’ll assume you are on your RPi and that the above archive is in your home folder:
Next, we are going to add the new compilers to the path and create a few symbolic links:
At this point, you should be able to invoke the compilers with gcc-10.1, g++-10.1 or gfortran-10.1.
Let’s try to compile and run a C++17 code that uses an if block with init-statement (the example is a bit silly, but it will show you how to compile C++17 programs):
Save the above code in a file named if_test.cpp and compile it with:
This is what I see on my RPi:
Let’s also try to use the C++17 filesystem:
Save the above code in a file named fs_test.cpp and compile it with:
This is what I see on my RPi (don’t run the next code in your home folder if you have a lot of files because it will recursively print all of them, for example you can move it in a folder with a smaller numbers of files):
If you want to learn more about programming on the Raspberry Pi, a very good book is Exploring Raspberry Pi by Derek Molloy:
If you are interested to learn more about modern C++, I recommend A Tour of C++ by Bjarne Stroustroup: