On 02/10/2011 09:17 PM, Adams, Brian M wrote: > I'm curious if the behavior I'm seeing with respect to FindBoost.cmake is > expected. (I realize I'm using these macros in a convoluted way, so > understand if I can't make it work more cleanly.) > > What I'd like to be able to do is something like the following to probe for a > system-provided or user-specified Boost, but then fall back on a distributed > one that comes with our software as needed (probably in config instead of > module mode, but that's for another day): > > find_package(Boost 1.40) > if (NOT Boost_FOUND) > set(BOOST_ROOT /path/to/boost/in/our/tree) > find_package(Boost 1.40 REQUIRED) > endif() > > I get problems with this, e.g., on RHEL5, which has Boost 1.33 installed. > The first find fails due to version too low, then the second find doesn't > probe because it detects Boost settings in the cache. After the first probe > (and in the end) Boost_FOUND is false, AND the include and lib dirs for Boost > are set to the 1.33 install location, which is misleading. It seems odd to > me that these variables get set even though the probe failed. > > I can perform a workaround where I trick FindBoost.cmake to not use the cache: > > find_package(Boost 1.40) > if (NOT Boost_FOUND) > unset(Boost_INCLUDE_DIR CACHE) > # these not needed, but could do to be safe: > #unset(Boost_LIBRARY_DIRS CACHE) > #unset(Boost_LIB_VERSION CACHE) > #unset(Boost_VERSION CACHE) > set(BOOST_ROOT /path/to/boost/in/our/tree) > find_package(Boost 1.40) > endif() > > Then I end up with the 1.40 that I'd expect. This seems likely to bite me > down the road. How (besides requiring the user to have sufficiently new > Boost on their system), should I handle this? > > Thanks, > Brian
Without having inspected FindBoost.cmake in detail, I think what you report here is a fundamental problem of find modules in general: They don't clean up if they're about to return with a negative result, i.e. XXX_FOUND==FALSE. Particularly, they leave variables in the cache that stem from diverse find function calls, and if some of these calls have succeeded, a following invocation of the same module can't perform the search again because the find functions are prevented to do so by the positive results in the cache. Even quite simple find modules like FindJPEG.cmake show that behaviour: Suppose you've the runtime component, i.e. the library only, installed from the distribution and another full installation in, say, /opt/jpeg. If you say FIND_PACKAGE(JPEG) without hinting CMake at the latter path, you would end up with JPEG_FOUND==FALSE as well as JPEG_INCLUDE_DIR== JPEG_INCLUDE_DIR-NOTFOUND but JPEG_LIBRARY==/usr/lib/libjpeg.so, so a following FIND_PACKAGE(JPEG) with, e.g., CMAKE_PREFIX_PATH==/opt/jpeg set before will result in JPEG_FOUND==TRUE with JPEG_INCLUDE_DIR==/opt/jpeg/include JPEG_LIBRARY==/usr/lib/libjpeg.so which means a non-matching combination of header and library. While one hardly calls FindJPEG.cmake more than once in this manner, there're quite good occasions to do so with more complex find modules like FindBoost.cmake, especially if they support the specification of a version via FIND_PACKAGE() as your scenario clearly shows, cf. [1]. An obvious solution would be to unset the concerned variables in the cache if the module is going to return with a negative result so that a subsequent invocation of the find module can start all over again. OTOH, if you configure with -DXXX_LIBRARY=... on the command line or a GUI, you'd probably expect this to be respected by all invocations of FindXXX.cmake throughout the entire project, so the module would need to keep track of which variables are passed in from the outside and which ones are actually set by the module. Of course, this would complicate things a lot when writing find modules. IMO, the best approach to address this issue in your case is the one you presented above: Explicitly unset the concerned variables in the cache before performing the search again with a modified BOOST_ROOT. Alternatively, you might simply bail out if Boost 1.40 has not been found and instruct the user to throw away the cache and reconfigure with BOOST_ROOT set appropriately - or provide a dedicated option, e.g. USE_INTERNAL_BOOST, to handle this in your CMakeLists.txt. Note that there's no such issue with configuration files: A negative result from FIND_PACKAGE() in config mode means that no config file has been found or all version files have declared their package as incompatibe. In either case, no config file has been processed, so there can't be any legacies in the cache. Regards, Michael [1] http://www.mail-archive.com/[email protected]/msg34515.html _______________________________________________ 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
