[CMake] I'm confused with Find*.cmake and *-config.cmake

Michael Hertling mhertling at online.de
Tue Apr 20 03:27:23 EDT 2010


On 04/19/2010 10:07 PM, Benoit Thomas wrote:

> I'm using an external library which is already compiled. I have wrapped 
> the library in a MyLib.cmake and use it in cmake as an imported library. 
> It works fine, but since the include line uses relative path, it changes 
> from projects to projects and in some case it looks just wrong.

Just for my understanding: What exactly do you mean with "wrapped the
library in a MyLib.cmake" and "use it in cmake as an imported library"?

> I want to change this to something more like:
> 
> find_package (MyLib)
> include (MYLIB_CMAKE_FILE)
> # add_executable and stuff
> target_link_libraries (MyExe MyLib)

This is a possible approach which is also followed by FindQt4.cmake,
but, for several reasons, you shouldn't explicitly refer to "MyLib"
in TARGET_LINK_LIBRARIES(); use variables from FIND_PACKAGE(MyLib).

> However, I'm not sure if I should create a FindMyLib.cmake file or 
> MyLib-config.cmake. [...]

MyLibConfig.cmake or mylib-config.cmake, as MW pointed out recently.

> [..] Both seems to eventually do the same, [...]

Nearly - at least to my present understanding.

> [...] but I don't 
> really understand what are the differences.

Search procedure and MyLib_FOUND, mainly; see below.

> When I looked at some Find*.cmake file (FindSWIG for example) it has a 
> UseSWIG.cmake file. Syntax looks like what I'm trying to achieve, but 
> the none of the Use* files I've check create imported libray, so I guess 
> this is not the way to go.

Yes, you probably want to go with config files.

> In the book, there is an example which seems to do more what I want and 
> use *-config.cmake, which give something like
> 
> find_package (MyLib)
> # no include, since the MyLib-config.cmake already took care of the include
> # add_executable and stuff
> target_link_libraries (MyExe MyLib)

What is meant with "took care of the include"? I don't have the book. ;)

> Part of what I don't understand is when a user use the find_package 
> command, is he expecting to load a Find* file or a *-config file (or he 
> doesn't care?), [...]

In general, he doesn't care; in particular, she can tell
FIND_PACKAGE() to look for a config file exclusively.

> [...] and is he expecting a specific behavior from each file, 

Again to my present understanding: ${CMAKE_ROOT}/Modules/readme.txt.

> [...] And would it be a surprise for the user if the 
> find_package(MyLib) add a MyLib target into his project ? [...]

As for myself: Yes, absolutely. FIND_PACKAGE(MyLib) should try to find
anything necessary to use Mylib, i.e. preprocessor definitions, include
directories, libraries etc., and communicate the results as variables,
e.g. MyLib_DEFINITIONS, MyLib_INCLUDE_DIRS, MyLib_LIBRARIES etc., but it
should not have a direct, hard-coded impact on the configuration process
as a target definition would be; this should be reserved for the calling
CMake script. BTW, why would you need a target "MyLib" here? As you said
before, the library is external and already compiled.

> [...] And is using 
> find_package appropriate for this kind of situation [...]

As far as I understand your concern: Yes, it is.

> [...] and I got it all 
> wrong :) ?

Being on the right way... :)

> Bottom line, I'm looking for a way to write my projects so that if 
> someone else with cmake experience look into them, it will feel like 
> "common" cmake project (if such thing exists) and not something I'm the 
> only one to understand...

Good intention, feel encouraged.

> (Sorry if this sound confusing)

No, sounds like reasonable questions.

As MW has already pointed out, FindXXX.cmake is usually intended to be
installed apart from its package, e.g. in ${CMAKE_ROOT}/Modules, while
XXXConfig.cmake is installed in, say, ${CMAKE_INSTALL_PREFIX}/share/XXX.
Moreover, FindXXX.cmake and XXXConfig.cmake (uppercase without hyphen)
or, respectively, xxx-config.cmake (lowercase with hyphen) differ
w.r.t. the search procedure; roughly speaking:

If FIND_PACKAGE(XXX ...) is called with the usual, simple set of
parameters, it will look for a "find module" named FindXXX.cmake in
${CMAKE_MODULE_PATH} and ${CMAKE_ROOT}/Modules; if no find module is
found or FIND_PACKAGE() is explicitly told to do so, it continues by
looking for a "config file" named XXXConfig.cmake or xxx-config.cmake,
following a sophisticated search procedure. E.g., amongst others, any
bindir in $PATH is searched as <bindir>/../share/XXX; i.e., if you've
installed your project XXX in $HOME having XXXConfig.cmake written to
$HOME/share/XXX, and if $HOME/bin is in your path, then your project's
config file is found automatically as $HOME/share/XXX/XXXConfig.cmake.

Since find modules and config files are both loaded by FIND_PACKAGE()
they are - AFAIK - expected to follow the same guidelines worded in
${CMAKE_ROOT}/Modules/readme.txt, but there's at least the following
aspect in which they differ again: FindXXX.cmake usually set XXX_FOUND
to FALSE if XXX isn't found, however, but if FIND_PACKAGE() is lead to
XXXConfig.cmake or xxx-config.cmake, i.e. a config file, XXX_FOUND is
set to TRUE automatically as finding the config file indicates the
presence of the corresponding package.

My advice: Write a MyLibConfig.cmake file which sets variables like
MyLib_DEFINITIONS, MyLib_INCLUDE_DIRS, MyLib_LIBRARIES etc. to values
needed to use MyLib from another project. Install MyLibConfig.cmake to
${CMAKE_INSTALL_PREFIX}/share/MyLib or the like. Then, from the other
project's CMakeLists.txt files:

FIND_PACKAGE(MyLib)
ADD_DEFINITIONS(${MyLib_DEFINITIONS})
INCLUDE_DIRECTORIES(${MyLib_INCLUDE_DIRS})
# Add your target here.
TARGET_LINK_LIBRARIES(YourTarget ${MyLib_LIBRARIES})

If MyLib is installed in a proper place, see above, you even don't have
to tell CMake where to find it; otherwise, consider CMAKE_PREFIX_PATH
from the command line or via ccmake et al.

'hope this helps a little bit, and to CMake experts: Feel free to beat
me if I'm telling nonsense, but give some enlightenment afterward. ;-)

Best regards,

Michael Hertling


More information about the CMake mailing list