Robotics StackExchange | Archived questions

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

Comments

Extending:        [explicit] /opt/ros/kinetic

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 all amd64: binaries, libraries, etc. The entire infrastructure in that directory is going to expect amd64. 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 the rootfs 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 into rootfs ?

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 requirements

Asked 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

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