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

Alexander Neundorf neundorf at kde.org
Thu Feb 16 02:24:12 EST 2012


On Wednesday 15 February 2012, Brad King wrote:
> On 2/15/2012 4:50 PM, Alexander Neundorf wrote:
> > Ok, a working ConfigureConfigFile.cmake is attached, together with
> > example files, input and the configured output and the driving
> > CMakeLists.txt.
> 
> Nice!
> 
> Alternative name ideas:
> 
>    CMakePackageHelper     [1]
>    ConfigureCMakePackage
>    ConfigureCMakePackageFile
>    ConfigurePackage
>    ConfigurePackageFile
>    ConfigurePackageConfig
> 
> [1] Generic name for helper APIs so we can add more macros later.
> In this case the macro can perhaps be called:
> 
>    cmake_package_config


We have already write_basic_config_version_file(), and I wanted to have the 
name somewhat similar, so I decided for the configure_config_file().
If we decide for something else, the write_basic_config_version_file() should 
be changed/wrapped also accordingly.
E.g. configure_package_file() and write_basic_package_version_file().

I was thinking about putting it into a file which may have a different name, 
maybe CMakeConfigHelpers.cmake, which should then also 
include(WriteBasicConfigVersionFile), so you get both when you include it.

 
> > 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 ...
> >                       
> >                       )
> 
> Good.  Note that configure_file automatically treats a relative path
> for the output file w.r.t. the build tree.  Therefore the second arg
> can be just "BarConfig.cmake".

Yes, it's just to make it really obvious where it is going.

> > and in the Config.cmake.in file you have to put:
> > 
> > @CONFIG_HELPER_DIRS_INIT@
> 
> Good.  Did you consider other prefixes?  I'm okay with CONFIG_HELPER_
> but I wonder if there is something better.  Alternatively it could
> be configured by an option to the macro.


It should match with the other variable names which are generated, and they 
use the CONFIG_HELPER_ prefix.
I thought about making the prefix configurable, but did not really find it 
necessary. Those variables are replaced anyway by the configure_file() call.
 
> > 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.
> 
> Okay.  The set_and_check macro is perhaps overkill.  I've never
> done an explicit existence check on such directories in a package
> configuration file.  

Yes, but I think it's better to do it.
The export targets files do this now, and by checking that the directories 
exist, the Config.cmake file is really connected to the files it references, 
and not just a text file which contains some settings, which are hopefully 
correct.
I mean, this Config.cmake file and the exported targets file are somewhat 
similar to pkgconfig pc-files and those weird libtool la files, i.e. they 
contain information about something else.
With Find-modules this is different, they search for a file existing on the 
file system, so if find_path() says it found the file, it is really there.
OTOH if find_package() found a Config.cmake file, it really only guarantees 
that it found the Config.cmake file (and since 2.8.6 also that the libraries 
for the exported targets really do exist), but without checking it does not 
guarantee that the include directories etc. reported from that file actually 
exist.
Packages may be packaged wrongly, or an installation may be messed up, or 
something.

Another option would be:

set(FOO_DIR ... )
set(BAR_DIR ... )
set(BLUB_DIR ...)

foreach(dir FOO_DIR BAR_DIR BLUB_DIR)
  if(NOT EXISTS ${dir]})
    message(FATAL_ERROR "....")
  endif()
endforach()

But this would require extra work by the Config.cmake file author, while with 
using set_and_check() this is almost no extra work.

Alex



More information about the cmake-developers mailing list