-
Notifications
You must be signed in to change notification settings - Fork 13
Cross compiling for Raspberry Pi
I'm using Ubuntu 16.10
- Raspberry Pi 2 Model B
- Raspbian OS (2016-11-25-raspbian-jessie-lite.img)
- OpenFramework from ofnode for cross-compiling (https://github.com/ofnode/of.git)
Use Ubuntu disk utility if you're lazy like me.
You can do it with dd
too, there are plenty of command line example on the net but you should end up with something like :
$ sudo dd bs=1m if=2016-11-25-raspbian-jessie-lite.img of=/dev/rdisk2
You can either connect the RPi directly to your computer and share a Wifi connection via ethernet adapter, or connect it to the same router your computer is connected to.
On 2016-11-25-raspbian-jessie-lite.img ssh is not enabled by default. The simplest way to set up is to plug a screen, a keyboard and a power cable to the RPi then on the Pi terminal :
$ sudo raspi-config
In the raspi-config
menu, select Option 1 Expand Filesystem
, then go to 5 Interfacing Options
and choose P2 SSH Enable/Disable remote command line access to your Pi using SSH
(this menu position may change according to your raspi-config version) then enable the SSH service. You can also change Keyboard layout, localization, time zone, etc. and reboot.
Now you connect through SSH to the RPi with :
$ ssh [email protected]
And use this session to enter the following command line instructions.
gcc-4.9
becomes outdated and it becomes more and more difficult to build a working cross-compiler, we may jump into the future and use gcc-6
instead. Unfortunately, it is not available into jessie
repo, so we will grab the scretch
one.
Here is a sum-up of a step by step tutorial :
pi@raspberrypi:~ $ sudo cp /etc/apt/sources.list /etc/apt/sources.list_bak
pi@raspberrypi:~ $ sudo sed -i -- 's/jessie/stretch/g' /etc/apt/sources.list
pi@raspberrypi:~ $ sudo apt update
pi@raspberrypi:~ $ sudo apt install gcc-6 g++-6
pi@raspberrypi:~ $ sudo mv /etc/apt/sources.list_bak /etc/apt/sources.list # revert changes to sources.list
pi@raspberrypi:~ $ sudo apt update
Now, update the dependencies required when cross-compiling by downloading and running raspbian.sh
.
pi@raspberrypi:~ $ wget https://github.com/raw/ofnode/of/master/dev/install/linux/raspbian.sh
pi@raspberrypi:~ $ chmod +x raspbian.sh
pi@raspberrypi:~ $ sudo ./raspbian.sh
Shutdown the Raspberry Pi with :
pi@raspberrypi:~ $ sudo shutdown -P now
Then remove the SD card from the Raspberry Pi, insert the SD card in your host and use dd
to make an new image file.
$ df # and identify where is your SD card, note both first and last item in the line
Sys. de fichiers blocs de 1K Utilisé Disponible Uti% Monté sur
/dev/sdc2 7513804 6000140 1158168 84% /media/antoine/13d368bf-6dbf-4751-8ba1-88bed06bef77
/dev/sdc1 57288 20384 36904 36% /media/antoine/boot
$ umount /media/antoine/boot /media/antoine/13d368bf-6dbf-4751-8ba1-88bed06bef77
$ sudo dd bs=1m if=/dev/sdc of=raspbian-jessie-lite+of+ofnode_dependency.img # you could try to increase bs value but bbe careful this could cause read/write error and then you'll end up with a corrupted image.
Or use Linux disk utility GUI to do the same. I am using raspbian-jessie-lite+of+ofnode_dependency.img
as the image name.
Now we need to mount the .img but default image loader (when you double click it) mount in read only mode and we need to fix dead symlink.
Get the partition table with :
$ fdisk -lu raspbian-jessie-lite+of+ofnode_dependency.img
Périphérique Amorçage Start Fin Secteurs Size Id Type
raspbian-jessie-lite+of+ofnode_dependency.img1 8192 137215 129024 63M c W95 FAT32 (LBA)
raspbian-jessie-lite+of+ofnode_dependency.img2 137216 7774207 7636992 3,7G 83 Linux
Then get the start offset of the second partition (The Linux one) and multiply it by 512 to get an offset in octet rather than in sector. Here it is 137216 * 512 = 70254592
. Then mount the partition with read/write permission :
$ mkdir /tmp/rpi/root
$ sudo mount -o loop,offset=70254592,rw,sync raspbian-jessie-lite+of+ofnode_dependency.img /tmp/rpi/root
Many symbolic links in Linux system refered to absolute path with cause error when mounting the image in a folder, like we do. So we need to fix the links with :
$ cd /tmp/rpi/root/usr/lib/arm-linux-gnueabihf
$ sudo ln -fs ../../../lib/arm-linux-gnueabihf/libudev.so.1.5.0 libudev.so
$ sudo ln -fs ../../../lib/arm-linux-gnueabihf/libglib-2.0.so.0 libglib-2.0.so
$ sudo ln -fs ../../../lib/arm-linux-gnueabihf/libz.so.1 libz.so
$ sudo ln -fs ../../../lib/arm-linux-gnueabihf/libdl.so.2 libdl.so
In Ubuntu 16.10 you can get arm-linux-gnueabihf-gcc-4.9
and arm-linux-gnueabihf-g++-4.9
with :
$ sudo apt install gcc-4.9-arm-linux-gnueabihf g++-4.9-arm-linux-gnueabihf pkg-config-arm-linux-gnueabihf
If you need gcc-6
, then just do :
$ sudo apt install gcc-arm-linux-gnueabihf g++-arm-linux-gnueabihf pkg-config-arm-linux-gnueabihf
If you don't have it already :
$ git clone https://github.com/ofnode/of.git
We need to define some environnement variable, CMake can't do it because of an annoying bug.
$ export RPI_ROOT_PATH=/tmp/rpi/root
$ export PKG_CONFIG_SYSROOT_DIR=$RPI_ROOT_PATH
$ export PKG_CONFIG_LIBDIR=${RPI_ROOT_PATH}/usr/lib/pkgconfig:${RPI_ROOT_PATH}/usr/share/pkgconfig:${RPI_ROOT_PATH}/usr/lib/arm-linux-gnueabihf/pkgconfig/
Then configure build system :
$ mkdir build-of-rpi-debug
$ cd build-of-rpi-debug
$ cmake ../of -DCMAKE_TOOLCHAIN_FILE=${PWD}/../of/dev/arm-linux-gnueabihf-4.9.cmake -DRPI_ROOT_PATH='/tmp/rpi/root' -DOF_STATIC=ON -DCMAKE_BUILD_TYPE=Debug -G Ninja
I strongly recommand to build a static library, then you don't need to copy all the shared library to the RPi but just the resulting binary (and its data folder if needed). Replace arm-linux-gnueabihf-4.9.cmake
with arm-linux-gnueabihf.cmake
if you need gcc-6
.
Then you're ready to build :
$ ninja
Take a rest and a coffee :-)
You can now build an example :
$ cd ..
$ git clone https://github.com/ofnode/ofApp.git
$ mkdir build-ofApp-rpi-debug
$ cd build-ofApp-rpi-debug
$ cmake ../ofApp -DCMAKE_TOOLCHAIN_FILE=${PWD}/../of/dev/arm-linux-gnueabihf-4.9.cmake -DRPI_ROOT_PATH='/tmp/rpi/root' -DOF_STATIC=ON -DCMAKE_BUILD_TYPE=Debug -G Ninja
$ ninja
Then you just have to copy the new binary to the Raspberry Pi.
$ scp ../bin/ofApp-armv7-Debug [email protected]:~/
And test it :
$ ssh [email protected] /home/pi/ofApp-armv7-Debug
You can use QtCreator to edit your code and build your app and even start it.
There are at least 2 ways to configure it : you can setup a kit for Raspberry Pi or configure by command line and then tell QtCreator to use that configuration. I choose the second one.
After configuring the build with the command above, open the CMakeLists.txt
in QtCreator. Then go to the project settings page and display build configuration. In the build folder
field, put the path to the folder where you configured the buidl. And at the bottom of the page in Build environment
, display details and clic on batch edit
then enter :
PKG_CONFIG_LIBDIR=${RPI_ROOT_PATH}/usr/lib/pkgconfig:${RPI_ROOT_PATH}/usr/share/pkgconfig:${RPI_ROOT_PATH}/usr/lib/arm-linux-gnueabihf/pkgconfig/
PKG_CONFIG_SYSROOT_DIR=${RPI_ROOT_PATH}
RPI_ROOT_PATH=/tmp/rpi/root
This will ensure that the environment variable are correctly set when you run CMake.
It appears that network copy is quite slow for me and to avoid it, I add the bin
folder of my app to my NFS export, by adding the following line to /etc/exports
:
/<custom path>/ofApp 192.168.0.0/24(rw,sync,no_root_squash,no_subtree_check)
Restart nfs-kernel-server
$ sudo service nfs-kernel-server reload
Then I mount it on the Raspberry Pi with :
pi@raspberrypi:~ $ mkdir -p ~/ofApp
pi@raspberrypi:~ $ sudo mount <host ip>:/<custom path>/ofApp/bin ~/ofApp
and run :
pi@raspberrypi:~ $ ~/ofApp/bin/ofApp-Debug
You can start it directly from QtCreator
by adding a custom executable with command ssh
and arguments [email protected] /home/pi/ofApp/bin/ofApp
.
Of course, adapt paths to your configuration and it's much easier to setup a passwordless SSH authentication.