Skip to content

Cross Compiler CMake Usage Guide with Raspbian 32 bit Image

Abhishek Thakur edited this page Dec 14, 2021 · 15 revisions

Raspberry Pi Toolchains Logo

Cross-Compiler CMake Usage Guide with Raspbian 32-bit Image

This guide documents the complete steps to create rootfs/sysroot so that you can create a cross compile environment for any Raspberry Pi on a Linux machine using only a Raspbian OS 32-bit image file. After that we will cross-compile a working Software Binaries (Hello-World CMAKE example in this case) with CMAKE using only the Raspberry Pi GCC Toolchains available within our project.

👀 This guide is suitable if you don't own a Raspberry Pi hardware yet.
💡 Note: Our Cross-Compiler toolchains also works out-of-the-box on any Linux distro via WSL2 on Windows 10 Machines. 💯

⚠️ These instruction are only meant for 32-bit Raspbian OS images only.

 

 

Prerequites:

A. Hardware:

  • Any x86/x86_64 AMD/Intel machine

B. Software:

  • Host: Any Linux machine (💡 Our Cross-Compiler toolchains also works out-of-the-box on any Linux distro via WSL2 on Windows 10 Machines. 💯)
  • Target: Any Raspbian 32-bit OS image (Raspbian Buster lite tested)

C. Others:

  • A cup of coffee ☕.

 

Steps for Host Machine (PC/Laptop)

Let's go through all the commands for our Host Machine, i.e. PC/Laptop, where you going to build sysroot and cross-compile software binaries (Hello world application in this case) for your Raspberry Pi.

1. Update the Host Machine

First of all, Run the following commands to update your system and install important dependancies:

sudo apt update
sudo apt dist-upgrade
sudo apt install build-essential cmake unzip gfortran
sudo apt install gcc git bison python gperf pkg-config gdb-multiarch wget qemu-user-static rsync
sudo apt install gcc g++ gperf flex texinfo gawk bison openssl pigz libncurses-dev autoconf automake tar figlet

 

2. Setting up the directory structure

You can use these following commands to create "cmake-test" to use as workspace for the project:

sudo mkdir ~/cmake-test
sudo mkdir ~/cmake-test/tools
sudo mkdir ~/cmake-test/build
sudo chown -R 1000:1000 ~/cmake-test
cd ~/cmake-test

Note: Ensure the last command should have changed your current directory to ~/cmake-test. If not, run the last line again to make sure you are inside it, as the next steps assume you're running your commands from this directory.

 

3. Building Sysroot from Raspbian Image

First, make sure you're in cmake-test folder as needed for the next sections:

cd ~/cmake-test

⚠️ Warning: You need active internet connection to update packages while building images.

A: Clone and cd into Dedicated GitHub Repository:

git clone https://github.com/abhiTronix/rpi_rootfs.git && cd rpi_rootfs

B: Download and Extract Raspbian Lite 32-bit Buster image file:

💡 Note: These instruction also work for 32-bit Stretch and Bullseye images.

💡 Note: Always use the latest image for build sysroot. Download latest Raspbian-lite images from here

curl -O https://downloads.raspberrypi.org/raspios_lite_armhf/images/raspios_lite_armhf-2021-03-25/2021-03-04-raspios-buster-armhf-lite.zip
unzip 2021-03-04-raspios-buster-armhf-lite.zip

C: Build rootfs/sysroot with Raspbian Lite 32-bit Buster image file

💡 Note: These instruction also work for 32-bit Stretch images.

💡 Tip: Use ./build_rootfs.sh clean if anything goes wrong.

sudo chmod +x ./build_rootfs.sh

# To build rootfs
./build_rootfs.sh create ./2021-03-04-raspios-buster-armhf-lite.img

If you have followed above instructions carefully then, built rootfs will exist in ~/cmake-test/rpi_rootfs/rootfs directory.

⚠️ DO NOT move or copy rootfs directory to somewhere else otherwise rootfs files will throw errors.

 

4. Download & Extract the Precompiled Cross-Compiler

Now, Let's first change into tools directory for downloading our Precompiled Cross-compiler with the following command:

cd ~/cmake-test/tools

Note: Ensure the last command should have changed your current directory to ~/cmake-test/tools now. If not, run it again.

A. Copy Binary URL:

Copy URL from one of following Precompiled Compressed Base-Toolchain (for maximum compatibility) based on your Raspberry Pi Variant and OS you installed on it, from below:

Raspberry Pi Board Stretch(32-bit) OS Buster(32-bit) OS Bullseye(32-bit) OS
Raspberry Pi - Zero/W/WH & 1 Model A/B/A+/B+ 6.3.0 8.3.0 10.2.0
Raspberry Pi - 2 & 3 Model A/B 6.3.0 8.3.0 10.2.0
Raspberry Pi - 3 & 4 Model A+/B+ & Compute 3/3-lite/3+ 6.3.0 8.3.0 10.2.0

Note: You can also use the latest cross-compiler binaries instead. But they are not tested.

B. Download Binary

After that, paste your copied URL and run the following command to download the Cross-compiler:

