[cmake-developers] Making Config.cmake files easier to write
Alexander Neundorf
neundorf at kde.org
Tue Feb 14 14:44:00 EST 2012
On Tuesday 14 February 2012, Yury G. Kudryashov wrote:
> Brad King wrote:
> > On 2/13/2012 4:52 PM, Alexander Neundorf wrote:
> >> we are hoping that more and more libraries will install Config.cmake
> >> files (and for kdelibs this is actually happening right now), so we
> >> should make sure it is straighforward to create proper Config.cmake
> >> files.
> >
> > This is a worthwhile goal, but I do not like the approach proposed:
> >
> > (1) It makes BarConfig.cmake depend on a file not distributed with it.
> >
> > (2) The content of a relocatable BarConfig.cmake should not depend on
> > where it happened to be installed when the package was built.
> >
> > I'd rather see an approach that processes paths during configuration
> > of the original package. Provide some helper macros that can configure
> > BarConfig.cmake with the proper code in it to compute paths relative
> >
> > to its location:
> > include(CMakePackageConfigHelper)
> > cmake_package_config_for_install(Bar
> >
> > DESTINATION lib/cmake/Bar # install destination
> > # INPUT BarConfig-install.cmake.in # alternate input
> > )
> >
> > This would look for "BarConfig.cmake.in" (or whatever INPUT says) and
> > do configure_file along with install(FILES). The module can document
> > some standard @CONFIG@ variables that can be used inside the input
> >
> > file to get various paths:
> > $ cat BarConfig.cmake.in
> > @PACKAGE_INIT@
> > set(BAR_INCLUDE_DIRS "@PACKAGE_PREFIX@/include/bar")
>
> Another way to achieve the same result:
>
> set(INCLUDE_INSTALL_DIR "include") # relative
> set(MYPKGDATA_INSTALL_DIR ${CMAKE_PREFIX_PATH}/share/mypkg) # absolute
>
> cmake_package_config_for_install(Bar
> DESTINATION lib/cmake/Bar
> INPUT BarConfig-install.cmake.in
> PATH_VARS
> INCLUDE_INSTALL_DIR # interpreted as relative to install prefix
> MYPKGDATA_INSTALL_DIR # absolute
> )
>
> will substitute @PACKAGE_INCLUDE_INSTALL_DIR@ by "../../../include" and
> @PACKAGE_MYPKGDATA_INSTALL_DIR@ by "../../../share/mypkg" (both transformed
> to be relative to DESTINATION).
A problem I see here (and which we discussed already before on kde-
buildsystem) is the handling of the install() command.
The targets file and the version file have to be installed to the same
directory.
Currently I would do it like this:
configure_file(BarConfig.cmake.in BarConfig.cmake)
write_basic_config_version_file(BarConfigVersion.cmake
VERSION ${BAR_VERSION}
COMPATIBILITY AnyNewerVersion )
install(EXPORT BarExport DESTINATION ${CMAKECONFIG_INSTALL_DIR}
FILE BarTargets.cmake )
install(FILES BarConfig.cmake
BarConfigVersion.cmake
DESTINATION ${CMAKECONFIG_INSTALL_DIR} )
With the macro as suggested above, it would become:
write_basic_config_version_file(BarConfigVersion.cmake
VERSION ${BAR_VERSION}
COMPATIBILITY AnyNewerVersion )
cmake_package_config_for_install(Bar
DESTINATION ${CMAKECONFIG_INSTALL_DIR}
INPUT BarConfig.cmake.in
PATH_VARS INCLUDE_INSTALL_DIR DATA_INSTALL_DIR)
install(EXPORT BarExport DESTINATION ${CMAKECONFIG_INSTALL_DIR}
FILE BarTargets.cmake )
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/BarConfigVersion.cmake
DESTINATION ${CMAKECONFIG_INSTALL_DIR} )
What I don't like about this is that the three files which go into the same
directory are installed in three separate commands (install(FILES),
install(EXPORTS), cmake_package_config_for_install() ).
I thought a bit about a syntax like this, which I would like:
configure_config_file(BarConfig.cmake.in BarConfig.cmake
INSTALL_DESTINATION ${CMAKECONFIG_INSTALL_DIR}
PATH_VARS INCLUDE_INSTALL_DIR DATA_INSTALL_DIR
EXPORT_FILE BarExport.cmake)
write_basic_config_version_file(${CMAKE_CURRENT_BINARY_DIR}/BarConfigVersion.cmake
VERSION ${BAR_VERSION}
COMPATIBILITY AnyNewerVersion )
install(EXPORT BarExport DESTINATION ${CMAKECONFIG_INSTALL_DIR}
FILE BarTargets.cmake )
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/BarConfig.cmake
${CMAKE_CURRENT_BINARY_DIR}/BarConfigVersion.cmake
DESTINATION ${CMAKECONFIG_INSTALL_DIR} )
but this can't work, can it ?
In the BarConfig.cmake file there would still be either a
set(BAR_INCLUDE_DIR "@INCLUDE_INSTALL_DIR@")
which would work for absolute paths, or a
set(BAR_INCLUDE_DIR "${SomePrefix}/@INCLUDE_INSTALL_DIR@")
which would work only for relative paths, but a simple set() cannot work for
both cases. Am I missing something ?
So I think there has to be a special macro to be used for setting those
variables in the Config.cmake file, which takes care of converting a relative
path into an absolute, and of potentially "relocating" an absolute path.
Do you have a working example ?
This week Thursday and Friday I'll have time to work on it, and I'd like to
get this into cmake 2.8.8.
Alex
More information about the cmake-developers
mailing list