I ran into a really frustrating problem while trying to cross compile an application for my Raspberry Pi 3. I didn’t want to keep the Pi compiling all day, so I set up a cross-compilation toolchain on my PC. Everything seemed fine until I tried to build a project that depended on Boost. Suddenly, CMake exploded with a Boost error. Let me walk you through what I saw, what it actually means, how I fixed it, and how I tested my setup with a little practice project.
My First Toolchain File
Here’s the toolchain file I started with:
# Toolchain-Raspberry-pi.cmake (original)
set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_VERSION 1)
set(CMAKE_C_COMPILER $ENV{HOME}/Code/toolchains/crosscompile-raspberrypi/bin/arm-unknown-linux-androideabi-gcc)
set(CMAKE_CXX_COMPILER $ENV{HOME}/Code/toolchains/crosscompile-raspberrypi/bin/arm-unknown-linux-androideabi-g++)
set(CMAKE_FIND_ROOT_PATH $ENV{HOME}/Code/toolchains/crosscompile-raspberrypi/)
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
The Error I Saw
When I ran CMake with that toolchain, I got this:
Found package configuration file:
/usr/lib/cmake/boost_system-1.71.0/boost_system-config.cmake
but it set boost_system_FOUND to FALSE …
No suitable build variant has been found.
Tried and rejected:
* libboost_system.so.1.71.0 (64 bit, need 32)
* libboost_system.a (64 bit, need 32)
What This Error Really Means
At first glance it looks like CMake just can’t find Boost. But here’s the truth:
- CMake did find Boost but on my PC, under
/usr/lib
. Those are 64-bit x86 libraries. - My Raspberry Pi 3 runs 32-bit ARM (armv7, hard float). CMake realized that and rejected the host libs.
- To make matters worse, I was pointing my toolchain at
arm-unknown-linux-androideabi-gcc
, which is an Android toolchain, not Raspberry Pi OS. - Installing
lib32-boost-libs
on my PC didn’t help, because that’s 32-bit x86, not ARM.
So the bottom line: I had an architecture mismatch, a wrong compiler triple, and no sysroot with ARM Boost libraries.
The Fix
Here’s how I solved it step by step.
Install the right cross compiler
I switched to a real Linux ARM cross compiler:
sudo apt install gcc-arm-linux-gnueabihf g++-arm-linux-gnueabihf
Create a Raspberry Pi sysroot
On the Pi I installed Boost development headers and libs:
sudo apt update
sudo apt install build-essential libboost-all-dev
Then I synced the Pi’s libraries and headers to my PC:
mkdir -p $HOME/rpi-sysroot
rsync -avz --delete --rsync-path="sudo rsync" \
pi@raspberrypi.local:/lib/ $HOME/rpi-sysroot/lib/
rsync -avz --delete --rsync-path="sudo rsync" \
pi@raspberrypi.local:/usr/ $HOME/rpi-sysroot/usr/
A Corrected Toolchain File
Here’s the fixed toolchain:
# Toolchain-RaspberryPi-gnueabihf.cmake (fixed)
set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_PROCESSOR arm)
set(TOOLCHAIN_PREFIX arm-linux-gnueabihf)
set(CMAKE_C_COMPILER ${TOOLCHAIN_PREFIX}-gcc)
set(CMAKE_CXX_COMPILER ${TOOLCHAIN_PREFIX}-g++)
set(CMAKE_SYSROOT "$ENV{HOME}/rpi-sysroot")
set(CMAKE_FIND_ROOT_PATH ${CMAKE_SYSROOT})
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -march=armv7-a -mfpu=neon-vfpv4 -mfloat-abi=hard")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=armv7-a -mfpu=neon-vfpv4 -mfloat-abi=hard")
set(ENV{PKG_CONFIG_SYSROOT_DIR} "${CMAKE_SYSROOT}")
set(ENV{PKG_CONFIG_LIBDIR} "${CMAKE_SYSROOT}/usr/lib/arm-linux-gnueabihf/pkgconfig:${CMAKE_SYSROOT}/usr/lib/pkgconfig:${CMAKE_SYSROOT}/usr/share/pkgconfig")
Minimal Project CMakeLists
cmake_minimum_required(VERSION 3.15)
project(RpiBoostDemo LANGUAGES C CXX)
set(CMAKE_CXX_STANDARD 17)
set(Boost_NO_SYSTEM_PATHS ON)
set(BOOST_ROOT "$ENV{HOME}/rpi-sysroot/usr")
set(BOOST_INCLUDEDIR "$ENV{HOME}/rpi-sysroot/usr/include")
set(BOOST_LIBRARYDIR "$ENV{HOME}/rpi-sysroot/usr/lib/arm-linux-gnueabihf")
find_package(Boost 1.67 REQUIRED COMPONENTS filesystem system)
add_executable(demo src/main.cpp)
target_link_libraries(demo PRIVATE Boost::filesystem Boost::system)
Build Command
mkdir -p build && cd build
cmake .. -DCMAKE_TOOLCHAIN_FILE=$HOME/Code/toolchains/cmake-files/raspberry-pi/Toolchain-RaspberryPi-gnueabihf.cmake -DCMAKE_BUILD_TYPE=Release
cmake --build . -j
Now CMake happily finds Boost in the sysroot and builds the project.
Practice Functionality
I didn’t want to stop there. I wrote a small test app to prove the cross-compiled Boost libs were actually working.
Filesystem Lister
src/main.cpp
#include <boost/filesystem.hpp>
#include <boost/system/error_code.hpp>
#include <iostream>
int main(int argc, char** argv) {
namespace fs = boost::filesystem;
fs::path p = (argc > 1) ? fs::path(argv[1]) : fs::current_path();
boost::system::error_code ec;
if (!fs::exists(p, ec)) {
std::cerr << "Path does not exist: " << p.string()
<< " (error: " << ec.message() << ")\n";
return 1;
}
if (fs::is_directory(p, ec)) {
std::cout << "Listing directory: " << p.string() << "\n";
for (auto& entry : fs::directory_iterator(p, ec)) {
std::cout << " - " << entry.path().filename().string() << "\n";
}
} else {
auto size = fs::file_size(p, ec);
std::cout << "File: " << p.string() << " | size=" << size << " bytes\n";
}
return 0;
}
On the Pi I ran:
./demo /home/pi
And it listed my files correctly.
Add a Timer with Boost.Asio
I then extended the program with a one-second timer:
#include <boost/asio.hpp>
// inside main()
boost::asio::io_context io;
boost::asio::steady_timer t(io, std::chrono::seconds(1));
t.async_wait([](const boost::system::error_code& ec){
if (!ec) std::cout << "Timer fired after 1s (Boost.Asio test)\n";
});
io.run();
This proved not only Boost.Filesystem worked, but also Boost.System + Boost.Asio.
Final Thought
At first, I thought the Boost error was something trivial. But the real issue was bigger: I was mixing host libraries with a target architecture, using the wrong compiler triple, and not providing a proper sysroot. Once I fixed those three things, cross compiling Boost-based projects for Raspberry Pi 3 became straightforward.