Anche io non riesco a trovare un modo ideale per farlo. Ma ecco la soluzione che sto usando per ora. È un lavoro extra, e non ASCIUTTO, ma penso che raggiunga la cosa giusta.
Imagine lib B
dipende da lib di terze parti A
. A
ha un modulo di ricerca definito oppure possiamo implementare un modulo di ricerca personalizzato per questo. Entrambi sono fattibili. Supponiamo di aver già scritto FindA.cmake
e memorizzato in ${CMAKE_SOURCE_DIR}/cmake
.Inoltre, supponiamo che quando si esegue cmake per generare il sistema di generazione di B
, si fornisce A_ROOT
per aiutare a trovare ccake A
.
Poi nel di B di livello superiore CMakeLists.txt
abbiamo bisogno:
# Use FindA.cmake, defined in the cmake/ directory.
list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake")
find_package(A REQUIRED)
# ... (define the B target here)...
# Copy the config file to the build dir
configure_file(cmake/BConfig.cmake cmake/BConfig.cmake @ONLY)
# Copy A's find module (skip this step if FindA is not custom).
configure_file(cmake/FindA.cmake cmake/FindA.cmake COPYONLY)
# Create the target export.
export(EXPORT BTargets
FILE ${CMAKE_BINARY_DIR}/cmake/BTargets.cmake
NAMESPACE B::
)
# Register B so cmake can find B's config file.
export(PACKAGE B)
Ora in cmake/BConfig.cmake
:
# Get the exported find module onto the module path.
# This step is unnecessary if the find module is part of cmake.
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}")
# Store the root so that find_package will work.
# You may have to store other variables here, too, but
# the principle is just more of the same.
set(A_ROOT @[email protected]) # **Could optionally cache this.
find_package(A MODULE REQUIRED)
# The usual one-liner for a config file.
include("${CMAKE_CURRENT_LIST_DIR}/BTargets.cmake")
giusto per guidare la casa di soluzione, diamo un'occhiata a un secondo esempio, Rocket
questa volta usando Boost
, che ha già definito un modulo di ricerca.
CMakeLists.txt
:
option(Boost_USE_MULTITHREADED ON)
option(Boost_USE_STATIC_LIBS OFF)
find_package(Boost REQUIRED COMPONENTS filesystem program_options)
add_library(Rocket rocket.cpp)
target_link_libraries(Rocket
PUBLIC Boost::filesystem
PRIVATE Boost::program_options
)
configure_file(cmake/BConfig.cmake cmake/BConfig.cmake @ONLY)
export(EXPORT RocketTargets
FILE ${CMAKE_BINARY_DIR}/RocketTargets.cmake
NAMESPACE Rocket::
)
export(PACKAGE Rocket)
Poi cmake/RocketConfig.cmake
avrebbe:
set(BOOST_ROOT @[email protected] CACHE PATH "In case boost was relocated.")
set(Boost_USE_MULTITHREADED @[email protected])
set(Boost_USE_STATIC LIBS @[email protected])
find_package(Boost REQUIRED COMPONENTS filesystem program_options)
include("${CMAKE_CURRENT_LIST_DIR}/RocketTargets.cmake")
Quindi sì. Sembra digitare troppo. Sembra che cmake dovrebbe essere in grado di generare tutto il codice da una dichiarazione export
in CMakeLists.txt
. Ma questa strategia sembra raggiungere l'obiettivo.
Inoltre, non ho ancora testato, ma ho il sospetto che, se la vostra dipendenza transitiva utilizza una CONFIG
invece di un MODULE
per find_package
, dovrebbe essere molto facile solo per aggiungere al CMAKE_PREFIX_PATH
nel file di configurazione pure.
Un problema è che non consente di impostare proprietà di destinazione come INTERFACE_INCLUDE_DIRECTORIES – RiaD