Reputation: 131547
In talks by Daniel Pfeiffer (Effective CMake) and by Deniz Bahadir (More Modern CMake), and even in the CMake documentation, it is suggested that (at least) to .cmake
files be generated for using a repository with CMake in other projects: foo-config.cmake
and foo-config-version.cmake
(for package foo
; another possible naming scheme is FooConfig.cmake
and FooConfigVersion.cmake
).
This already seems strange to me. Why shouldn't foo-config.cmake
also have information/commands regarding the installed version? Is there some objective reason for the two separate files to exist, or is it just a CMake design 'gaffe'?
Edit: snipped the rest of this question, for focus and since I got something wrong.
Upvotes: 5
Views: 1707
Reputation: 19916
Why shouldn't foo-config.cmake also have information/commands regarding the installed version?
The package script foo-config.cmake
is free to create targets (which cannot be deleted), set variables in the parent scope, and so on. Splitting foo-config-version.cmake
into a script that runs in an isolated scope makes it easy for the package search to proceed without fear of clobbering variables. It would have been possible to incorporate all this functionality in one file (the way find modules do) but history has shown this practice to be error-prone and redundant.
Basically, there are two advantages:
find_package
caller. Once foo-config.cmake
runs, it may set package variables, create targets, and so on with full confidence that the user intended this action.CMakePackageConfigHelpers
can generate good version scripts at the cost of two lines in your CMakeLists.txt
file. Given the new version range features in CMake 3.19, this is a welcome task to automate.Upvotes: 1
Reputation: 6734
To much for a comment but not a full answer:
A typical sequence in the projects I generate is using the CMakePackageConfigHelper and GNUInstallDirs modules from CMake.
There is no need to generate a foo-config-version.cmake
template. Just use the write_basic_package_version_file
command from this module to get things done.
The export
command comes handy if you want to use the config packages from the build directory without the need to install them.
See example:
# Support find_package(Foo NO_MODULE).
set(FOO_DOC_DIR ${CMAKE_INSTALL_DOCDIR})
set(FOO_INCLUDE_DIR ${CMAKE_INSTALL_INCLUDEDIR})
set(FOO_LIB_DIR ${CMAKE_INSTALL_LIBDIR})
set(FOODIR ${CMAKE_INSTALL_PREFIX})
include(CMakePackageConfigHelpers)
include(GNUInstallDirs)
configure_package_config_file(foo-config.cmake.in "${CMAKE_CURRENT_BINARY_DIR}/foo-config.cmake"
INSTALL_DESTINATION ${FOO_CONFIG_PACKAGE_LOCATION}
PATH_VARS FOODIR FOO_INCLUDE_DIR FOO_LIB_DIR FOO_DOC_DIR
)
write_basic_package_version_file("${CMAKE_CURRENT_BINARY_DIR}/foo-config-version.cmake"
VERSION ${PROJECT_VERSION}
COMPATIBILITY SameMajorVersion
)
# To make the component usable not only from the install directory but also from the build directory
export(
TARGETS Foo
FILE foo-export.cmake
)
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/foo-config.cmake" "${CMAKE_CURRENT_BINARY_DIR}/foo-config-version.cmake"
DESTINATION ${FOO_CONFIG_PACKAGE_LOCATION}
COMPONENT development
)
install(EXPORT Foo
DESTINATION ${FOO_CONFIG_PACKAGE_LOCATION}
NAMESPACE ${PROJECT_NAME}::
FILE foo-export.cmake
COMPONENT development
)
Upvotes: 0