C cross compile for raspberry pi with cmake fails to find header file

2.1k Views Asked by At

I'm trying to port a program that runs fine in x86 architecture (Linux Mint 17.1) to a Raspberry Pi (Raspbian Jessie Lite). I'm using CMake, so I just followed the nice guide in Crafty Bytes.

My toolchain-raspberrypi.cmake looks like this:

SET(CMAKE_SYSTEM_NAME Linux)
SET(CMAKE_SYSTEM_VERSION 1)

# Specify the cross compiler
SET(CMAKE_C_COMPILER $ENV{HOME}/rpi/tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian-x64/bin/arm-linux-gnueabihf-gcc)

#SET(CMAKE_C_FLAGS "-L$ENV{HOME}/rpi/rootfs/usr/lib/arm-linux-gnueabihf -I$ENV{HOME}$ENV{HOME}/rpi/rootfs/usr/include")

# Where is the target environment
SET(CMAKE_FIND_ROOT_PATH $ENV{HOME}/rpi/rootfs)
SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} --sysroot=${CMAKE_FIND_ROOT_PATH}")
SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} --sysroot=${CMAKE_FIND_ROOT_PATH}")
SET(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} --sysroot=${CMAKE_FIND_ROOT_PATH}")

# Search for programs only in the build host directories
SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)

