[cmake-developers] the future of FIND_PACKAGE()

Alexander Neundorf neundorf at kde.org
Mon Jun 26 17:19:11 EDT 2006


Hi,

I guess you already know what this email is about.

Now KDE 4 uses cmake, Boson and Scribus also switched already, the Qt bindings 
for DBUS are built with cmake.
Probably more and more software packages will follow.

This leads to a new problem.

Until now cmake comes with a collection of FindXXX.cmake files. Each of the 
FindXXX.cmake files defines a set of variables and optionally macros required 
for building software which uses this package.
This makes using the FIND_PACKAGE() command very easy, all the more difficult 
things are hidden inside the FindXXX.cmake files:

find_package(Foo)

and you are done.
For the case that really a lot of projects might switch to cmake as native 
buildsystem, it is not realistic to expect that all will commit there 
respective FindXXX.cmake files to cmake cvs.
The FIND_PACKAGE() command checks for two things:
FindXXX.cmake
and XXXConfig.cmake

The FindXXX.cmake file is intended to contain cmake code which searches for 
header and library files. The XXXConfig.cmake files are intended to contain 
the fixed locations of the installed software on the specific system.

"Third party software" can install either a FindXXX.cmake file or a 
XXXConfig.cmake file.
Currently the only way to make additional files available to cmake is to 
either
A) install the modules directly into CMAKE_ROOT/Modules/ 
-this is probably not recommended

B) setting up CMAKE_MODULE_PATH
-this can only be done once you know where to set it to

In KDE4 we have a lot of additional modules, there we do it this way:
we added a small and simple FindKDE4.cmake to cmake cvs, which really only 
tries to find the cmake files installed by kdelibs/, in this case installed 
to KDEDIR/share/apps/cmake/modules/FindKDE4Internal.cmake.
This file is then included and KDEDIR/share/apps/cmake/modules/ is added to 
CMAKE_MODULE_PATH.
I.e. this works only since we have the combination of a simple cmake module 
directly in cmake, and the sophisticated one in 
KDEDIR/share/apps/cmake/modules/.


It would be nice, if not required, if there was a standard way for 3rd party  
software to make its cmake files avaiable to cmake.

There are several options to do this:

1) define a set of directories where cmake searches for files

Currently cmake searches in CMAKE_ROOT/Modules/. This means it only finds the 
modules installed with this version of cmake.
A directory could be defined for 3rd party cmake modules, e.g. 
CMAKE_ROOT/3rdPartyModules/. 3rd party packages could install their files 
directly into this directory, or into subdirs named after the package 
( CMAKE_ROOT/3rdPartyModules/Foo/) or into subdirs named after the package 
with an additional version or install-location suffix 
(CMAKE_ROOT/Foo.usr_local_lib/)

Pros:
-easy for the user to understand

Cons:
-may change the include() and find_package() behaviour
-on systems with multiple versions of cmake only one version of cmake will 
find the modules automatically, since the other cmake version will have a 
different CMAKE_ROOT.
This could be worked around with a command line switch or an environment 
variable -CMAKE_3rdPARTY_MODULE_DIR.

This would mean that KDE 4 doesn't install its files to 
KDEDIR/share/apps/cmake/, but e.g. to CMAKE_ROOT/3rdPartyModules/KDE4/

2) install the cmake files in the installation of the project

This would mean that a project installs its files somewhere indepedent from 
cmake, e.g. to INSTALL_PREFIX/(lib|share)/Foo/cmake/.

Pro:
-available for multiple installed versions of cmake
-no clashes when multiple versions of the same package

Cons:
-it will be hard for cmake to find the modules, since they can end up anywhere 
on the system

This is IMO a major problem.
Until now one can simply do

find_package(Foo)

and FindFoo.cmake can search in all appropriate places on the system for the 
package. With a enhanced version of find_package() this is not possible 
anymore, since cmake will search only in a predefined set of directories, and 
no matter how well they are tuned, there will always be cases where it wont 
work. And then it can only be made to work by setting some options or 
environment variables so that they contain the list of the root directories 
of all packages which haven't been found. This can be a big number, KDE uses 
maybe 15..25 packages. Having to set up a variable which contains 25 
directories wouldn't be practical.

Compared to option 1) there would have to be set up only one directory, the 
central directory where all cmake files are installed to.

-----------------

FindFoo.cmake vs. FooConfig.cmake files

FindFoo.cmake files are generic (and I personally think I like them more). So 
being generic means they should be installed somewhere under share/ and not 
under lib/ (according to the file system hier. standard).

FooConfig.cmake files are not generic and as such shouldn't be installed 
somewhere under lib/ and not under share/.
The cmake module directory is located under share/, so it doesn't fit very 
well for FooConfig.cmake files.
So the location for FooConfig.cmake files should go either to 
INSTALL_PREFIX/lib/Foo/cmake/ or CMAKE_ROOT/Configs/.
The FooConfig.cmake files can probably not be transferred to another 
installation, since they contain the fixed paths, while FindFoo.cmake files 
can be copied.

--------------------

Different types of packages

I think there are at least three different kinds of packages to consider:

1) packages coming with the distribution

these packages know which version of cmake belongs to the distribution, know 
where it's located, and can install their files just to the correct location, 
so that they will be found automatically by cmake

2) packages compiled by the user, using cmake

If a package is compiled from sources by the user with cmake, he has a cmake 
inatalled on the system. In this case it would be possible to put some 
intelligence into cmake so that it can install cmake files in such locations 
so that this cmake will find them.

3) packages compiled by the user, not using cmake but installing cmake files

Such packages don't exist yet, but might exist in the future, in the case that 
cmake becomes the real successor of autotools.
During "make install" it's not reliable that the locations where cmake 
searches are known.
During the configure step of the package it could be checked whether cmake is 
installed on the system and if so it could be queried for its installation 
and search directories (using -P print_some_vars.cmake).

--------------------

How does pkgconfig deal with this issues ?

pkgconfig has very similar issues.
AFAIK software packages install their files into INSTALL_PREFIX/lib/pkgconfig/ 
(-> hint: FooConfig.cmake files should also go under lib/ something). 
pkgconfig searches the files in PKGCONFIG_INSTALL_PREFIX/lib/pkgconfig/, and 
additionally directories listed in some environment variable. This fails on 
many distributions where the environemtn variable is not set up so that it 
contains usual install dirs (e.g. /usr/local/lib/pkgconfig/ is not searched 
by default under both kubuntu and slackware) and the environment variable is 
not known by many users.
The same would be true if cmake relies on some environment variables to be set 
up correctly. 
That's why I would prefer if there would be a defined location under 
CMAKE_ROOT, this would work for all users which have only one version of 
cmake installed (I think this is the big majority), and all other could set 
up one env.var to point to the extra module dir or an cmd line argument.


-------------------

Next week I'm in Trysil ( http://dot.kde.org/1151271635/ ) where I could 
discuss this topic with other KDE core developers, e.g. David.

This issue needs a really good solution.

Bye
Alex
-- 
Work: alexander.neundorf AT jenoptik.com - http://www.jenoptik-los.de
Home: neundorf AT kde.org                - http://www.kde.org
      alex AT neundorf.net               - http://www.neundorf.net



More information about the cmake-developers mailing list