[CMake] Apply FIND_PACKAGE_HANDLE_STANDARD_ARGS() on COMPONENTS

Michael Hertling mhertling at online.de
Thu Apr 22 05:14:11 EDT 2010


On 04/21/2010 09:13 PM, Alexander Neundorf wrote:
> On Tuesday 20 April 2010, Michael Hertling wrote:
>> Dear CMake community, dear CMake developers,
>>
> ...
>> There's another aspect related to this I'd like to comment on: During
>> the abovementioned considerations on the bug tracker and the mailing
>> list, the question has arisen if it's reasonable to set XXX_FOUND to
>> FALSE if any of the requested components aren't found. As for myself,
>> I'd say: No, it isn't. Let's have a look at the following scenario:
>>
>> Package XXX normally provides components YY1 and YY2, but for some
>> reason, only YY1 is installed. Moreover, XXX provides a config file
>> XXXConfig.cmake. Now, a project's CMake script requests both YY1/2 by
>> FIND_PACKAGE(XXX COMPONENTS YY1 YY2). As Brad King has pointed out in
>> <http://www.mail-archive.com/cmake@cmake.org/msg15952.html>, finding a
>> config file results in XXX_FOUND to be set to TRUE automatically. Thus,
>> the absence of YY2 does not mean the absence of XXX as a whole in any
>> case, and, notwithstanding, the requesting CMake script should have a
>> chance to proceed even if YY2 isn't available, i.e. the following seems
>> reasonable: XXX_YY1_FOUND=TRUE, XXX_YY2_FOUND=FALSE *but* XXX_FOUND=TRUE.
> 
> I think I don't agree here.
> If I say
> find_package(XXX COMPONENTS YY1 YY2 REQUIRED)
> I think it makes a lot of sense to interpret this as "search package XXX, and 
> I need YY1 and YY2 from it".

OK, the presence of the REQUIRED option makes everything clear: A find
module or a config file bails out if anything is missing - no worry
about the final value of XXX_FOUND. The actual questions arise if
REQUIRED is absent.

> What other reason would I have to give YY1 and YY2 there otherwise ?

Perhaps, because YY2 is optional and I do not want FIND_PACKAGE() to
look for unrequested components, but that's merely my personal habit.

> If it still succeeds if they are not found, why should I list them then ?

It is possible for FIND_PACKAGE() - w/o REQUIRED - to succeed although
listed components aren't found, and *this* is what I'm worrying about.
As Brad King has pointed out in the abovementioned post, FIND_PACKAGE()
in config mode sets XXX_FOUND to TRUE if the config file is found and
processed without errors, and there's nothing one can do against it -
unless explicitly terminating the config file which would not be
expected if REQUIRED is absent. Thus, revisiting your question: It's
possible for it to succeed although they are not found, and this is,
IMHO, not a result of a faultily implemented config file and also the
reason why I recommended against setting XXX_FOUND to FALSE in a find
module if not all requested components are present; XXX_FOUND should,
perhaps, be interpreted in a different manner.

Core question reworded: Is it acceptable to obtain a different setting
from FIND_PACKAGE() depending on loading a find module or a config file?

> I think by default (no COMPONENTS specified) all components should be 
> searched. [...]

Or none. Just spontaneously:

- Searching a component could possibly be quite expensive.
- Populating XXX_{DEFINITIONS,LIBRARIES,INCLUDE_DIRS} with all settings
  to use the whole thing? E.g., FindQt4 behaves different: Just Core+GUI.
- Again, Brad King from above: "Perhaps the project finding Foo just
  wants to load some documentation files from it [...]", i.e. no
  interest in components at all, but only in Foo_ROOT_DIR, e.g.

But, in my opinion, these questions should be a module designer's affair.

> [...] By listing components you can say "I am ok if at least these are 
> found". [...]

Or "Look for these, and ignore any others.", but --> module designer.

> [...] (the man page doesn't say anything about how the "COMPONENTS" should 
> be interpreted).

Regrettably, that's right. For me, the sole reference

"A package-specific list of components may be listed after the REQUIRED
option or after the COMPONENTS option *if no REQUIRED option is given*."

sounds a little bit like COMPONENTS and REQUIRED are intended to be
mutually exclusive, and, indeed, FIND_PACKAGE(... REQUIRED ...) and
FIND_PACKAGE(... COMPONENTS ... REQUIRED) seem not to provide a sole
difference for the find module, only FIND_PACKAGE(... COMPONENTS ...)
without REQUIRED does. Furthermore, one can read in Modules/readme.txt:

"The set of components listed after *either* the REQUIRED option or the
COMPONENTS option will be specified in a XXX_FIND_COMPONENTS variable."

Perhaps, we can get some clarifications w.r.t. the particular intention
of the COMPONENTS option, especially when REQUIRED isn't mentioned, too.

Finally, an example: I have endangered my Qt installation by saying
"# mv libQtXml.so{,.bak}" for testing the following CMakeLists.txt:

CMAKE_MINIMUM_REQUIRED(VERSION 2.8 FATAL_ERROR)
PROJECT(QT_COMPONENT_TEST)
FIND_PACKAGE(Qt4 COMPONENTS QtCore QtGui QtXml REQUIRED)
MESSAGE("QT4_FOUND: <${QT4_FOUND}>")
MESSAGE("QT_QTCORE_FOUND: <${QT_QTCORE_FOUND}>")
MESSAGE("QT_QTGUI_FOUND: <${QT_QTGUI_FOUND}>")
MESSAGE("QT_QTXML_FOUND: <${QT_QTXML_FOUND}>")

When run from a clean directory - no cache and the like - it yields:

[...]
QT4_FOUND: <YES>
QT_QTCORE_FOUND: <1>
QT_QTGUI_FOUND: <1>
QT_QTXML_FOUND: <>
[...]

As you can see, QT4_FOUND is set to YES although the requested - and
even required - component QtXml wasn't found. OK, the modules aren't
authoritative, but I think the FindQt4.cmake is good example to state
the meaning of COMPONENTS/REQUIRED, FOUND variables and the behaviour
of find modules; I'd be very interested. :)

Best regards,

Michael


More information about the CMake mailing list