Cross compilation setup using a Debian 10.4 VM on a Mac M1.
Workflow:
-
start the VM, point VSCode-Remote to it;
-
develop changes, cross-compile the final executable;
-
sftp the executable into the BBB;
-
run the executable from the BBB.
Here's the test program used throughout this readme:
testprogram.cpp
#include <iostream>
int main()
{
int x{5};
x++;
std::cout << "The value of x is: " << x << '\n';
return 0;
}
You can use UTM to add a Debian VM to MacOS:
brew install --cask utm
The "Debian 10.4 (Xfce)" image will do: https://mac.getutm.app/gallery/debian-10-4-xfce
You can also use the "Debian 10.4 (Minimal)" image, but it won't allow shared directories (for some reasons unknown to me).
First, set up your router to give the BBB a static IP address each time it connects, e.g. 192.168.178.10
.
Then, to ssh
and sftp
into the BBB:
ssh -X [email protected]
sftp [email protected]
To ssh
into the Debian VM, first forward guest's port 22
to host's port 22022
(or any of your choice).
See: https://getutm.app/guide/#port-forwarding
Then, as before:
ssh -p 22022 debian@localhost
To avoid entering a password each time you ssh into the VM, create an identity key and copy the public one into the VM:
ssh-keygen
ssh-copy-id -p 22022 debian@localhost
All becomes easier when adding aliases to ~/.bashrc
:
alias ssh-bbb='ssh -X [email protected]'
alias sftp-bbb='sftp [email protected]'
alias ssh-debianvm='ssh -p 22022 debian@localhost'
alias sftp-debianvm='ssh -P 22022 debian@localhost'
If you want to open VSCode into these remote directories, add those lines to your ssh/config
:
~/.ssh/config
# UTM Debian VM for cross-compiling
Host debianvm
HostName localhost
Port 22022
User debian
# BeagleBone Black
Host beaglebone
HostName 192.168.178.10
ForwardX11 yes
User debian
It might be useful to have a shared directory between the host-os and the guest-os.
UTM's documentation is quite scarce on the topic: https://mac.getutm.app/guide/#sharing
This comment fills the missing steps: utmapp/UTM#3755 (comment)
Working on a project on the VM using shared directories is quite painful. Much easier, instead, to clone the repo directly in the VM and work from there instead.
You may want to create a separate GitHub token for the VM:
- https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls
- https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/creating-a-personal-access-token
You may need to import your GPG keys into your VM: https://linuxhint.com/export-import-keys-with-gpg
On the VM, install what's necessary to compile C/C++ programs:
sudo apt update
sudo apt install build-essential
Finally, compile and run your program:
g++ testprogram.cpp -o testprogram
To install a recent enough version of CMake
, the best option is to build it from source.
See: https://github.com/Kitware/CMake
To install Conan
, the recommended way is through pip
:
sudo apt install python3-pip
pip3 install conan
echo 'PATH=$PATH:~/.local/bin' >> ~/.bashrc
First, install the toolchain to compile for ARM:
sudo apt install crossbuild-essential-armhf
# check if it's all good
arm-linux-gnueabihf-g++ -v
Then compile using the new toolchain, and put it in the BeagleBoard:
arm-linux-gnueabihf-g++ testprogram.cpp -o testcross
sftp-bbb
sftp> put testcross
You can now execute it from there.
Install the required tools and update the apt packages:
sudo apt install qemu-user-static
sudo dpkg --add-architecture armhf
# check if it's all good
dpkg --print-foreign-architectures
sudo apt update
Finally compile the program using the -static
flag (to place the dynamic libraries into the final executable) and run it:
arm-linux-gnueabihf-g++ -static testprogram.cpp -o statictestcross
qemu-arm-static ./statictestcross
Alternatively, without using -static
, specify the libraries directory:
arm-linux-gnueabihf-g++ testprogram.cpp -o testcross
qemu-arm-static -L /usr/arm-linux-gnueabihf/ ./testcross
On the BeagleBone, install the GDB Server:
sudo apt install gdbserver
On the VM, install the multi-architecture debugger:
sudo apt install gdb-multiarch
On the BeagleBone, run the GDB Server (e.g. on port 12345):
gdbserver --multi localhost:12345
On the VM, compile the program with debug symbols, then put it on the BBB:
arm-linux-gnueabihf-g++ -g testprogram.cpp -o testcross
sftp-bbb
sftp> put testcross
Finally, on the VM, start debugging:
gdb-multiarch -q testcross
(gdb) set architecture arm
(gdb) target extended 192.168.178.10:12345
(gdb) set remote exec-file testcross
(gdb) break main
(gdb) run
On the VM, to avoid repeating the first three GDB commands over and over,
place them in a .gdbinit
file at $HOME
:
set architecture arm
target extended 192.168.178.10:12345
set remote exec-file testcross
I didn't manage to properly set it up yet :(
If you run out of space in the VM, you can resize the image, create a new partition, and mount it somewhere in your fs:
# from your Mac, with the VM shut down
qemu-img resize /path/to/your/something.qcow2 +5G
# from the VM
sudo gparted
# in gparted: create a new ext4 partition and apply the changes
doItInTheGUIApp
# mount the drive
sudo mount /dev/vda4 /media/newhd
Then you can, for example, store your Conan packages in the new partition.
To automatically mount the drive at boot time:
sudo vi /etc/fstab
# add this line
/dev/vda4 /media/newhd ext4 defaults 0 2