[CMake] Confusion on how find_package works.

Miguel A. Figueroa-Villanueva miguelf at ieee.org
Thu Jan 15 07:42:37 EST 2009


On Thu, Jan 15, 2009 at 12:15 AM, Philip Lowman wrote:
> On Wed, Jan 14, 2009 at 10:54 PM, Robert Dailey wrote:
<snip>
>
> It's not the only one.  There are many modules that lack _LIBRARIES.
> Somebody needs to fix them all but there is some confusion over how
> _LIBRARIES works that needs explaining (sorry to hijack your thread).

Refer to my reply to Robert:

http://www.cmake.org/pipermail/cmake/2009-January/026431.html

> Most of the Find Modules do this:
>
> IF(FOO_FOUND)
>    SET(FOO_LIBRARIES ${FOO_LIBRARY})
> ENDIF()
>
> I have been advised to do this (and I prefer it)
>
> SET(FOO_LIBRARIES ${FOO_LIBRARY})
>
> Can we get some clarification on this?  The former form will not cause an
> error if someone links a target against ${FOO_LIBRARIES} because
> FOO_LIBRARIES will be undefined and not set to FOO-NOTFOUND.  Is this by
> design?  Is there a good reason to do this I'm not aware of?
>
> Is the rationale to allow user code to be shorter, like this?
>
> target_link_libraries(foo baz bimble blagojevich ${FOO_LIBRARIES}
> ${BAZ_LIBRARIES})
>
> At first glance someone new to CMake might have no clue that FOO_LIBRARIES
> or BAZ_LIBRARIES might be optional depedencies and be empty variables.
> Wouldn't it be better to encourage users to write code like this?
>
> target_link_libraries(foo baz bimble blagojevich)
> IF(FOO_FOUND)
>    target_link_libraries(foo ${FOO_LIBRARIES})
> endif()
> if(BAZ_FOUND)
>    target_link_libraries(foo ${BAZ_LIBRARIES})
> endif()
>
> And if that is the case, wouldn't a good default for the future be to simply
> do this in all new modules?
> SET(FOO_LIBRARIES ${FOO_LIBRARY})

I don't have the time to think of all the ramifications this might
have and I don't really have an opinion on which is better. To me the
above discussion is really missing the point. That is, it is difficult
to think of all the possible ways a user might use a package
(specially with packages that have multiple libraries). You might be
linking optionally, or to a subset, or optionally to a subset, etc.

So, what should be clear is that if <prefix>_FOUND is FALSE, you
should not use <prefix>_LIBRARIES or any other variable from that
module (again, making the above discussion irrelevant). In the case of
packages with multiple libraries, then you might need to inspect the
different XXX_YYY_FOUND variables.

If you require the module and do not want to encapsulate your code in
a bunch of IF(<prefix>_FOUND) statements, then you can simply use the
REQUIRED keyword:

find_package(<prefix> REQUIRED)
...

This will cause an error and bail out. Note that this is not a
guarantee that all modules will work that way, rather it is how they
are supposed to work if they follow the readme.txt.

Hope that helps.

--Miguel


More information about the CMake mailing list