[CMake] Code and API review request for Qt5 CMake files
Michael Hertling
mhertling at online.de
Wed Feb 29 21:36:33 EST 2012
On 02/28/2012 10:03 PM, Alexander Neundorf wrote:
> ...will reply later in detail.
>
> Could you please go through the existing find-modules shipped with cmake which
> support COMPONENTS and make a summary of how they handle them ?
>
> At least FindQt4.cmake be default searches all components.
>
> Thanks
> Alex
The following CMakeLists.txt can be used to systematically investigate
the results of the component-aware find modules currently shipped with
CMake, these are Find{Boost,GTK2,HDF5,ImageMagick,Java,OpenSceneGraph,
Qt4,wxWidgets,XMLRPC}:
CMAKE_MINIMUM_REQUIRED(VERSION 2.8 FATAL_ERROR)
PROJECT(FINDRESULTVARIABLES C CXX)
SET(CMAKE_VERBOSE_MAKEFILE ON)
FUNCTION(FindResultVariables pkg)
SET(prefix ${pkg})
IF(DEFINED ARGV1)
SET(prefix ${ARGV1})
ENDIF()
UNSET(REQUIRED)
IF(${pkg}_REQUIRED)
SET(REQUIRED REQUIRED)
ENDIF()
FIND_PACKAGE(${pkg} COMPONENTS ${${pkg}_COMPONENTS} ${REQUIRED})
MESSAGE("Begin: ${pkg} result variables")
GET_DIRECTORY_PROPERTY(v VARIABLES)
FOREACH(i IN LISTS v)
IF(i MATCHES "^${prefix}.*_FOUND$")
MESSAGE("${i}=${${i}}")
ENDIF()
ENDFOREACH()
MESSAGE("${prefix}_LIBRARIES: ${${prefix}_LIBRARIES}")
MESSAGE("End: ${pkg} result variables")
ENDFUNCTION()
FindResultVariables(Boost)
FindResultVariables(GTK2)
FindResultVariables(HDF5)
FindResultVariables(ImageMagick)
FindResultVariables(Java)
FindResultVariables(OpenSceneGraph)
FindResultVariables(Qt4 QT)
FindResultVariables(wxWidgets)
FindResultVariables(XMLRPC)
HDF5, OpenSceneGraph and XMLRPC aren't installed on my system; my
preliminary findings for the remaining packages are as follows:
(1) Searching unrequested components:
Qt4: Yes.
GTK2,ImageMagick: Partially.
wxWidgets: All components if none are requested.
The remaining modules don't search unrequested components.
(2) Assigning *_*_FOUND variables:
Qt4: Only for modules which are known and found.
ImageMagick: Also for requested but unknown components.
wxWidgets: No *_*_FOUND variables at all but forwards unknown
components to *_LIBRARIES variable without an error.
The remaining modules assign only to *_*_FOUND variables for
components which they know and which have been requested.
(3) Respecting the REQUIRED flag:
wxWidgets: REQUIRED ignored completely.
Boost: SEND_ERROR instead of FATAL_ERROR.
GTK2,Java: Bail out on unknown components even if not REQUIRED.
The remaining modules bail out on unavailable requested components.
(4) Assinging the package-related *_FOUND variable:
Java: No *_FOUND variable at all although it's documented.
wxWidgets: TRUE even if requested components aren't found, see above.
The remaining modules return FALSE if a requested component isn't found.
My comments on these, say, multifarious findings are:
Ad.(1): In general, automatically searching unrequested components
does not mean a harm, but it is also not beneficial at all events:
- No guarantee to catch all components - consider a component added
later to the package - so no guarantee that all later *_*_FOUND
variables have been assigned a definite value by FIND_PACKAGE().
- Complicates find modules / config files due to REQUIRED/QUIET.
- Potentially higher costs due to unneeded search operations.
For the latter loint, there is a not-so-uncommon use case: Suppose
a find module wants to check whether a library matches its header.
Putting away cross-compiling issues for the moment, this requires
building and running a test program. If it is to be performed for
each Qt4 module, e.g., a FIND_PACKAGE(Qt4) invocation would most
certainly be quite expensive. For these reasons, I usually advice
to search only requested components, request all components going
to be used and refer only to components having been requested.
Ad.(2): Due to my guiding principle - refer only to FOUND variables
which have been assigned a definite value by FIND_PACKAGE() - I do
consider as important that a *_*_FOUND variable is assigned to for
each requested component. FindImageMagick.cmake does it right, but
the other modules - except for FindwxWidgets.cmake - have me check
*_*_FOUND variables without a definite value for requested but un-
known components. Again: The latters might become known one day.
Ad.(3): After FIND_PACKAGE(... REQUIRED), I definitely do not want
to check if all requested components including their prerequisites
are actually present. OTOH, the user must have the oppurtunity to
handle a package's or a component's absence by h(is|er)self. Thus,
FIND_PACKAGE() without REQUIRED should never bail out because of
something being not found, but with REQUIRED, it must bail out.
Ad.(4): None of the modules returning *_FOUND==FALSE just because
a component is missing could be turned into a config file at the
moment without changing its behavior. In order to address this
issue in the future, one has to decide if either
- a find module should behave like a config file in this regard and
return *_FOUND==FALSE only if the package is totally unavailable;
my favorite, or
- FIND_PACKAGE() should should allow config files to assign FALSE to
*_FOUND if a requested component is unavailable; your favorite, I
guess.
In the latter case, the components' *_*_FOUND variables would need
to be assigned to also, and if no config file has been found, this
must be done by FIND_PACKAGE() autonomously. Though, the *_*_FOUND
variables are just a convention of Modules/readme.txt whereas the
package's *_FOUND variable is documented for FIND_PACKAGE(); this
is a different quality. Finally, consider the following use case:
Suppose a package X with a non-(de)selectable core component and an
additionally selectable component Y; Qt's core module is a perfect
candidate for the former. If FIND_PACKAGE(X COMPONENTS Y) returns
with X_FOUND==FALSE and X_Y_FOUND!=TRUE, how do you determine the
core component's availability, following your favorite approach?
AFAICS, you can't: The results include "X totally unavailable" as
well as "X available without Y". Following my favorite approach,
by contrast, X_FOUND directly indicates the availability of the
core component. That's an example for the neccessity to reliably
detect a package's total presence/absence, and a multi-component
package needs not to be a pure additive entity made of its parts.
My main conclusion from the above-noted mess among CMake's current
component-aware find modules is that we urgently need a convention
how such modules and config files are intended to work. Hopefully,
we can take a step forward; Qt5's advent is a good opportunity.
Regards,
Michael
More information about the CMake
mailing list