If your subprojects require same variable to have different values(at global scope) you cannot build them using add_subdirectory
within single global project.
Instead, global project may install them using cmake
call either via execute_process
or ExternalProject_Add
. Sometimes, install(SCRIPT)
command may be used for that.
Installing using execute_process
makes subproject available immediately at configuration
stage.
It can be used when subproject has some packaging mechanism (see CMake tutorials about packaging), so global object may execute find_package(<subproject-name>)
and link with libraries, defined in subproject, in the most simple way(using variables, filled outside).
# Configure subproject into <subproject-build-dir>
execute_process(COMMAND ${CMAKE_COMMAND} -D<var>=<value> <subproject-source-dir>
WORKING_DIRECTORY <subproject-build-dir>)
# Build and install subproject
execute_process(COMMAND ${CMAKE_COMMAND} --build <subproject-build-dir> --target install)
# Extract variables, related to subproject for link with it.
find_package(<subproject-name>)
# Create target in global project and link with subproject
include_directories(${<subproject-name>_INCLUDE_DIRS})
link_directories(${<subproject-name>_LIBRARY_DIRS})
add_executable(global_program main.cpp)
target_link_libraries(global_program ${<subproject-name>_LIBRARIES})
Installing using ExternalProject_add
assigns target to the subproject, which will be installed at build
stage. Linking with subproject in that case is also possible, but requires to fill variables manually.
# Configure, build and install subproject
ExternalProject_Add(<subproject_target>
SOURCE_DIR <subproject-source-dir>
CMAKE_CACHE_ARGS -D<var>=<value>
BINARY_DIR <subproject-build-dir>
INSTALL_DIR <CMAKE_INSTALL_PREFIX-for-subproject>
)
# Create target in global project and link with subproject
include_directories(<subproject-include-files-location>)
link_directories(<subproject-libraries-location>)
add_executable(global_program main.cpp)
target_link_libraries(global_program <subproject-libraries-name>)
# Make sure that subproject will be built before executable.
add_dependencies(global_program <subproject_target>)
Installing using install(SCRIPT)
executes script at install
stage. This approach can be used when there is no build-dependencies between global project and subproject.
subproject_install.cmake:
# Configure subproject into <subproject-build-dir>
execute_process(COMMAND ${CMAKE_COMMAND} -D<var>=<value> <subproject-source-dir>
WORKING_DIRECTORY <subproject-build-dir>)
# Build and install subproject
execute_process(COMMAND ${CMAKE_COMMAND} --build <subproject-build-dir> --target install)
CMakeLists.txt:
install(SCRIPT subproject_install.cmake)