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 utmThe "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@localhostTo 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@localhostAll 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 debianIt 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-essentialFinally, compile and run your program:
g++ testprogram.cpp -o testprogramTo 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' >> ~/.bashrcFirst, install the toolchain to compile for ARM:
sudo apt install crossbuild-essential-armhf
# check if it's all good
arm-linux-gnueabihf-g++ -vThen compile using the new toolchain, and put it in the BeagleBoard:
arm-linux-gnueabihf-g++ testprogram.cpp -o testcross
sftp-bbb
sftp> put testcrossYou 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 updateFinally 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 ./statictestcrossAlternatively, without using -static, specify the libraries directory:
arm-linux-gnueabihf-g++ testprogram.cpp -o testcross
qemu-arm-static -L /usr/arm-linux-gnueabihf/ ./testcrossOn the BeagleBone, install the GDB Server:
sudo apt install gdbserverOn the VM, install the multi-architecture debugger:
sudo apt install gdb-multiarchOn the BeagleBone, run the GDB Server (e.g. on port 12345):
gdbserver --multi localhost:12345On 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 testcrossFinally, 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) runOn 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/newhdThen 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