We using some 3-rd party components in the project, which are built from sources and then cached in order to avoid unnecessary rebuilding.
That is done by simple logic, as
find_package (foo QUIET)
if (NOT foo_FOUND)
... configure external project file from template
... build & install configured project into predefined prefix
... add that prefix to CMAKE_PREFIX_PATH, or to CMAKE_FIND_ROOT_PATH
endif()
find_package (foo REQUIRED)
External project for caching is configured from template like
cmake_minimum_required ( VERSION 3.17 )
project ( @module@-prebuild NONE )
include ( ExternalProject )
ExternalProject_Add ( @module@_populate
SOURCE_DIR @MODULE_SRC@
BUILD_COMMAND "@CMAKE_COMMAND@" -E echo "Starting build config ${BUILD_TYPE}"
COMMAND "@CMAKE_COMMAND@" -DCMAKE_BUILD_TYPE=RelWithDebInfo .
COMMAND "@CMAKE_COMMAND@" --build . --config RelWithDebInfo
COMMAND "@CMAKE_COMMAND@" --install . --config RelWithDebInfo --prefix "@MODULE_BUILD@"
INSTALL_COMMAND ""
TEST_COMMAND ""
)
# file configured from cmake/external-build.cmake.in
Template is used to create real config and then build (in config-time) with a clause like this:
set(MODULE_SRC "${${MODULE_SRC_NAME}}")
set(MODULE_BUILD "${${MODULE_BUILD_NAME}}")
configure_file (external-build.cmake.in ${module}-build/CMakeLists.txt @ONLY )
execute_process(COMMAND ${CMAKE_COMMAND} -G "${CMAKE_GENERATOR}" . WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/${module}-build)
execute_process(COMMAND ${CMAKE_COMMAND} --build . WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/${module}-build)
It works perfectly with native build. Produced artifacts includes cmake exports, so that find_package then found them without rebuilding.
It works also perfectly with cross-compiling, if toolchain is passed via env CMAKE_TOOLCHAIN_FILE
(since all sub-processes see the same env and so, implicitly use same toolchain)
Problem is cross-compile which happens from outside which we can’t control. I’ve tried to build for openwrt and faced with the fact, that it passes params to cmake as cmd-line params, i.e. not via env variables. Call looks like cmake -DCMAKE_SYSTEM_PROCESSOR=mips -DCMAKE_BUILD_TYPE=Release -DCMAKE_C_FLAGS_RELEASE="-DNDEBUG" -DCMAKE_C_COMPILER="/Volumes/OpenWrt/openwrt/staging_dir/toolchain-mips_24kc_gcc-11.2.0_musl/bin/mips-openwrt-linux-musl-gcc"
… (and many others, about 5K of text).
I want to grab someway this params, and then pass them for configuring external project with the same environments.
Official docs just says, that cmake just pass several params, and you need to add others yourself, but I found no obvious way to take these ‘others’.
As ad-hoc I can, of course, accurate take the params from that call line, and pass them one-by-one into external_project, as -DCMAKE_C_COMPILER=${CMAKE_C_COMPILER}
and so on, but it looks really dirty and fragile (if on update it pass yet another param - we just don’t have it in our hard-coded list, and will lose it).
May be a way exists to access original params which was used calling cmake, to grab them? Like kind of iteration over cmake’s cache before ‘project’ statement, or anything else?