Cross-Compiling executables for RPi4 on x86_64 | Buildroot | RPi4 | rootfs Overlay | Post-Build Scripts
Need for Cross-Compilation
In the context of Embedded Linux, target devices often lack the resources to compile their own binaries due to their constrained hardware. Consequently, developers need to compile these binaries on a more powerful host device and then transfer them to the target device. This process necessitates a toolchain designed to compile binaries for the target architecture on the host device. In the context of a Raspberry Pi 4, this would involve compiling binaries for an aarch64 target architecture on an x86_64 host device.
Since we are using Buildroot to configure and generate the images, we have a few options for cross-compiling toolchains. We can either use:
- The internal toolchain built by Buildroot.
- An external toolchain available online.
External Toolchain
If an external toolchain is preferred for application development, a few options are available:
Download and Set Path
Obtain a pre-built toolchain from an online source and set the path to this toolchain in the Buildroot Configuration.Use Buildroot Configuration
Utilize the Buildroot Configuration to download and extract an already-built toolchain available online.Generate Custom Toolchain
Create a custom toolchain using crosstool-ng, and then set the path to this compiler in the Buildroot Configuration.
But we won't be following this path since we are focusing only on the Internal Toolchain built by Buildroot.
Building the Toolchain
In the Toolchain Configuration menu, we can select the C Library, the Kernel Headers version, and other Library-specific options. For the raspberrypi4_64_defconfig, we have the glibc as the C library.
The generated toolchain is located at /buildroot/output/host/usr/bin/. You can find the tools like Linker (ld), Assembler (as) in this directory. The highlighted aarch64-buildroot-linux-gnu-gcc is the C Compiler we will be using.
Native Compiling for x86_64
For demonstration, we have a C program that Monitors the CPU Usage of the Raspberry Pi and logs it to a file every 60 seconds. It will read from the /proc/stat file and write it to a file cpu_usage.log.
Now, let us compile and inspect the compiled binary of this program using the Host Compiler on the x86_64 system.
Now, let's compile the same program using the Internally generated toolchain by Buildroot.
Cross Compiling for aarch64
Earlier we used gcc to compile the program. But now, we have to call the generated compiler.
~/Lab/Buildroot/buildroot/output/host/usr/bin/aarch64-buildroot-linux-gnu-gcc cpulog.c -o cpulog
Now, we have created an executable that can run on the Raspberry Pi 4's Processor. Let's look at how we can execute it on the target device.
Transferring binaries to Target
We built a default configuration image for the Raspberry Pi in Buildroot, and we won't have utilities and tools that might be available on a Raspberry Pi running a Raspbian OS. Since Buildroot's use is to automate the building process, we can use its ability to Customize the Generated Target filesystem to transfer our executables to the target device. Two such ways are
- rootfs Overlay
- Post-Build Scripts
rootfs Overlay
Post-Build Scripts
Post-Image Scripts
Executing binaries on Target
After we flash the SD Card with the newly created image, we can boot up the Raspberry Pi and go through the directories to find our customized files in the root filesystem of the Raspberry Pi.