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

Alexander Neundorf neundorf at kde.org
Wed Feb 15 16:50:13 EST 2012


On Tuesday 14 February 2012, Alexander Neundorf wrote:
> On Tuesday 14 February 2012, Yury G. Kudryashov wrote:
> > Alexander Neundorf wrote:
> > > On Tuesday 14 February 2012, Yury G. Kudryashov wrote:
> > >> 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.
> > > 
> > > 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)
> > 
> > Why do you need EXPORT_FILE parameter? How can you use it? Include
> > automatically? Then you need VERSION_FILE parameter as well.
> > 
> > > 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 ?
> > 
> > You'll have in BarConfig.cmake.in
> > set(BAR_INCLUDE_DIR "@PACKAGE_HELPER_INCLUDE_INSTALL_DIR@)
> > 
> > After configure_config_file() you'll have
> > # At top
> > get_filename_component(_PKG_CURRENT_DIR "${CURRENT_LIST_FILE}" PATH)
> 
> Just a tip: since 2.8.3 or so there is ${CMAKE_CURRENT_LIST_DIR}
> 
> > get_filename_component(_PKG_PREFIX_PATH "${_PKG_CURRENT_DIR}/../../.."
> > ABSOLUTE)
> 
> The ../../../ will be also calculated by the macro, using RELATIVE_PATH and
> the DESTINATION parameter, right ?
> 
> > #in place of your set()
> > set(BAR_INCLUDE_DIR "${_PKG_PREFIX_PATH}/include")
> > 
> > > Do you have a working example ?
> > 
> > Not yet. I think about something like this (not tested).
> > 
> >   foreach(var ${PACAKGE_HELPER_PATH_VARS})
> >   
> >     if(NOT DEFINED ${var})
> >     
> >       message(FATAL_ERROR ...)
> >     
> >     else if(IS_ABSOLUTE ${${var}})
> >     
> >       file(RELATIVE_PATH PACKAGE_HELPER_${var} ${CMAKE_INSTALL_PREFIX}
> > 
> > ${${var}})
> > 
> >     else()
> >     
> >       set(PACKAGE_HELPER_${var} ${${var}})
> >     
> >     endif()
> >   
> >   endforeach()
> > 
> > It would be nice to make those PACKAGE_HELPER_* vars local to
> > configure_config_file() function.
> 
> If it's a function(), they are local automatically.
> 
> Also still not tested, but now it should have the right prefix:
> 
> foreach(var ${PACAKGE_HELPER_PATH_VARS})
>   if(NOT DEFINED ${var})
>     message(FATAL_ERROR ...)
>   else if(IS_ABSOLUTE ${${var}})
>     string(REPLACE "${CMAKE_INSTALL_PREFIX}" "\${_PKG_PREFIX_PATH}"
>                     PACKAGE_HELPER_${var} "${${var}}"
>     else()
>       set(PACKAGE_HELPER_${var} ${${var}})
>     endif()
>   else()
>     set(PACKAGE_HELPER_${var} "\${_PKG_PREFIX_PATH}/${${var}}")
>   endif()
> endforeach()

Ok, a working ConfigureConfigFile.cmake is attached, together with example 
files, input and the configured output and the driving CMakeLists.txt.

The call now looks like this:

configure_config_file(BarConfig.cmake.in 
${CMAKE_CURRENT_BINARY_DIR}/BarConfig.cmake
                      INSTALL_DESTINATION "${CMAKECONFIG_INSTALL_DIR}"
                      PATH_VARS INCLUDE_INSTALL_DIR
                                BIN_INSTALL_DIR
                                FOO_INSTALL_DIR ...
                     )


and in the Config.cmake.in file you have to put:

@CONFIG_HELPER_DIRS_INIT@

set_and_check(BAR_INCLUDE_DIR "@CONFIG_HELPER_INCLUDE_INSTALL_DIR@")
set(BAR_DATA_DIR    "@CONFIG_HELPER_DATA_INSTALL_DIR@")


The set_and_check() macro is provided by the @CONFIG_HELPER_DIRS_INIT@, it 
sets the variable and checks that the given directory or file exists.

IMO it's a bit much macro magic.
I'll also try an alternative approach tomorrow.

Comments ?

Alex
-------------- next part --------------

# 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} )

# get_filename_component(CONFIG_PREFIX_DIR "${CMAKE_CURRENT_LIST_DIR}/@CONFIG_RELATIVE_PATH@" ABSOLUTE)

@CONFIG_HELPER_DIRS_INIT@

set_and_check(BAR_INCLUDE_DIR "@CONFIG_HELPER_INCLUDE_INSTALL_DIR@")
set_and_check(BAR_BIN_DIR     "@CONFIG_HELPER_BIN_INSTALL_DIR@")
set(BAR_DATA_DIR    "@CONFIG_HELPER_DATA_INSTALL_DIR@")
set(BAR_BAR_DIR     "@CONFIG_HELPER_BAR_INSTALL_DIR@")
set(BAR_FOO_DIR     "@CONFIG_HELPER_FOO_INSTALL_DIR@")

# 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: CMakeLists.txt
Type: text/x-cmake
Size: 3226 bytes
Desc: not available
URL: <http://public.kitware.com/pipermail/cmake-developers/attachments/20120215/6cf43961/attachment-0006.bin>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: ConfigureConfigFile.cmake
Type: text/x-cmake
Size: 1969 bytes
Desc: not available
URL: <http://public.kitware.com/pipermail/cmake-developers/attachments/20120215/6cf43961/attachment-0007.bin>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: BarConfig.cmake
Type: text/x-cmake
Size: 1219 bytes
Desc: not available
URL: <http://public.kitware.com/pipermail/cmake-developers/attachments/20120215/6cf43961/attachment-0008.bin>


More information about the cmake-developers mailing list