# Search for libraries and headers only in the target directories
SET(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
SET(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)

CMake generates the Makefiles and seems to find all the required libraries:

$ cmake -D CMAKE_BUILD_TYPE=Debug -D CMAKE_TOOLCHAIN_FILE=/home/unknown/rpi/toolchain-raspberrypi.cmake ..
-- The C compiler identification is GNU 4.8.3
-- Check for working C compiler: /home/unknown/rpi/tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian-x64/bin/arm-linux-gnueabihf-gcc
-- Check for working C compiler: /home/unknown/rpi/tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian-x64/bin/arm-linux-gnueabihf-gcc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Looking for include file stdlib.h
-- Looking for include file stdlib.h - found
-- Looking for sys/types.h
-- Looking for sys/types.h - found
-- Looking for stdint.h
-- Looking for stdint.h - found
-- Looking for stddef.h
-- Looking for stddef.h - found
-- Check size of intmax_t
-- Check size of intmax_t - done
-- Check size of uintmax_t
-- Check size of uintmax_t - done
-- Check size of pid_t
-- Check size of pid_t - done
-- Found Lua51: /home/unknown/rpi/rootfs/usr/lib/arm-linux-gnueabihf/liblua5.1.so;/home/unknown/rpi/rootfs/usr/lib/arm-linux-gnueabihf/libm.so (found version "5.1.5")
-- Luaudio_INCLUDE_DIRS:     /home/unknown/rpi/rootfs/usr/include/lua5.1
-- LUA_LIBRARIES:         /home/unknown/rpi/rootfs/usr/lib/arm-linux-gnueabihf/liblua5.1.so;/home/unknown/rpi/rootfs/usr/lib/arm-linux-gnueabihf/libm.so
-- Found libusb-1.0:
--  - Includes: /home/unknown/rpi/rootfs/usr/include/libusb-1.0
--  - Libraries: /home/unknown/rpi/rootfs/usr/lib/libusb-1.0.a
-- Found PkgConfig: /usr/bin/pkg-config (found version "0.26")
-- checking for one of the modules 'check'
-- Looking for include file pthread.h
-- Looking for include file pthread.h - found
-- Looking for pthread_create
-- Looking for pthread_create - not found
-- Looking for pthread_create in pthreads
-- Looking for pthread_create in pthreads - not found
-- Looking for pthread_create in pthread
-- Looking for pthread_create in pthread - found
-- Found Threads: TRUE
-- Found libusb-1.0:
--  - Includes: /home/unknown/rpi/rootfs/usr/include/libusb-1.0
--  - Libraries: /home/unknown/rpi/rootfs/usr/lib/libusb-1.0.a
-- Configuring done
-- Generating done
-- Build files have been written to: /home/unknown/projects/ha/workspace/ha/build-rpi

But when I run make I get an error trying to locate a library header:

$ make
Scanning dependencies of target ha
[  2%] Building C object src/CMakeFiles/ha.dir/log.c.o
[  5%] Building C object src/CMakeFiles/ha.dir/cm.c.o
/home/unknown/projects/ha/workspace/ha/src/cm.c:13:31: fatal error: libusb-1.0/libusb.h: No such file or directory
 #include <libusb-1.0/libusb.h>
                               ^
compilation terminated.
make[2]: *** [src/CMakeFiles/ha.dir/cm.c.o] Error 1
make[1]: *** [src/CMakeFiles/ha.dir/all] Error 2
make: *** [all] Error 2

I'm totally stuck here. The files are there:

$ ls ~/rpi/rootfs/usr/include/libusb-1.0/ -l
total 72
-rw-r--r-- 1 unknown unknown 70156 jun 22  2014 libusb.h

$ ls ~/rpi/rootfs/usr/lib/libusb-1.0.a -l
-rw-r--r-- 1 unknown unknown 109920 jun 22  2014 /home/unknown/rpi/rootfs/usr/lib/libusb-1.0.a

And when running CMake with the --trace flag, it seems to find libusb related files:

/home/unknown/projectes/ha/workspace/ha/src/CMakeLists.txt(8):  find_package(libusb-1.0 REQUIRED )
/usr/share/cmake-2.8/Modules/Findlibusb-1.0.cmake(46):  if(LIBUSB_1_LIBRARIES AND LIBUSB_1_INCLUDE_DIRS )
/usr/share/cmake-2.8/Modules/Findlibusb-1.0.cmake(49):  else(LIBUSB_1_LIBRARIES AND LIBUSB_1_INCLUDE_DIRS )
/usr/share/cmake-2.8/Modules/Findlibusb-1.0.cmake(50):  find_path(LIBUSB_1_INCLUDE_DIR NAMES libusb.h PATHS /usr/include /usr/local/include /opt/local/include /sw/include PATH_SUFFIXES libusb-1.0 )
/usr/share/cmake-2.8/Modules/Findlibusb-1.0.cmake(62):  find_library(LIBUSB_1_LIBRARY NAMES usb-1.0 usb PATHS /usr/lib /usr/local/lib /opt/local/lib /sw/lib )
/usr/share/cmake-2.8/Modules/Findlibusb-1.0.cmake(72):  set(LIBUSB_1_INCLUDE_DIRS ${LIBUSB_1_INCLUDE_DIR} )
/usr/share/cmake-2.8/Modules/Findlibusb-1.0.cmake(75):  set(LIBUSB_1_LIBRARIES ${LIBUSB_1_LIBRARY} )
/usr/share/cmake-2.8/Modules/Findlibusb-1.0.cmake(79):  if(LIBUSB_1_INCLUDE_DIRS AND LIBUSB_1_LIBRARIES )
/usr/share/cmake-2.8/Modules/Findlibusb-1.0.cmake(80):  set(LIBUSB_1_FOUND TRUE )
/usr/share/cmake-2.8/Modules/Findlibusb-1.0.cmake(83):  if(LIBUSB_1_FOUND )
/usr/share/cmake-2.8/Modules/Findlibusb-1.0.cmake(84):  if(NOT libusb_1_FIND_QUIETLY )
/usr/share/cmake-2.8/Modules/Findlibusb-1.0.cmake(85):  message(STATUS Found libusb-1.0: )
-- Found libusb-1.0:
/usr/share/cmake-2.8/Modules/Findlibusb-1.0.cmake(86):  message(STATUS  - Includes: ${LIBUSB_1_INCLUDE_DIRS} )
--  - Includes: /home/unknown/rpi/rootfs/usr/include/libusb-1.0
/usr/share/cmake-2.8/Modules/Findlibusb-1.0.cmake(87):  message(STATUS  - Libraries: ${LIBUSB_1_LIBRARIES} )
--  - Libraries: /home/unknown/rpi/rootfs/usr/lib/libusb-1.0.a
/usr/share/cmake-2.8/Modules/Findlibusb-1.0.cmake(96):  mark_as_advanced(LIBUSB_1_INCLUDE_DIRS LIBUSB_1_LIBRARIES )
/home/unknown/projectes/ha/workspace/ha/src/CMakeLists.txt(10):  INCLUDE_DIRECTORIES(${LIBUSB_1_INCLUDE_DIRS} )

I'm a newcomer to CMake and so far I've not been able to find any helpful entry in this site nor anywhere else regarding this same problem.

Any clue?

1

There are 1 best solutions below

0
On BEST ANSWER

Problem

From the cmake --trace output one can see, that Findlibusb-1.0.cmake script, which search libusb-1.0 library, detects include directory for the library's headers via

find_path(LIBUSB_1_INCLUDE_DIR NAMES libusb.h ...)

This means, that the script expects libusb.h header to be included as

#include <libusb.h>

(The same conclusion can be deduced from the output of cmake call: line

- Includes: /home/unknown/rpi/rootfs/usr/include/libusb-1.0

already includes libusb-1.0 suffix for the include path.)

But error message shows, that cm.c file actually includes the header as

#include <libusb-1.0/libusb.h>

This means, that Findlibusb-1.0.cmake script you use (which is shipped with CMake itself) is not compatible with actual usage of the library in you project.

Ideal solution

You need to ship your project with compatible Findlibusb-1.0.cmake script, which uses

find_path(LIBUSB_1_INCLUDE_DIR NAMES libusb-1.0/libusb.h ...)

for detect include path. E.g., the one from PCL library. (At the beginning of your project's CMakeLists.txt you need to adjust CMAKE_MODULE_PATH variable for find the script.)

As fast workaround

You may replace path /home/unknown/rpi/rootfs/usr/include/libusb-1.0 with /home/unknown/rpi/rootfs/usr/include in the CMake cache. (After modification of the cache you need to rerun cmake).

Because cached value is likely used in include_directories() call from your project, proper directory will be used instead.


I'm wondering why find_package works differently when cross compiling.

More likely that find_package works identical on PC and when cross-compiling, but on PC you get path /usr/include being included by other means (e.g., it is included by default).