Today, we’re going to build our own toolchain using crosstool-NG. There are so many cases that we want to build a particular toolchain for a specific embedded system development board. One MOST important reason for that is probably because the specific development board has limited resource to build upon, therefore, the time-consumption to build some software on the development board is VERY inefficient. In the other way around, cross compiling on the host PC is MORE efficient with respective to the time-consumption.

In this blog, for simplicity, we take Raspberry Pi 3B as our demo development board, for which we are building the cross compiler. Some references can be found at:

# 1. Installation

How to install crosstool-NG are thoroughly summarized at its official website. In my case, I had it installed under folder /opt/compilers/crosstool-ng. Let’s take a look:

And make sure /opt/compilers/crosstool-ng/bin is under environment variable PATH.

# 2. Configuration

Under any directory that you want to save your .config file, we can configure our target cross compiler.

According to elinux: RPi Linaro GCC Compilation, we need to do the following selections:

• Paths and misc options:

• Try features marked as EXPERIMENTAL: ticked
• Prefix directory: input the full path where you want to save the built toolchains
• Number of parallel jobs: 4. Sorry that I’ve NO idea if this is the number of cores on Raspberry Pi 3B, but Raspberry Pi 3B does have 4 cores.
• Target options:

• Target Architecture: arm
• Default instruction set mode: arm
• Use EABI: ticked
• append hf to the tuple (EXPERIMENTAL): ticked
• Endianness: Little endian
• Bitness: 32-bit
• Emit assembly for CPU: cortex-a53
• Use specific FPU: vfp
• Floating point: hardware (FPU)
• Toolchain options:

• Tuple’s vendor string: rpi
• Operating System

😝
• Binary utilities:

• Binary format: ELF
• Version of binutils: 2.31.1
• C-library:

• C library: glibc
• Version of glibc: 2.28
• C compiler:

• Show gcc versions from: GNU
• Version of gcc: 8.3.0
• gcc extra config: --with-float=hard
• Link libstdc++ statically into the gcc binary: tick
• C++: tick

After we save the configuration to file .config, we Exit the crosstool-NG configuration dialog.

# 3. Build

• unset LD_LIBRARY_PATH before building. Otherwise, you’ll meet some ERROR messages.
• mkdir ~/src before building. Otherwise, whenever you tried to rerun ct-ng build, you’ll have to download ALL required packages from scratch.

This process may take a while. I’m going to sleep tonight. Continue tomorrow…

Alright, let’s continue today. Glad to know it’s built successfully.

😄

Let’s FIRST take a look at what’s under the current folder.

And then, let’s take a look at what’s built under the specified destination folder.

Finally, let’s take a look at the version of our built cross compilers for Raspberry Pi 3B.

Additional issue: It seems current crosstool-NG does NOT officially support Python. Please refer to my issue at crosstool-NG.

# 4. Compile/Build a Package with Generated Toolchain

For most of the packages nowadays, they are

• either supported by make: ./configure -> make -> make install
• or supported by CMake: mkdir build -> cd build -> ccmake ../ -> make -> make install

How to use our generated toolchain to compile/build our target packages?

Today, we’re going to take the package flann as an example, which are to be built with CMake.

## 4.1 CMakeLists.txt Modification

### 4.1.1 CMake Toolchains - Cross Compiling for Linux

By following CMake Toolchains - Cross Compiling for Linux, we FIRST modify flann CMakeLists.txt a bit by adding the following lines before project(flann).

• CMAKE_SYSROOT specify the sysroot directory which emulate your target environment, here, Raspberry Pi 3B
• CMAKE_STAGING_PREFIX is where the STAGING results store, for the reason that final results may require to be built in multiple stages. You may refer to Linux From Scratch for further background knowledge about that.
• tools actually specify the building tool directory. Making sure all generated cross compiling tools are under folder \${tools}/bin.

### 4.1.2 Ignore hdf5

In addition, for the emulated Raspberry Pi 3B sysroot, hdf5 is NOT supported. Therefore, let’s simply comment out the following line in flann CMakeLists.txt.

## 4.2 Cross Compile

Now, let’s start cross-compiling flann.

and press c and then t, you’ll see the cross compiling toolchains have been automatically configured as:

The LAST step before make is to modify some of the parameters accordingly, in my case:

• BUILD_PYTHON_BINDINGS: ON -> OFF
• CMAKE_CXX_FLAGS: -I/usr/include (for lz4.h from my host Ubuntu 19.04)
• CMAKE_C_FLAGS: -I/usr/include (for lz4.h from my host Ubuntu 19.04)
• CMAKE_VERBOSE_MAKEFILE: OFF -> ON
• CMAKE_INSTALL_PREFIX: /usr/local/ -> under which directory you want to install, which can be IGNORED for now

Now, press c, you’ll see:

A warining of missing hdf5 is clearly reasonable and acceptable. Then press g.

Finally, it’s the time for us to cross build flann.

VERY Important:

• If you build flann from source on a Raspberry Pi 3B, your system is going to hang HERE, possibly due to lack of memory…
• Raspberry Pi 3B has 4 cores ONLY, but now you can use MORE cores on your host PC, which is clearly one advantage of using cross compiling.

Finally, you’ll see flann has been successfully cross compiled as:

You can now:

• make install to install the built/generated libraries installed under CMAKE_INSTALL_PREFIX
• copy and paste the built/generated libraries onto Raspberry Pi 3B and use it directly.

BTW: do NOT forget to install the header files.