Support standalone build of project modules
schuhschuh opened this issue · 0 comments
Issue by schuhschuh
Thursday Mar 03, 2016 at 17:43 GMT
Originally opened as cmake-basis/legacy#555
The standalone build of project modules currently yields a different result than when the modules would have been built as part of the top-level project. This affects mainly the CMake files in the <prefix>/lib/cmake/<package>/
directory. The standalone built of subprojects (see SUBPROJECT
option of basis_project
) is a different subject and should work already. This issue is also concerned with module that are tightly coupled with the top-level project and other modules. These share a common namespace named after the top-level project (see PACKAGE
option of basis_project
).
- Name module configuration files
<Pkg><Module>Config.cmake
instead of<Pkg>Config.cmake
- Append module to
<Pkg>_MODULES
and<Pkg>_MODULES_ENABLED
lists - Include installed
<Pkg><Module>InstallManifest.txt
in uninstaller script - Skip
<prefix>/bin/uninstall-<pkg>
and<prefix>/lib/cmake/<pkg>/<Pkg>Uninstall.cmake
files - Include exported targets in
<Pkg><Module>Exports.cmake
in<Pkg><Module>Use.cmake
file which is to be included by<Pkg>Use.cmake
file when the module was requested
Thoughts on the export/import of module targets
Best would be to write <Pkg><Module>Exports.cmake
files for each module and include these in the respective <Pkg><Module>Config.cmake
files. This, however, is not possible with CMake because it requires all (library) targets that depend on each other to be exported altogether. What can we do about this?
Can/shall we make use of the following glob expression that CMake generates? But this would include the files <Pkg>Exports-<Module>-<config>.cmake
twice, once in <Pkg>Exports-<Module>.cmake
and another time in <Pkg>Exports.cmake
.
# Load information for each installed configuration.
get_filename_component(_DIR "${CMAKE_CURRENT_LIST_FILE}" PATH)
file(GLOB CONFIG_FILES "${_DIR}/MIRTKExports-*.cmake")
foreach(f ${CONFIG_FILES})
include(${f})
endforeach()
It seems the following code at the top of the generated exports file guards against multiple inclusions:
# Protect against multiple inclusion, which would fail when already imported targets are added once more.
set(_targetsDefined)
set(_targetsNotDefined)
set(_expectedTargets)
foreach(_expectedTarget mirtk::lbfgs mirtk::LibNumerics)
list(APPEND _expectedTargets ${_expectedTarget})
if(NOT TARGET ${_expectedTarget})
list(APPEND _targetsNotDefined ${_expectedTarget})
endif()
if(TARGET ${_expectedTarget})
list(APPEND _targetsDefined ${_expectedTarget})
endif()
endforeach()
if("${_targetsDefined}" STREQUAL "${_expectedTargets}")
set(CMAKE_IMPORT_FILE_VERSION)
cmake_policy(POP)
return()
endif()
if(NOT "${_targetsDefined}" STREQUAL "")
message(FATAL_ERROR "Some (but not all) targets in this export set were already defined.\nTargets Defined: ${_targetsDefined}\nTargets not yet defined: ${_targetsNotDefined}\n")
endif()
unset(_targetsDefined)
unset(_targetsNotDefined)
unset(_expectedTargets)
It may be necessary to export all targets to a single file and then split this <Pkg>Exports.cmake
into separate <Pkg><Module>Exports.cmake
files using a Python script which filters only those parts that relate to the targets of the respective module.
Why not just including the <Pkg><Module>Exports.cmake
file in the <Pkg><Module>Use.cmake
file that is in turn included by <Pkg>Use.cmake
file as long as the module is added to the list of requested modules. The <Pkg><Module>Exports.cmake
file will only exist when the module was built and installed separate from the top-level project. When it is built and installed as part of the top-level project, its targets are in the <Pkg>Exports.cmake
file which is included by the <Pkg>Use.cmake
.