[CMake] How to make a ProjectConfig.cmake

Alexander Neundorf a.neundorf-work at gmx.net
Wed Jan 19 13:37:07 EST 2011


On Thursday 30 December 2010, Ian Monroe wrote:
> On Thu, Dec 30, 2010 at 08:08, Michael Hertling <mhertling at online.de> wrote:
> > On 12/30/2010 11:33 AM, Ian Monroe wrote:
> >> To create my QyotoConfig.cmake I need to know the full path of a
> >> library so that I can set a variable like QYOTO_LIBRARY.
> >>
> >> This is pretty standard requirement right? Its what we're supposed to
> >> do in *Config.cmake's?
> >
> > Yes.
> >
> >> So anyways, how do I that? The only target property that hasn't
> >> returned NOTFOUND is LOCATION, which unhelpfully returns the location
> >> of the library in the build directory. I could parse this to get the
> >> file name, and then append it to the library install location... but
> >> that seems like such a hack. Feels like I'm doing something wrong if I
> >> need to use a hack to do something standard.
> >
> > Usually, I'd have a template QyotoConfig.cmake.in which contains
> >
> > FIND_LIBRARY(QYOTO_LIBRARY qyoto
> >    PATHS @CMAKE_INSTALL_PREFIX@/lib
> >    NO_DEFAULT_PATH
> > )
> >
> > and is processed by CONFIGURE_FILE(). If the library is installed with
> >
> > INSTALL(TARGETS qyoto
> >    RUNTIME DESTINATION bin
> >    LIBRARY DESTINATION lib
> >    ARCHIVE DESTINATION lib
> > )
> >
> > the FIND_LIBRARY() in the resulting QyotoConfig.cmake file will find
> > the library right at the installation location but nowhere else, and
> > the platform-dependent file names, e.g. libqyoto.so versus qyoto.dll,
> > are also handled correctly.
> >
> >> I looked at install(EXPORT which could work, but it seems to include a
> >> lot more information then is needed. I just want to set a variable
> >> with the full path to a library.
> >
> > Nevertheless, the imported-targets approach, i.e. the combination of
> > INSTALL(TARGETS ... EXPORT ...) and INSTALL(EXPORT ...) along with an
> > appropriately set up config file, is much more powerful and should be
> > preferred, IMO; see [1] for more information. BTW, as the export file
> > defines the imported targets, its inclusion in the config file should
> > possibly be protected in a suitable way to avoid fatal redefinitions.
>
> The context I'm coming from is that I'm developing stuff that is
> distributed by Linux distributions. The export file has information
> about what the target is dependent on, including full paths. That
> feels like a bad thing to me. What was true about dependencies when a
> package was being built on a build server might not be true later.
>
> ...or maybe its fine? Can someone point me to an example of a package
> distributed by linux distros that uses this feature? Would make me
> feel better to know that I'm not the first person to use it. :)

KDE since 4.2: 
http://techbase.kde.org/Development/CMake_KDE_4_2#New:_Exporting_and_importing_targets :-)

It installs a FindKDE4Internal.cmake (which is basically what a 
KDELibs4Conf.cmake should be, if that feature would have existed already at 
KDE 4.0 time), which is searched by FindKDE4.cmake which comes with CMake. 
This file then includes KDELibsDependencies.cmake, KDEPlatformProfile.cmake, 
KDELibs4ToolsTargets.cmake and KDELibs4LibraryTargets.cmake.

If you look at KDELibs4LibraryTargets.cmake, you'll see that it includes the 
configuration specific targets-file, 
KDELibs4LibraryTargets-relwithdebinfo.cmake in my case.

This has stuff like the following:

# Import target "KDE4__kdeui" for configuration "RelWithDebInfo"
...
SET_TARGET_PROPERTIES(KDE4__kdeui PROPERTIES
                      IMPORTED_LINK_INTERFACE_LIBRARIES_RELWITHDEBINFO
                              "KDE4__kdecore;Qt4::QtSvg;Qt4::QtGui"
                      IMPORTED_LOCATION_RELWITHDEBINFO
                        "/home/alex/Dashboards/installs/2.8.1/kdelibs/lib/libkdeui.so.5.5.0"
                      IMPORTED_SONAME_RELWITHDEBINFO "libkdeui.so.5"
                     )


The line for IMPORTED_LINK_INTERFACE_LIBRARIES_RELWITHDEBINFO is interesting. 
You can see that it lists e.g. "KDE4__kdecore" and "Qt4::QtGui".
KDE4__kdecore is a library target which has been added just a few lines 
earlier, along with its own installed location.

Qt4::QtGui is also a target name. Where does this target come from ?
When FindKDE4.cmake is executed, Qt4 will be searched. Since some time 
FindQt4.cmake now also creates imported targets for its installed libraries, 
named as you can see above.
So cmake will see that kdeui depends on Qt4::QtGui, look for the target 
Qt4::QtGui, and this will have the location set which has been found by 
FindQt4.cmake. FindQt4.cmake currently does a normal search for the Qt 
libraries, so this will be the current location. If Qt would install a 
Qt4Config.cmake, the targets imported there would also have the correct 
current locations.

So, in the long run, imported targets should be created in the Find-modules, 
which will solve the fixed-path issue you see.
Our (KDE's) Windows developers stumbled already over this issue, since in 
their installer you can choose where to install KDE and Qt, so the hardcoded 
paths broke for them. With the new way, where the Qt libs are referenced by 
their imported targets, they are happy (AFAIK).

Alex


More information about the CMake mailing list