[CMake] Apply FIND_PACKAGE_HANDLE_STANDARD_ARGS() on COMPONENTS

Alexander Neundorf a.neundorf-work at gmx.net
Mon Apr 26 16:07:46 EDT 2010


On Sunday 25 April 2010, Michael Hertling wrote:
> On 04/22/2010 09:55 PM, Alexander Neundorf wrote:
> > On Thursday 22 April 2010, Michael Hertling wrote:
> >> 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 -
> >
> > Well, find_package() could be enhanced to set this considering the
> > specified COMPONENTS. [...]
>
> I'm in doubt if this is the right way, and you, Alex, once have been in
> doubt, too: <http://www.cmake.org/Bug/view.php?id=5920>, Note #0010405:
> "[...] this means FOO_FOUND is only set to TRUE if all components have
> been found, right ? Is this the expected behaviour ? I'm not sure."

Yes, I know. And I'm still not sure enough to just go ahead and commit 
something.
It's good that we have that discussion now.

> I'm not, too: For a single-component package, you've an all-or-nothing
> situation which can be perfectly summed up by a sole boolean variable.
> For a multi-component package, you've the states "all", "nothing" and
> intermediate "partials", and a boolean variable is, IMHO, neither
> sufficient nor appropriate to comprise all possible outcomes of
> FIND_PACKAGE() in such a case. Therefore, the interpretation of
> XXX_FOUND should be restricted, roughly like the following:
>
> FALSE: Nothing of XXX has been found at all - don't try to use it; in
> particular, don't rely on any other variable related to XXX to have a
> defined value. [The latter is config mode not finding a config file.]
> TRUE: Basically, XXX has been found, but for any information about the
> available components, refer to their specific variables, in particular
> XXX_YY_FOUND, as provided by the find module or the config file.

But I could check XXX_YY_FOUND also without specifying COMPONENTS. That's what 
FindQt4.cmake does.

> This interpretation is compliant to the behaviour of FIND_PACKAGE() in
> config mode and preserves the possibility to reliably request optional
> components from a package as I've pointed out in this thread recently.
> Obviously, it implies that XXX_FOUND could be TRUE although not all
> requested components have been found.

This also means that if REQUIRED is specified, the find_package() would not 
fail even if some of the listed components have not been found ?
Or, in other words, what you write about XXX_FOUND, does this apply the same 
way to the REQUIRED argument ?

> > [..] There hasn't been much discussion about how the COMPONENTS
> > arguments should be interpreted until now.
>
> OK, let me try to contribute. From a module designer's perspective,
> things are quite clear: XXX_FIND_QUIETLY and XXX_FIND_REQUIRED get the
> QUIET and REQUIRED options, and components go into XXX_FIND_COMPONENTS.
> What we'd need is a guideline how the results of FIND_PACKAGE() should
> be set up and interpreted when components come into play. My suggestion:
>
> 1) Recommend to interpret XXX_FOUND in then above-mentioned manner.
> 2) Urge the module designers to document which components can be
>    requested with FIND_PACKAGE() and if they must be requested
>    explicitly or if they are searched automatically.
> 3) To support the handling of components, provide a function like:
>
> FUNCTION(FIND_COMPONENT_HANDLE_STANDARD_ARGS PKG CMPNT MSG VAR0)
>     # Prepare forwarding variables:
>     SET(${PKG}_${CMPNT}_FIND_QUIETLY ${${PKG}_FIND_QUIETLY})
>     SET(${PKG}_${CMPNT}_FIND_REQUIRED ${${PKG}_FIND_REQUIRED})
>     # Delegate the actual work:
>     FIND_PACKAGE_HANDLE_STANDARD_ARGS(
>         ${PKG}_${CMPNT} ${MSG} ${VAR0} ${ARGN}
>     )
>     # Propagate the result:
>     SET(${PKG}_${CMPNT}_FOUND ${${PKG}_${CMPNT}_FOUND} PARENT_SCOPE)
> ENDFUNCTION()
>
> This wrapper around FIND_PACKAGE_HANDLE_STANDARD_ARGS() handles a
> single component in the same way the latter handles a package; in
> particular, it respects the package's QUIET and REQUIRED options,
> and finally, it sets up the component's XXX_YY_FOUND variable as
> demanded in Modules/readme.txt for a package XXX's "part" YY.
>
> 4) Slightly edit Modules/readme.txt to reflect the changes.
>
> Further measures, e.g. concerning FIND_PACKAGE(), aren't needed.
>
> Of course, I would be especially interested in your opinion, Alex,
> since the related issue #5920 is still open and marked as urgent.

I was actually almost about to close this issue with "no change required", see 
my last comment there. So, I think that this issue currently has "Urgent" 
does not matter much.

Alex


More information about the CMake mailing list