Compute binary filename from "stem" name without caching
In cases where dependencies of a project are provided "locally" in some form (either as binary packages or build from source with ExternalProject for example) it is useful to provide config-file packages where the upstream does not.
In such cases, we know the directory location of the binaries already, but the file name follows a platform-specific pattern which may or may not include a lib
prefix and a so
or dll
etc file extension. CMake is aware of these differences and makes use of them in the find_*
commands.
The problem is that using find_*
commands should really only be used in module-file packages because module-file packages really do have to find things, whereas with config-file packages, the location of everything is determined already by the existence of the config-file package itself.
Use of find_
commands in hand-written config-file packages means that
- The user has to be very careful to use
PATH
to specify the path to the library andNO_DEFAULT_PATH
to ensure that the library is found within the prefix and not from the system or elsewhere. - The result is cached and presented to the user in
ccmake
/cmake-gui
and available for the user to change to an arbitrary path which may not be coherent with the rest of the package. It is possible to mark variables as "advanced", but such variables are also still presented to the user. "Advanced" doesn't mean "users never see this".
It is possible to use
find_library(BZIP_LOC
bz2
PATH "${KNOWN_EXTRACTED_PACKAGE_PREFIX}/lib"
NO_DEFAULT_PATH
)
set(BZIP_LOC ${BZIP_LOC} CACHE INTERNAL "")
to avoid the cache variable showing up even under "Advanced", but this is cumbersome.
It also has the disadvantage that the variable is still cached. With normal (cmake-install-command-generated) config-file packages, I only have to change one _DIR
variable to completely specify a different location for the package after generating the first time. If I do that with a config-file package which uses find_
commands, I would have to specify new values for both the _DIR
and any other cache variables resulting from the find_
command usage.
So, I can eventually arrive at
find_library(BZIP_LOC_C
bz2
PATH "${KNOWN_EXTRACTED_PACKAGE_PREFIX}/lib"
NO_DEFAULT_PATH
)
set(BZIP_LOC ${BZIP_LOC_C})
unset(BZIP_LOC_C CACHE)
which doesn't leave a populated cache and which does have the platform-specific behavior of the find_
commands, and which I can wrap into a generic command:
function(uncached_find_library VAR_NAME LIB_NAME LIB_PATH)
find_library(${VAR_NAME}_C
${LIB_NAME}
PATH "${LIB_PATH}"
NO_DEFAULT_PATH
)
set(${VAR_NAME} ${${VAR_NAME}_C} PARENT_SCOPE)
unset(${VAR_NAME}_C CACHE)
endfunction()
uncached_find_library(BZIP_LOC bz2 ${KNOWN_EXTRACTED_PACKAGE_PREFIX}/lib)
message("BZIP_LOC ${BZIP_LOC}")
It might be worth adding an API to CMake which can do the platform-specific finding, without the side-effect of caching the result in cases where that is not desired.