Prepare for cross-compilation

Install developer tools

sudo apt install ubuntu-dev-tools

We're only using these tools to easily manage chroot environments and to run apt to manage cross-compilation dependencies. If you're interested, you can find more information on the Ubuntu and Debian Wiki, but most of it is far beyond the scope of this guide: https://wiki.ubuntu.com/SimpleSbuild, https://wiki.debian.org/sbuild.

Install Docker

You need Docker to pull or build the toolchain. You can find detailed installation instructions here: DigitalOcean - How to Install and Use Docker
Also follow the step to add your user to the docker group so you can run it without sudo.

Create a Raspberry Pi OS root filesystem

We'll use debootstrap to create a minimal Raspberry Pi OS root filesystem in a folder on our computer. It has all the system libraries of the Raspberry Pi installed and you can install third-party libraries as well, these are necessary to link your executables when cross-compiling.
This root filesystem folder is often referred to as the sysroot, and it will later be passed as an option to CMake, the compiler, the linker, GDB, etc. so they can find the necessary files (we cannot use the actual root file system of our computer, because the libraries there have the wrong architecture, most likely x86_64, but we need armv6 libraries).

wget -qO - https://archive.raspbian.org/raspbian.public.key | gpg --import -
mk-sbuild --arch=armhf buster --debootstrap-mirror=http://raspbian.raspberrypi.org/raspbian --name=rpizero-buster --debootstrap-keyring "$HOME/.gnupg/pubring.kbx --merged-usr" --skip-proposed --skip-updates --skip-security

If this is the first time you use mk-sbuild, you'll be asked to edit your ~/.sbuildrc file. Since we're not actually going to be publishing any packages, you can just accept the defaults. After this first run, reboot your computer, and run the second command again:

mk-sbuild --arch=armhf buster --debootstrap-mirror=http://raspbian.raspberrypi.org/raspbian --name=rpizero-buster --debootstrap-keyring "$HOME/.gnupg/pubring.kbx --merged-usr" --skip-proposed --skip-updates --skip-security

This will install a minimal version of Raspberry Pi OS in a folder on your computer. The Ubuntu development tools allow you to install libraries into this folder using apt install, which makes it very easy to manage the cross-compilation dependencies.

The --merged-usr option is included in the --debootstrap-keyring option so that it is passed on to debootstrap, the mk-sbuild script currently lacks this option.

If something went wrong or if you no longer need it, you can use sudo sbuild-destroychroot rpizero-buster-armhf, it will give instructions how to remove the root filesystem and the schroot configuration.

Install the toolchain

The cross-compilation toolchains in the Ubuntu repositories are not compatible with Raspberry Pi OS, so you'll have to build or install your own. It's easiest to just download the crosstool-NG toolchain from https://github.com/tttapa/RPi-Cpp-Toolchain.

mkdir -p ~/GitHub
cd ~/GitHub
git clone https://github.com/tttapa/RPi-Cpp-Toolchain
cd RPi-Cpp-Toolchain
./toolchain/toolchain.sh rpi --export-toolchain

This exports the toolchain to ~/GitHub/RPi-Cpp-Toolchain/toolchain/x-tools/armv6-rpi-linux-gnueabihf. You can add it to your path using:

echo 'export PATH="$HOME/GitHub/RPi-Cpp-Toolchain/toolchain/x-tools/armv6-rpi-linux-gnueabihf/bin:$PATH"' >> ~/.profile

This will only take effect after you log out and back in again, so you might want to do that now, or execute the following command to add it to your path in the current terminal:

export PATH="$HOME/GitHub/RPi-Cpp-Toolchain/toolchain/x-tools/armv6-rpi-linux-gnueabihf/bin:$PATH"

Verify that the toolchain is installed correctly by running:

armv6-rpi-linux-gnueabihf-g++ --version
armv6-rpi-linux-gnueabihf-g++ (crosstool-NG UNKNOWN) 11.1.0
Copyright (C) 2021 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

You can find more information about this toolchain and instructions on how to customize it here.

Install the C++ standard library to the Pi

Raspberry Pi OS uses an older compiler and has an older version of the C++ standard library installed. Since we're going to use a new toolchain, we need to install a newer version of libstdc++ to the Pi to be able to run our programs:

scp ~/GitHub/RPi-Cpp-Toolchain/toolchain/x-tools/armv6-rpi-linux-gnueabihf/armv6-rpi-linux-gnueabihf/sysroot/lib/libstdc++.so.6.0.29 RPi0:~
ssh RPi0 bash << 'EOF'
    sudo mkdir -p /usr/local/lib/arm-linux-gnueabihf
    sudo mv libstdc++.so.6.0.29 $_
    sudo ldconfig
EOF

The library is installed in /usr/local/lib so it doesn't interfere with the libraries managed by the system in /usr/lib.

Also do the same for the root filesystem on your computer, this comes in handy when debugging later:

sudo mkdir -p /var/lib/schroot/chroots/rpizero-buster-armhf/usr/local/lib/arm-linux-gnueabihf
sudo cp ~/GitHub/RPi-Cpp-Toolchain/toolchain/x-tools/armv6-rpi-linux-gnueabihf/armv6-rpi-linux-gnueabihf/sysroot/lib/libstdc++.so.6.0.29 $_
sudo schroot -c source:rpizero-buster-armhf -u root -d / ldconfig

Install and configure the IDE

Install Visual Studio Code

You can download and install VSCode from https://code.visualstudio.com/Download.

Install the extensions

You'll need the following extensions:

images/clangd.png
images/cmake-tools.png

Installing clangd

If this is the first time you're using the clangd extension, you'll have to install the language server. When you open a C++ file for the first time, the extension will automatically give you a prompt:

images/install-clangd-crop.png
images/clangd-installed-crop.png

Once the language server is installed, you get all features you'd expect from an IDE, such as semantic syntax highlighting, go-to-definition, autocomplete, documentation, refactoring options, etc.

images/clangd-working.png