[cmake-developers] Making Config.cmake files easier to write

Alexander Neundorf neundorf at kde.org
Mon Feb 13 16:52:54 EST 2012


Hi,

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.

IMO the most tricky issue is how to deal with the location of the various 
installed files and directories.
Config.cmake files should be relocatable, i.e. their installation directory 
must be changeable at install time, i.e. not at cmake-time via 
CMAKE_INSTALL_PREFIX.
This is typical under Windows, where the user decides at install-time of a 
binary package where to put it.

This would be relatively straightforward if the install destinations e.g. for 
libs and headers would be relative directories.
But users/packagers want to be able to change those install directories, and 
so we must expect that some of the install directories are absolute 
directories, and handle this case properly.
Properly here means at least issue a useful error message if the package has 
been relocated, even better would be to adjust the install dirs to the changed 
location.
IMO we can't expect the average developer to figure out all the details how to 
handle those install dirs correctly by himself, taking into accoutn wishes of 
users, packagers and also Windows people.

Attached you can find an attempt to do so.
The file CMakeConfigHelpers.cmake is intended to be included by Config.cmake 
files (or preloaded by cmake automatically when loading a Config.cmake file).

It provides two functions:

determine_installed_location()

This function determines the current installation root of the package.
For a not-relocated package this will be CMAKE_INSTALL_PREFIX.
For a relocated package it detects that it has been relocated, and calculates 
the root dir.
This needs some logic since even the directory where the Config.cmake file is 
installed to can be configured e.g. to an absolute path.

This root dir is then used later on in set_absolute() to either adjust 
relative install dirs to their new install location, or to adjust absolute 
install dirs to their new location if the original absolute path was a subdir 
of the original CMAKE_INSTALL_PREFIX.

What the developer needs to do is shown in BarConfig.cmake.in:

* he must configure CMAKE_INSTALL_PREFIX into the Config.cmake file
* he must configure the install dir of the Config.cmake file into the 
Config.cmake file (@CMAKECONFIG_INSTALL_DIR@)
* he must call determine_installed_location() to calculate the current 
installation prefix dir
* done that, he must use set_absolute() with the additional two argument of 
the original and the current install prefix dir to set the location variables 
to their current location:

set(BAR_CMAKE_INSTALL_PREFIX "@CMAKE_INSTALL_PREFIX@")

determine_installed_location(_BAR_INSTALLED_PREFIX 
                "${BAR_CMAKE_INSTALL_PREFIX}"  "@CMAKECONFIG_INSTALL_DIR@")

set_absolute(BAR_INCLUDE_DIR "@INCLUDE_INSTALL_DIR@"
             "${_BAR_INSTALLED_PREFIX}" "${BAR_CMAKE_INSTALL_PREFIX}")

set_absolute(BAR_DATA_DIR "@DATA_INSTALL_DIR@"
             "${_BAR_INSTALLED_PREFIX}" "${BAR_CMAKE_INSTALL_PREFIX}")



I would consider this an acceptable easy way to write Config.cmake files.
The names of the macros/functions can of course be changed, and maybe the two 
additional parameters to set_absolute() could be hidden somewhere as global 
variables to save typing. But OTOH this would make the dependency that 
determine_installed_location() has to be called before set_absolute() 
invisible.


What do you think ?


An additional step would be to provide a macro which completely generates the 
Config.cmake file (similar to WriteBasicConfigVersionFile.cmake), e.g. a 
WriteBasicConfigFile.cmake.
This would take a whole bunch of arguments, like e.g. which variables to put 
in the file, what the exports-file is, and which install directories to put 
into that file, and then generate the file.
But I'm not sure I want to hide the Config.cmake file so much from the 
developers, I think developers should be aware of what can be done with a 
Config.cmake file, so they should write them themselves.
OTOH this would result in quite standard-conforming Config.cmake files, 
without a lot of exotic stuff people might come up. Not sure. I think the 
macros above are a useful first step, independent from whether such a 
convenience macro will be provided or not.


Additionally some helper files to make testing the installed Config.cmake 
files would be good. It is quite tedious to always write a small test program 
which tries to find the respective library and check that it works. Something 
to make this simple would be nice.

Alex
-------------- next part --------------
include(CMakeConfigHelpers)

# set the version of myself
set(BAR_VERSION_MAJOR @BAR_VERSION_MAJOR@)
set(BAR_VERSION_MINOR @BAR_VERSION_MINOR@)
set(BAR_VERSION_PATCH @BAR_VERSION_PATCH@)
set(BAR_VERSION ${BAR_VERSION_MAJOR}.${BAR_VERSION_MINOR}.${BAR_VERSION_PATCH} )

set(BAR_CMAKE_INSTALL_PREFIX "@CMAKE_INSTALL_PREFIX@")

determine_installed_location(_BAR_INSTALLED_PREFIX  "${BAR_CMAKE_INSTALL_PREFIX}"  "@CMAKECONFIG_INSTALL_DIR@")

set_absolute(BAR_INCLUDE_DIR "@INCLUDE_INSTALL_DIR@" "${_BAR_INSTALLED_PREFIX}" "${BAR_CMAKE_INSTALL_PREFIX}")

set_absolute(BAR_DATA_DIR "@DATA_INSTALL_DIR@" "${_BAR_INSTALLED_PREFIX}" "${BAR_CMAKE_INSTALL_PREFIX}")

# what is my include directory
set(BAR_INCLUDES "${BAR_INCLUDE_DIR}")

# import the exported targets
include(${CMAKE_CURRENT_LIST_DIR}/BarTargets.cmake)

# set the expected library variable
set(BAR_LIBRARIES bar )
-------------- next part --------------
A non-text attachment was scrubbed...
Name: CMakeConfigHelpers.cmake
Type: text/x-cmake
Size: 1606 bytes
Desc: not available
URL: <http://public.kitware.com/pipermail/cmake-developers/attachments/20120213/a099d27d/attachment-0002.bin>


More information about the cmake-developers mailing list