Cross-Compile C++ for Raspberry Pi 4B (32-bit OS)

I have been a fan of CMake and the conan package manager for some time when building C++. The following contains to cross-compile from Windows for the Raspberry Pi 4B.

Dependencies

About the Raspberry Pi 4B

The Raspberry Pi 4 Model B was released in June 2019 with a 1.5 GHz 64-bit quad core ARM Cortex-A72 processor, on-board 802.11ac Wi-Fi, Bluetooth 5, full gigabit Ethernet (throughput not limited), two USB 2.0 ports, two USB 3.0 ports, 2-8 GB of RAM, and dual-monitor support via a pair of micro HDMI (HDMI Type D) ports for up to 4K resolution.

It uses the Cortex-A72 architecture (quad-core 64-bit ARMv8 at 1.5GHz).

https://www.raspberrypi.com/products/raspberry-pi-4-model-b/specifications/

Key Attributes

The following are the key attributes for this demo project.

  • Target: Raspberry Pi 4 Model B (arch=armv8, aarch64)

    • Running Raspberry Pi OS (32-bit) on the RPi at present.
  • Build Machine: Windows 11 (64-bit)

Install the Toolchain

Install the toolchain from:

https://developer.arm.com/tools-and-software/open-source-software/developer-tools/gnu-toolchain/gnu-a/downloads

Specifically, I used AArch32 target with hard float (arm-none-linux-gnueabihf) or more specifically ( gcc-arm-10.3-2021.07-mingw-w64-i686-arm-none-linux-gnueabihf.tar.xz)

Install CMake

Download and install the latest version of CMake from https://cmake.org/download/. Specifically, I used ‘cmake-3.22.1-windows-x86_64.msi‘. I think that it automatically added to the PATH.

Add Conan Profiles

First thing, install conan if you haven’t (pip install conan). Create the following files in C:\<user>\.conan\profiles\.

raspberrypi-arm8

include(user-raspberrypi-arm7-x86_64)

target_host=arm-linux-gnueabihf
cc_compiler=gcc
cxx_compiler=g++

[settings]
os_build=Windows
arch_build=x86_64
os=Linux
arch=armv7
compiler=gcc
compiler.version=8
compiler.libcxx=libstdc++11
build_type=Release

[env]
CONAN_CMAKE_FIND_ROOT_PATH=$standalone_toolchain/$target_host/sysroot
PATH=[$standalone_toolchain/bin]
CHOST=$target_host
AR=$target_host-ar
AS=$target_host-as
RANLIB=$target_host-ranlib
LD=$target_host-ld
STRIP=$target_host-strip
CC=$target_host-$cc_compiler
CXX=$target_host-$cxx_compiler
CXXFLAGS=-I"$standalone_toolchain/$target_host/lib/include"

user-raspberrypi-arm7-x86_64

This file is meant for user / computer-specific settings. This is mainly only for if multiple team members are sharing the configuration.

Note: I couldn’t find ‘make.exe’ in the toolchain, so I used an alternate.

standalone_toolchain=D:/Programs/gcc-arm-10.3-arm-none-linux-gnueabihf

[env]
CONAN_MAKE_PROGRAM="D:/Programs/SysGCC/raspberry/bin/make.exe"

Build

For the purpose of this demo, the use of conan has limited value, but comes in super handy for running unit-tests prior to building the target application.

# Install Dependencies
conan install . --install-folder build-raspberry-armv7 -pr=raspberrypi-arm7

# Build
conan build . --build-folder build-raspberry-armv7

Console Output

PS D:\Projects\blog\raspberry-pi-4b-demo> cd .\code\hello-world\
PS D:\Projects\blog\raspberry-pi-4b-demo\code\hello-world> conan install . --install-folder build-raspberry-armv7 -pr=raspberrypi-arm7
Configuration:
[settings]
arch=armv7
arch_build=x86_64
build_type=Release
compiler=gcc
compiler.libcxx=libstdc++11
compiler.version=8
os=Linux
os_build=Windows
[options]
[build_requires]
[env]
AR=arm-linux-gnueabihf-ar
AS=arm-linux-gnueabihf-as
CC=arm-linux-gnueabihf-gcc
CHOST=arm-linux-gnueabihf
CONAN_CMAKE_FIND_ROOT_PATH=D:/Programs/gcc-arm-10.3-arm-none-linux-gnueabihf/arm-linux-gnueabihf/sysroot
CONAN_MAKE_PROGRAM=D:/Programs/SysGCC/raspberry/bin/make.exe
CXX=arm-linux-gnueabihf-g++
CXXFLAGS=-I"D:/Programs/gcc-arm-10.3-arm-none-linux-gnueabihf/arm-linux-gnueabihf/lib/include"
LD=arm-linux-gnueabihf-ld
PATH=[D:/Programs/gcc-arm-10.3-arm-none-linux-gnueabihf/bin]
RANLIB=arm-linux-gnueabihf-ranlib
STRIP=arm-linux-gnueabihf-strip
conanfile.py: Installing package
Requirements
Packages

Cross-build from 'Windows:x86_64' to 'Linux:armv7'
Installing (downloading, building) binaries...
conanfile.py: Generator txt created conanbuildinfo.txt
conanfile.py: Aggregating env generators
conanfile.py: Generated conaninfo.txt
conanfile.py: Generated graphinfo
PS D:\Projects\blog\raspberry-pi-4b-demo\code\hello-world> conan build . --build-folder build-raspberry-armv7
Using lockfile: 'D:\Projects\blog\raspberry-pi-4b-demo\code\hello-world\build-raspberry-armv7/conan.lock'
Using cached profile from lockfile
conanfile.py: Calling build()
conanfile.py: Using 'D:/Programs/SysGCC/raspberry/bin/make.exe' as CMAKE_MAKE_PROGRAM
-- Configuring done
-- Generating done
-- Build files have been written to: D:/Projects/blog/raspberry-pi-4b-demo/code/hello-world/build-raspberry-armv7
Consolidate compiler generated dependencies of target helloworld
[100%] Built target helloworld

Code

The latest profiles and demo source is found here: https://github.com/echozulucode/raspberry-pi-4b-demo.