How to cross compile for Raspberry Pi 3 ?

asked 2018-07-03 01:52:41 -0600

Delb gravatar image

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 ... (more)

edit retag flag offensive close merge delete

Comments

Extending:        [explicit] /opt/ros/kinetic

your Catkin workspace is extending the default amd64 ROS install location. That doesn't sound right to me.

gvdhoorn gravatar imagegvdhoorn ( 2018-07-03 02:11:33 -0600 )edit

What could it be instead ? Isn't it required to compile the non-custom packages ?

Delb gravatar imageDelb ( 2018-07-03 02:16:29 -0600 )edit

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.

gvdhoorn gravatar imagegvdhoorn ( 2018-07-03 02:45:09 -0600 )edit

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.

gvdhoorn gravatar imagegvdhoorn ( 2018-07-03 02:47:07 -0600 )edit

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 ?

Delb gravatar imageDelb ( 2018-07-03 03:46:30 -0600 )edit

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.

gvdhoorn gravatar imagegvdhoorn ( 2018-07-03 03:59:08 -0600 )edit

So you mean I shouldn't link the /opt/ros/.. libraries but instead copy the dir into rootfs ?

Delb gravatar imageDelb ( 2018-07-03 04:34:23 -0600 )edit

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.

gvdhoorn gravatar imagegvdhoorn ( 2018-07-03 07:13:34 -0600 )edit