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 ...
your Catkin workspace is extending the default
amd64
ROS install location. That doesn't sound right to me.What could it be instead ? Isn't it required to compile the non-custom packages ?
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.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.
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 ?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.
So you mean I shouldn't link the
/opt/ros/..
libraries but instead copy the dir intorootfs
?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.