CMAKE_STAGING_PREFIX not being used by find_*

CMAKE_STAGING_PREFIX would indicate that it’s used as one of the search paths for the find_*** methods. However, I’m not finding that in practice - wondering if I’m missing some other configuration.

Toolchain (for ubuntu’s arm-linux-gnueabihf):

set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_PROCESSOR "arm")
set(CMAKE_C_COMPILER   arm-linux-gnueabihf-gcc)
set(CMAKE_CXX_COMPILER arm-linux-gnueabihf-g++)
list(APPEND CMAKE_FIND_ROOT_PATH "/usr/arm-linux-gnueabihf")
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 ONLY)

Args passed to cmake:

-DCMAKE_TOOLCHAIN_FILE=${PWD}/arm-linux-gnueabihf.cmake -DCMAKE_STAGING_PREFIX=${PWD}/install

Debugging code in CMakeLists.txt:

message(WARNING "CMAKE_FIND_ROOT_PATH.......${CMAKE_FIND_ROOT_PATH}")
message(WARNING "CMAKE_STAGING_PREFIX..........${CMAKE_STAGING_PREFIX}")
message(WARNING "CMAKE_PREFIX_PATH..........${CMAKE_PREFIX_PATH}")
message(WARNING "CMAKE_SYSTEM_PREFIX_PATH...${CMAKE_SYSTEM_PREFIX_PATH}")
set(CMAKE_FIND_DEBUG_MODE TRUE)
find_package(ament_cmake_core REQUIRED)
message(FATAL_ERROR "BOOM")

Output:

CMake Warning at CMakeLists.txt:5 (message):
  CMAKE_FIND_ROOT_PATH......./usr/arm-linux-gnueabihf;/usr/arm-linux-gnueabihf

CMake Warning at CMakeLists.txt:6 (message):
  CMAKE_STAGING_PREFIX........../mnt/mervin/workspaces/foxy/skobuki/install

CMake Warning at CMakeLists.txt:7 (message):
  CMAKE_PREFIX_PATH..........

CMake Warning at CMakeLists.txt:9 (message):
  CMAKE_SYSTEM_PREFIX_PATH.../usr/local;/usr;/;/usr;/usr/X11R6;/usr/pkg;/opt

Checking prefix [/usr/arm-linux-gnueabihf/mnt/mervin/workspaces/foxy/skobuki/install/]
Checking prefix [/usr/arm-linux-gnueabihf/mnt/mervin/workspaces/foxy/skobuki/.venv/]
Checking prefix [/usr/arm-linux-gnueabihf/usr/local/]
Checking prefix [/usr/arm-linux-gnueabihf/usr/]
Checking prefix [/usr/arm-linux-gnueabihf/]
Checking file [/usr/arm-linux-gnueabihf/ament_cmake_coreConfig.cmake]
Checking file [/usr/arm-linux-gnueabihf/ament_cmake_core-config.cmake]
Checking prefix [/usr/arm-linux-gnueabihf/usr/games/]
Checking prefix [/usr/arm-linux-gnueabihf/usr/local/games/]
Checking prefix [/usr/arm-linux-gnueabihf/snap/]
Checking prefix [/usr/arm-linux-gnueabihf/usr/arm-linux-gnueabihf/]
Checking prefix [/usr/arm-linux-gnueabihf/usr/X11R6/]
Checking prefix [/usr/arm-linux-gnueabihf/usr/pkg/]
Checking prefix [/usr/arm-linux-gnueabihf/opt/]
Checking prefix [/usr/arm-linux-gnueabihf/mnt/mervin/workspaces/foxy/skobuki/install/]
Checking prefix [/usr/arm-linux-gnueabihf/mnt/mervin/workspaces/foxy/skobuki/.venv/]
Checking prefix [/usr/arm-linux-gnueabihf/usr/local/]
Checking prefix [/usr/arm-linux-gnueabihf/usr/]
Checking prefix [/usr/arm-linux-gnueabihf/]
Checking file [/usr/arm-linux-gnueabihf/ament_cmake_coreConfig.cmake]
Checking file [/usr/arm-linux-gnueabihf/ament_cmake_core-config.cmake]
Checking prefix [/usr/arm-linux-gnueabihf/usr/games/]
Checking prefix [/usr/arm-linux-gnueabihf/usr/local/games/]
Checking prefix [/usr/arm-linux-gnueabihf/snap/]
Checking prefix [/usr/arm-linux-gnueabihf/usr/arm-linux-gnueabihf/]
Checking prefix [/usr/arm-linux-gnueabihf/usr/X11R6/]
Checking prefix [/usr/arm-linux-gnueabihf/usr/pkg/]
Checking prefix [/usr/arm-linux-gnueabihf/opt/]
CMake Error at CMakeLists.txt:11 (find_package):
  By not providing "Findament_cmake_core.cmake" in CMAKE_MODULE_PATH this
  project has asked CMake to find a package configuration file provided by
  "ament_cmake_core", but CMake did not find one.

