-
Notifications
You must be signed in to change notification settings - Fork 0
CMake
Acknowledgement: big thanks to Micael Oliveira for his work on exporting CMake targets in ACCESS-OM3 and providing a starting point for the organisation on this topic
CMake projects which provide targets should install a CMake package configuration file. This is currently the best practice for library authors and has the benefit that projects can find and import targets out of the box via find_package()
without needing a find module.
This talk given by Daniel Pfeifer gives a great introduction to the topic:
Here are examples where we have done this at ACCESS-NRI:
- ACCESS-OM3 (deprecated):
- access3-share:
Other useful material:
-
CMake: Importing and Exporting Guide
- Examples from the tutorial can be found in the CMake GitLab repository.
- It's Time To Do CMake Right
When a CMake package config file is installed, the targets which are exported often require dependencies on other packages - these dependencies must be available for consumers of your exported targets. For example, this may be necessary if any targets declare a PUBLIC
dependency, or if the dependency may be provided as a static library. This is because for these cases, the INTERFACE_*
target properties of your exported targets will contain a reference to these dependencies and CMake will error if these dependencies cannot be found (see target usage requirements for more details on these properties).
find_dependency()
facilitates this by ensuring that the necessary dependencies are found when the package itself is found by the consuming project via find_package()
. It also forwards the correct parameters for QUIET
and REQUIRED
which were passed to the original find_package()
call.
If your project requires using find modules (Find<project>.cmake
files) to find its dependencies, then these find modules should be installed along with your package config file so that these dependencies can be found using find_dependency()
. Once the find modules are installed (typically in CMAKE_CURRENT_LIST_DIR
), we can make these find modules discoverable in the package config file:
list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR})
find_dependency(foo)
find_dependency(bar)
list(REMOVE_ITEM CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR})
See the following for more details:
- Exporting packages with a custom Find module
- Installing a CMake library: also ship find modules for the dependencies?
See Creating Relocatable Packages.
Relocatability has the benefit that the installed package will not break if the location of any installed dependencies and/or the package itself changes.
Common pitfalls which break relocatability:
-
Hardcoded paths to third-party dependencies
- Be careful to not populate any properties which may contain paths, such as
INTERFACE_INCLUDE_DIRECTORIES
andINTERFACE_LINK_LIBRARIES
(see target usage requirements for more details), with paths relevant to dependencies. This will result in hard coded paths to dependencies for your exported targets. - This can happen when using variables such as
Foo_LIBRARIES
orFoo_INCLUDE_DIRS
to link against third party dependencies. Instead, link against aFoo
imported target withtarget_link_libraries
to avoid populating paths to dependencies in the exported targets. However, this may not always be possible and the CMake manual suggests two workarounds here.
- Be careful to not populate any properties which may contain paths, such as