[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