Importantly, no CMAKE_STAGING_PREFIX being used in the search…

Ordinarily, find_package() would search all relevant locations with / as the root and again with CMAKE_FIND_ROOT_PATH as the root. Your toolchain file sets CMAKE_FIND_ROOT_PATH_MODE_PACKAGE to ONLY, which changes this to skip searching / as a base and it only uses CMAKE_FIND_ROOT_PATH as the base. You can see that in the very first search location, which is essentially ${CMAKE_FIND_ROOT_PATH}/${CMAKE_STAGING_PREFIX}

Oh, indeed. Just confirmed this before skipping over here and reading the answer. Nonetheless, still baffled.

From the documentation for find_package:

The CMake variable CMAKE_FIND_ROOT_PATH specifies one or more directories to be prepended to all other search directories. This effectively “re-roots” the entire search under given locations. Paths which are descendants of the CMAKE_STAGING_PREFIX are excluded from this re-rooting, because that variable is always a path on the host system. By default the CMAKE_FIND_ROOT_PATH is empty.

and

ONLY_CMAKE_FIND_ROOT_PATH Search only the re-rooted directories and directories below `CMAKE_STAGING_PREFIX.

also, from the documentation of CMAKE_STAGING_PREFIX:

The CMAKE_STAGING_PREFIX location is also used as a search prefix by the find_* commands. 

This would seem to indicate that directories related to the staging prefix not be re-rooted and that it also acts as an alternative root to CMAKE_FIND_ROOT_PATH. Admittedly though, I’m finding the preceding paragraphs not easy to follow.

Essentially, I figured there must be some means of co-ordinating the search across a set of directories that included a) installed toolchain, b) sysroot, c) staging area whilst excluding the root filesystem. e.g.

/ <- not searchable
/usr/arm-linux-gnueabihf/ <- searchable
/opt/staging <- searchable (and this is where to be compiled code will install)
/opt/sysroot <- searchable

That’s something I’ve done in the past and can force by setting CMAKE_FIND_ROOT_PATH capture both /usr/arm-linux-gnueabihf/ and /opt/staging, but I would have thought CMAKE_STAGING_PREFIX would have been useful here so I could decouple workspace specifics from toolchain specifics.

Is there an example of how CMAKE_STAGING_PREFIX is intended to be used? There’s not much available, even on a google search.

Aha, an example here.

set(CMAKE_SYSTEM_NAME Linux)

set(CMAKE_SYSROOT /home/devel/rasp-pi-rootfs)
set(CMAKE_STAGING_PREFIX /home/devel/stage)

set(CMAKE_C_COMPILER /home/devel/gcc-4.7-linaro-rpi-gnueabihf/bin/arm-linux-gnueabihf-gcc)
set(CMAKE_CXX_COMPILER /home/devel/gcc-4.7-linaro-rpi-gnueabihf/bin/arm-linux-gnueabihf-g++)

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 ONLY)

This however, would fail to discover cmake modules in /home/devel/stage when you have multiple, dependent projects installing to /home/devel/stage. In short, it would only be useful for a single project, or completely independent projects.

I use it like that in my toplevel CMakeLists.txt:

if ( CMAKE_CROSSCOMPILING )
set ( CMAKE_INSTALL_PREFIX “/opt” )
set ( STAGING_BASE_DIR “${CMAKE_BINARY_DIR}/staging” )
set ( CMAKE_STAGING_PREFIX “${STAGING_BASE_DIR}${CMAKE_INSTALL_PREFIX}” )
endif ()