How to cross compile for Raspberry Pi 3 ?
Hello,
Compiling my project directly on my raspberry has a high failure rate so I thought the cross compilation was a good option to avoid that. But it appears to be more difficult than I thought and there are not that much tutorials on the internet about this topic.
Can somebody help me figure it out by describing how to proceed step by step not to miss anything ?
Here's what I did : (this answer from stackoverflow helped me a lot)
1) Install the compiler for the raspberry on my computer (running Ubuntu 16.04) -> for my raspberry it's arm-linux-gnueabihf
2) Create a rostoolchain.cmake
file :
SET(CMAKE_SYSTEM_NAME Linux)
SET(CMAKE_SYSTEM_VERSION 1)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
#avoid RT_LIBRARY-NOT-FOUND issue
set(CMAKE_LIBRARY_ARCHITECTURE arm-linux-gnueabihf)
#set(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib")
#set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)
set(LD_LIBRARY_PATH ${LD_LIBRARY_PATH}
$ENV{HOME}/raspberrypi/devel/lib)
set(PKG_CONFIG_PATH ${PKG_CONFIG_PATH}
$ENV{HOME}/raspberrypi/devel/lib/pkgconfig)
# specify the cross compiler
SET(CMAKE_C_COMPILER /usr/bin/arm-linux-gnueabihf-gcc)
SET(CMAKE_CXX_COMPILER /usr/bin/arm-linux-gnueabihf-g++)
SET(CMAKE_FIND_ROOT_PATH $ENV{HOME}/raspberrypi/rootfs)
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_LIBRARY_PATH
$ENV{HOME}/raspberrypi/rootfs)
# Set compiler flag
SET(CMAKE_C_FLAGS "${CMAKE_CXX_FLAGS} --sysroot=${CMAKE_FIND_ROOT_PATH}")
SET( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} --sysroot=${CMAKE_FIND_ROOT_PATH}" )
3) Create a catkin profile to cross compile :
Profile: cross
Extending: [explicit] /opt/ros/kinetic
Workspace: /home/robotics/raspberrypi
-------------------------------------------------------------------------------------------------------------------------
Source Space: [exists] /home/robotics/raspberrypi/src
Log Space: [exists] /home/robotics/raspberrypi/logs
Build Space: [exists] /home/robotics/raspberrypi/build
Devel Space: [exists] /home/robotics/raspberrypi/devel
Install Space: [unused] /home/robotics/raspberrypi/install
DESTDIR: [unused] None
-------------------------------------------------------------------------------------------------------------------------
Devel Space Layout: linked
Install Space Layout: None
-------------------------------------------------------------------------------------------------------------------------
Additional CMake Args: -DBUILD_SHARED_LIBS=Off -DCMAKE_TOOLCHAIN_FILE=/home/robotics/raspberrypi/rostoolchain.cmake
Additional Make Args: None
Additional catkin Make Args: None
Internal Make Job Server: True
Cache Job Environments: False
-------------------------------------------------------------------------------------------------------------------------
Whitelisted Packages: None
Blacklisted Packages: None
4) Finally, run catkin build
but it generates this warning (I display for only one package) :
Warnings << tile_manager:cmake /home/robotics/raspberrypi/logs/tile_manager/build.cmake.001.log
CMake Warning at /home/robotics/raspberrypi/src/tile_manager/CMakeLists.txt:79 (add_executable):
Cannot generate a safe linker search path for target tile_marker_node
because there is a cycle in the constraint graph:
dir 0 is [/home/robotics/raspberrypi/rootfs/usr/lib/arm-linux-gnueabihf]
dir 1 must precede it due to link library [libpthread.so]
dir 1 is [/usr/lib/x86_64-linux-gnu]
dir 0 must precede it due to link library [libpthread.so]
Some of these libraries may not be found correctly.
Leading to this error :
Errors << tile_manager:make /home/robotics/raspberrypi/logs/tile_manager/build.make.002.log
/opt/ros/kinetic/lib/libtf.so: file not recognized: File format not recognized
collect2: error: ld returned 1 exit status
It seems that there is a conflict with the paths /usr/lib/x86_64-linux-gnu
, /home/robotics/raspberrypi/rootfs/usr/lib/arm-linux-gnueabihf
and I have other warnings with /opt/ros/kinetic/lib
too but I can't find which variable is defining those paths (I think I should only have /home/robotics/raspberrypi/rootfs/usr/lib/arm-linux-gnueabihf
)
Am I missing something here or is it possible that the issues come from my CMakeLists.txt
files ?
Any insight would be greatly appreciated.
Asked by Delb on 2018-07-03 01:52:41 UTC
Answers
Oh, I approached to the similar issue. My RPI is on aarch4
instead of arm64.
run uname -m
in terminal then use the one works with your processor. Hope it helps!
Asked by kak13 on 2021-08-16 11:40:28 UTC
Comments
your Catkin workspace is extending the default
amd64
ROS install location. That doesn't sound right to me.Asked by gvdhoorn on 2018-07-03 02:11:33 UTC
What could it be instead ? Isn't it required to compile the non-custom packages ?
Asked by Delb on 2018-07-03 02:16:29 UTC
I'm not a cross-compilation expert, but how would you expect that to work? The files in
/opt/ros
are going to be allamd64
: binaries, libraries, etc. The entire infrastructure in that directory is going to expectamd64
. You cannot mix and match that.Asked by gvdhoorn on 2018-07-03 02:45:09 UTC
See the source install instructions (
amd64
though), they also don't do this.If you have binary artefacts that you want to include in your build, they'll have to come from your RPi and be present in your rootfs dir.
Asked by gvdhoorn on 2018-07-03 02:47:07 UTC
I'm sorry but I don't quite understand your answer, I do have binary artifacts to include. Are you saying I should have my
src/
dir inside therootfs
dir ?Asked by Delb on 2018-07-03 03:46:30 UTC
No, I'm saying that you cannot reuse any binary artefacts from your host (
amd64
) when compiling for your RPi. By using/opt/ros/..
you're doing exactly that.All libraries (and also headers) would have to come from your rootfs. So that includes any ROS binaries and libraries.
Asked by gvdhoorn on 2018-07-03 03:59:08 UTC
So you mean I shouldn't link the
/opt/ros/..
libraries but instead copy the dir intorootfs
?Asked by Delb on 2018-07-03 04:34:23 UTC
No: copying that directory in your rootfs dir would essentially copy
amd64
libraries into your rootfs. That won't work.You'll either need to install the arm binaries into your rootfs, or build them from source and then install them into your rootfs.
Asked by gvdhoorn on 2018-07-03 07:13:34 UTC
Okay I realized I didn't correctly understood your previous answer. Currently, inside my rootfs I have the
/usr
and/lib
dirs from my raspberry (as in the link I gave). I'm going to copy the/opt/ros/kinetic
from the raspberry too so that it'll meet your requirementsAsked by Delb on 2018-07-03 07:39:15 UTC
Hi, have you found a solution about that? I'm trying to compile for arm from my linux x86_64 pc.
Asked by i.giannak on 2019-01-15 09:33:21 UTC
Not yet I've set this aside since I asked the question. But I'll probably use a docker to achieve this.
Asked by Delb on 2019-01-16 04:38:44 UTC
So that you compile native on docker arm container and scp then executables to arm device. Could this be possible?
Asked by i.giannak on 2019-01-16 04:49:06 UTC
Haven't tried yet but yes, it seems to be a work around.
Asked by Delb on 2019-01-16 05:05:16 UTC
Might help you solve the problem: https://gitlab.com/VictorLamoine/libopencm3_bluepill_blink/tree/master. This allows to cross-compile for STM32 targets, you could start from here, modify the script to target a RPi CPU and first try to build a simple binary (no ROS). Then try to add ROS libraries
Asked by VictorLamoine on 2019-02-27 06:07:23 UTC