I am using yocto (kirkstone) to create a sysroot and toolchain to cross-compile a collection of ROS 2 packages using colcon + CMake and ament-cmake for a robot. I included the relevant layers from meta-ros, configured my recipe with all the necessary build dependencies and I got my image and sdk. As mentioned above, ROS 2 uses an extension of CMake, ament-cmake, which defines a set of cmake functions and macros. These need to be imported at configure time using find_package(ament_cmake)
which also needs to run some python scripts under the hood to check if certain resources are available and then call some executables to convert message definitions in the ROS 2 idl to source code.
Including ament_cmake in the target sysroot and adding some directories in the native sysroot to PYTHONPATH got the job done. However, it's kind of weird that CMake find_package is finding a package on the target sysroot which in turn is running Python from the native sysroot while importing modules and running executables from the target sysroot - which just happens to work because the target machine is also x86_64 in my case. So, ideally, since this is a build time dependency and some executables need to be run on the build machine, I would like to have this package in the native sysroot of my yocto sdk. So I added this to my recipe:
TOOLCHAIN_HOST_TASK:append = " nativesdk-ament-cmake"
# ... and a bunch of other ament-cmake components
and added this to my toolchain file to allow cmake to look for packages also in the native sysroot:
set(CMAKE_FIND_ROOT_PATH "$ENV{OECORE_TARGET_SYSROOT}" "$ENV{OECORE_NATIVE_SYSROOT}")
Overall the toolchain kinda looks like this:
set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_PROCESSOR x86_64)
set(CMAKE_SYSROOT "$ENV{OECORE_TARGET_SYSROOT}")
set(CMAKE_STAGING_PREFIX ${CMAKE_INSTALL_PREFIX})
set(CMAKE_FIND_ROOT_PATH "$ENV{OECORE_TARGET_SYSROOT}" "$ENV{OECORE_NATIVE_SYSROOT}")
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_FIND_ROOT_PATH_MODE_PACKAGE BOTH)
I source the environment setup script and tried to run cmake configure with the toolchain file on this dummy project:
cmake_minimum_required(VERSION 3.16)
project(test)
find_package(ament_cmake REQUIRED)
find_package(rosidl_default_generators REQUIRED)
Unfortunately this didn't work as CMake didn't find any config or module to for ament_cmake. So I tried to compare the target sysroot in the first sdk generate which included ament-cmake in IMAGE_INSTALL (causing it to install in the target sysroot) and the native sysroot in the second sdk which I generated by adding TOOLCHAIN_HOST_TASK:append = " nativesdk-ament-cmake"
. I noticed that in the target sysroot of the first sdk, ${TARGET_SYSROOT}/usr/share/ament_cmake
does include a cmake
directory with the CMake config files for ament_cmake
, whereas in the second sdk, ${NATIVE_SYSROOT}/usr/share/ament_cmake
contains the exact same files except for those CMake configs. Now, I am not an expert with Yocto, so I'd like to ask what would be a good way to solve this problem? Why are the cmake config files not generate for the recipes added with nativesdk*
?