First, you need toolchain - arm gnu toolchain. I used 9.2 as it happended to be the version I used on work.
Second, part of target file system - /usr and /lib. For raspberry pi 32bit, download raspberry pi OS lite at here. Then extract /usr and /lib only.
With these two, we can make docker image for the build. Build needs x86_64 tools. And cross-compiler tool-chain - gcc-arm-xxx-x86_64-arm-xxx. And target root of raspbian os.
# Dockerfile
FROM ubuntu:20.04
RUN useradd -s /bin/bash -u 1000 docker_user && \
apt-get update && \
apt-get install -y \
gcc g++ cmake git ninja-build lcov bison flex curl python3 fakeroot libpcre3-dev libcurl4-openssl-dev libxml2-dev \
cppcheck clang-tools clang-format clang-tidy
RUN apt-get install -y python3-pip
# https://developer.arm.com/downloads/-/gnu-a
# AArch32 target with hard float (arm-none-linux-gnueabih, )
ADD gcc-arm-9.2-2019.12-x86_64-arm-none-linux-gnueabihf.tar.xz /opt
# SYSROOT from rapsbian buster armhf - usr, lib only
ADD raspios-buster-armhf-lite.usrlib.tar.gz /opt/raspios-buster-armhf-lite
RUN ln -s /opt/raspios-buster-armhf-lite/lib/arm-linux-gnueabihf/ /lib/arm-linux-gnueabihf
... snip ...
Third, we needs cmake cross-compiling toolchain file. Below cmake defines the cross-compiling by specifying compiler - gcc-arm-xxx - and include and lib path at /opt/raspios-xxx. You may wonders why is there no CMAKE_SYSROOT, CMAKE_FIND_ROOT_PATH. I found those generate number of error that ask other changes which seems to be too obscure to pursue. And I think it is succinct to tell the tool-chain where to look at to compile and link instead of using those magic words.
# toolchain_raspberrypi_gcc9.cmake
set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_VERSION arm)
set(CMAKE_SYSTEM_PROCESSOR arm-linux-gnueabihf)
set(CMAKE_C_COMPILER /opt/gcc-arm-9.2-2019.12-x86_64-arm-none-linux-gnueabihf/bin/arm-none-linux-gnueabihf-gcc)
set(CMAKE_CXX_COMPILER /opt/gcc-arm-9.2-2019.12-x86_64-arm-none-linux-gnueabihf/bin/arm-none-linux-gnueabihf-g++)
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -L/opt/raspios-buster-armhf-lite/usr")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -L/opt/raspios-buster-armhf-lite/usr/lib")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -L/opt/raspios-buster-armhf-lite/usr/lib/arm-linux-gnueabihf")
include_directories(BEFORE
/opt/raspios-buster-armhf-lite/usr/include
/opt/raspios-buster-armhf-lite/usr/include/arm-linux-gnueabihf
With above cmake toolchain file, we can define remainging part of docker that prepares google unittest and google benchmark.
# Dockerfile
...
ADD toolchain_raspberrypi_gcc9.cmake .
RUN git clone https://github.com/google/googletest.git --depth 1 --branch release-1.11.0 &&\
cd googletest &&\
cmake -S . -B ./build_x86_64 &&\
cmake --build ./build_x86_64 &&\
cmake --install ./build_x86_64 &&\
cmake -S . -B ./build_arm -DCMAKE_TOOLCHAIN_FILE=../toolchain_raspberrypi_gcc9.cmake &&\
cmake --build ./build_arm &&\
cmake --install ./build_arm --prefix /opt/raspios-buster-armhf-lite/usr/ &&\
cd ../ &&\
rm -rf googletest
ADD CMakeLists.benchmark.txt .
RUN git clone https://github.com/google/benchmark.git --depth 1 --branch v1.6.1 && \
cd benchmark &&\
mv ../CMakeLists.benchmark.txt ./CMakeLists.txt &&\
cmake -S . -B ./build_x86_64 -DCMAKE_BUILD_TYPE=Release -DBENCHMARK_ENABLE_GTEST_TESTS=0&&\
cmake --build ./build_x86_64 --config Release &&\
cmake --install ./build_x86_64 &&\
cmake -S . -B ./build_arm -DCMAKE_BUILD_TYPE=Release -DBENCHMARK_ENABLE_GTEST_TESTS=0 -DCMAKE_TOOLCHAIN_FILE=../toolchain_raspberrypi_gcc9.cmake &&\
cmake --build ./build_arm &&\
cmake --install ./build_arm --prefix /opt/raspios-buster-armhf-lite/usr/ &&\
cd ../ &&\
rm -rf benchmark
After you generate docker image, you can go in the image, and make the host build and cross-compile build.
$ docker run --rm -it -v "$PWD":/du -w /du -u 0 samplecpp_build:0.1
/du# rm -rf ./build_x86_64
/du# cmake -S . -B ./build_x86_64
/du# cmake --build ./build_x86_64
/du# rm -rf ./build_arm
/du# cmake -S . -B ./build_arm -DCMAKE_TOOLCHAIN_FILE=../toolchain_raspberrypi_gcc9.cmake
/du# cmake --build ./build_arm
Cross-compiling means you specify compiler and include and lib path. And that is all.
You can find the code at my gitlab project samplecpp