wget <Copied Binary URL goes here> #for e.g. => wget https://sourceforge.net/projects/raspberry-pi-cross-compilers/files/Raspberry%20Pi%20GCC%20Cross-Compiler%20Toolchains/Buster/GCC%208.3.0/Raspberry%20Pi%202%2C%203/cross-gcc-8.3.0-pi_2-3.tar.gz 

C. Extract Binary:

Once it is downloaded, we can extract it using the following command:

tar xf cross-gcc-*.tar.gz

 

Build Dummy Hello-World Project

First, let's move back into the cmake-test folder as needed for the next sections:

cd ~/cmake-test

Now we need to create suitable files for our CMAKE project.

1. Create C++ main.cpp file:

Let’s try to compile and run a C++17 code that uses an if block with init-statement (the example is a bit simple, but will show you how to compile C++17 programs):

#include <iostream>

int main() {
  // if block with init-statement:
  if (int a = 5; a < 8) {
    std::cout << "Local variable a is < 8\n";
  } else {
    std::cout << "Local variable a is >= 8\n";
  }
  return 0;
}

2. Create PI.cmake CMAKE File

Let's create a typical cross-compiling toolchain that has content such as:

⚠️ Remember to replace Cross-Compiler Toolchain absolute path with yours in following CMAKE file.

set(CMAKE_VERBOSE_MAKEFILE ON)
set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_VERSION 1)
set(CMAKE_SYSTEM_PROCESSOR arm)

set(tools <absolute path to toolchain. for e.g $ENV{HOME}/cmake-test/tools/cross-pi-gcc-8.3.0-0>) # warning change toolchain path here.
set(rootfs_dir $ENV{HOME}/cmake-test/rpi_rootfs/rootfs) # warning make sure rootfs exist at this path

set(CMAKE_FIND_ROOT_PATH ${rootfs_dir})
set(CMAKE_SYSROOT ${rootfs_dir})

set(CMAKE_LIBRARY_ARCHITECTURE arm-linux-gnueabihf)
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fPIC -Wl,-rpath-link,${CMAKE_SYSROOT}/usr/lib/${CMAKE_LIBRARY_ARCHITECTURE} -L${CMAKE_SYSROOT}/usr/lib/${CMAKE_LIBRARY_ARCHITECTURE}")
set(CMAKE_C_FLAGS "${CMAKE_CXX_FLAGS} -fPIC -Wl,-rpath-link,${CMAKE_SYSROOT}/usr/lib/${CMAKE_LIBRARY_ARCHITECTURE} -L${CMAKE_SYSROOT}/usr/lib/${CMAKE_LIBRARY_ARCHITECTURE}")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC -Wl,-rpath-link,${CMAKE_SYSROOT}/usr/lib/${CMAKE_LIBRARY_ARCHITECTURE} -L${CMAKE_SYSROOT}/usr/lib/${CMAKE_LIBRARY_ARCHITECTURE}")

## Compiler Binary 
SET(BIN_PREFIX ${tools}/bin/arm-linux-gnueabihf)

SET (CMAKE_C_COMPILER ${BIN_PREFIX}-gcc)
SET (CMAKE_CXX_COMPILER ${BIN_PREFIX}-g++ )
SET (CMAKE_LINKER ${BIN_PREFIX}-ld 
            CACHE STRING "Set the cross-compiler tool LD" FORCE)
SET (CMAKE_AR ${BIN_PREFIX}-ar 
            CACHE STRING "Set the cross-compiler tool AR" FORCE)
SET (CMAKE_NM {BIN_PREFIX}-nm 
            CACHE STRING "Set the cross-compiler tool NM" FORCE)
SET (CMAKE_OBJCOPY ${BIN_PREFIX}-objcopy 
            CACHE STRING "Set the cross-compiler tool OBJCOPY" FORCE)
SET (CMAKE_OBJDUMP ${BIN_PREFIX}-objdump 
            CACHE STRING "Set the cross-compiler tool OBJDUMP" FORCE)
SET (CMAKE_RANLIB ${BIN_PREFIX}-ranlib 
            CACHE STRING "Set the cross-compiler tool RANLIB" FORCE)
SET (CMAKE_STRIP {BIN_PREFIX}-strip 
            CACHE STRING "Set the cross-compiler tool RANLIB" FORCE)

set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)

3. Create CMakeLists.txt File

Finally create a suitable CMakeLists.txt file:

cmake_minimum_required(VERSION 3.10)
project(cmake_test)
set(CMAKE_VERBOSE_MAKEFILE ON)
set(CMAKE_CXX_STANDARD 17)
add_executable(cmake_test main.cpp)

4. Configure CMAKE Project

Let's move into the build directory for further steps, as we don't want to build within that source directory as its crowded, so we will access it from within this this directory:

cd ~/cmake-test/build

Important: Ensure you are still in the ~/cmake-test/build directory.

Finally, Now we can configure our Hello-World CMAKE Project as follows:

cmake -DCMAKE_TOOLCHAIN_FILE=~/cmake-test/PI.cmake  -DCMAKE_BUILD_TYPE=Debug ..

5. Finally Build Project

Our build has been configured now, and it is time to actually build the source files, and run the following command:

make -j$(nproc)

Note: -j$(nproc) option indicates that the job should be spread into mutliple threads and run in parallel on available cores.

and your compiled files will be available at ~/cmake-test/build.

 

 

Clone this wiki locally