Dear CMake community, dear CMake developers, until recently, there has been some considerations w.r.t. the applicability of FIND_PACKAGE_HANDLE_STANDARD_ARGS() to components requested by FIND_PACKAGE() with the COMPONENTS|REQUIRED option, see <http://www.cmake.org/Bug/view.php?id=5920> and the initial discussion at <http://www.cmake.org/pipermail/cmake/2007-October/017068.html>. To this, I would like to make the following proposal:
Given a package XXX with a component YY being requested by FIND_PACKAGE(XXX ... COMPONENTS ... YY ...) or FIND_PACKAGE(XXX ... REQUIRED ... YY ...), and imagine FIND_PACKAGE() would provide the following new variables to FindXXX.cmake or XXXConfig.cmake or xxx-config.cmake, respectively: XXX_YY_FIND_REQUESTED: True if component YY of package XXX is requested, either by COMPONENTS or as REQUIRED XXX_YY_FIND_REQUIRED: True *only* if XXX is requested as REQUIRED XXX_YY_FIND_QUIETLY: True if XXX is requested as QUIET Having these variables availabe, one could handle a requested component YY of package XXX, e.g. a library, as follows - just a simple example: IF(XXX_YY_FIND_REQUESTED) # Component YY of package XX was requested with COMPONENTS or # REQUIRED option; in either case, we'll do our very best: FIND_LIBRARY(XXX_YY_LIBRARY xxxyy ...) FIND_PATH(XXX_YY_INCLUDE_DIR xxx/yy.h ...) # Now, due to the suitably named variables XXX_YY_FIND_REQUIRED and # XXX_YY_FIND_QUIETLY, FIND_PACKAGE_HANDLE_STANDARD_ARGS() can be # applied to YY in an immediate manner: FIND_PACKAGE_HANDLE_STANDARD_ARGS( XXX_YY DEFAULT_MSG|<custom message> XXX_YY_LIBRARY XXX_YY_INCLUDE_DIR ) # Additionally, FIND_PACKAGE_HANDLE_STANDARD_ARGS() has set # XXX_YY_FOUND as being demanded by Modules/readme.txt if # YY is considered a "part" of XXX, like the readme says. # Now, we can extend the officially recommended variables # for libraries and include directories with the results: IF(XXX_YY_LIBRARY) LIST(APPEND XXX_LIBRARIES ${XXX_YY_LIBRARY}) ENDIF() IF(XXX_YY_INCLUDE_DIR) LIST(APPEND XXX_INCLUDE_DIRS ${XXX_YY_INCLUDE_DIR}) ENDIF() # Finally, remove YY from the list of requested components to # preserve the option to handle unknown components at the end: LIST(REMOVE_ITEM XXX_FIND_COMPONENTS YY) ENDIF() The availability of XXX_YY_FIND_REQUIRED and XXX_YY_FIND_QUIETLY, although just copies of XXX_FIND_REQUIRED and XXX_FIND_QUIETLY, would enable FIND_PACKAGE_HANDLE_STANDARD_ARGS() to handle the REQUIRED and QUIET options w.r.t. the component YY in a correct manner and without any modification; in particular, there would be no impact on backward compatibility. The variable XXX_YY_FIND_REQUESTED is just the same as XXX_FIND_REQUIRED_YY, but, IMHO, the latter is somewhat misnamed since it is set to TRUE even if the concerned component wasn't requested as REQUIRED. Of course, one could define these three variables within a find module or config file, but having them defined by FIND_PACKAGE() itself would be much more elegant. In summary, this turns out to be an adaption of variables provided by FIND_PACKAGE() to requirements of FIND_PACKAGE_HANDLE_STANDARD_ARGS() when it comes to components. Alternatively, it could perhaps be worth considering to provide a slightly modified copy of FIND_PACKAGE_HANDLE_STANDARD_ARGS(), say FIND_COMPONENT_HANDLE_STANDARD_ARGS(), with the following signature: FIND_COMPONENT_...(_PACKAGE _COMPONENT _MESSAGE _VAR1) Basically, this function would do the same as FIND_PACKAGE_...(), but takes ${_PACKAGE}_FIND_QUIETLY and ${_PACKAGE}_FIND_REQUIRED as QUIET and REQUIRED flags, and sets up ${_PACKAGE}_${_COMPONENT}_FOUND at the end. Again, this would mean no harm to backward compatibility. 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. >From a user's perspective, FIND_PACKAGE() should yield the same results, regardless if they are obtained by config file or by find module. It is even possible - albeit quite strange - for a package not to provide one single component, but to provide a config file. Consequently, XXX_FOUND should be FALSE if nothing from XXX can be found at all, but if true it should mean: "There is something from XXX present, but for information about the available components, imperatively refer to the XXX_YY_FOUND variables." Or, in other words: XXX_FOUND simply does not carry enough information about available components from a multi-component package, so, IMHO, a component's absence isn't sufficient to negate XXX_FOUND. Any comments, suggestions etc. would be greatly appreciated. Best regards, Michael Hertling _______________________________________________ Powered by www.kitware.com Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html Please keep messages on-topic and check the CMake FAQ at: http://www.cmake.org/Wiki/CMake_FAQ Follow this link to subscribe/unsubscribe: http://www.cmake.org/mailman/listinfo/cmake