[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