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.
You can read more about the Cross-Compilation toolchain in Buildroot's Manual










External Toolchain

If an external toolchain is preferred for application development, a few options are available:

  1. Download and Set Path
    Obtain a pre-built toolchain from an online source and set the path to this toolchain in the Buildroot Configuration.

  2. Use Buildroot Configuration
    Utilize the Buildroot Configuration to download and extract an already-built toolchain available online.

  3. 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

In the rootfs overlay, we will create a new directory containing the necessary files to modify the root filesystem. This directory will include two files: the executable binary and the init script, which will run the binary in the background after booting up.



Post-Build Scripts

Using a custom script, we will change the permissions of the executable binary and the init script that we transferred to the target root filesystem. Then, in the Buildroot configuration menu, we will set the path to this script under the System Configuration Sub-Menu.



Post-Image Scripts

The Post-Image scripts are used to customize after the Boot-loader, Kernel, and File-system images are built. One use of this feature is to extract the root file-system to boot from a Network. For the time being, I am not going into this feature.

After creating and assigning the paths to the Overlay Directory and the Post-Build Scripts, we can execute the build.



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. 

Checkout the Log File that stored the CPU Usage data.

That's it for the time being. You can always try different configurations in the Buildroot menu to explore its features.

Popular posts from this blog

SignGlove: Bridging the Communication Gap for Paralyzed Patients

Cifradopro: A baremetal Hardware Security Module using the STM32L4S5 Cortex-M4 MCU

AESecureIO: Embedded Data Encryption and Decryption System