Reputation: 1713
For some reason I want to extend a find module (FindThreads
in my case) to do some specific stuff if CMake's FindThreads
fails. For the ordinary developer of other parts of our software system this should happen transparently, such that s/he could call find_package(Threads)
as usual, so I don't want to give my own find module an exclusive name.
My idea is to add my own FindThreads.cmake
in a folder contained in the CMAKE_MODULE_PATH
. Because CMAKE_MODULE_PATH
has priority find_package(Threads)
will execute my own FindThreads.cmake
.
But, inside my own FindThreads.cmake
I need to execute find_package(Threads ...)
such that it executes CMake's original FindThreads.cmake
. How to do that?
If that fails my own FindThreads.cmake
should try to add a specific Threads lib.
Unfortunately, there is no option NO_CMAKE_MODULE_PATH
for find_package
to fall back to CMake's own find modules and it seems not to be possible to pass a search path (for example ${CMAKE_ROOT}/Modules
) to find_package
to override CMAKE_MODULE_PATH
.
Upvotes: 3
Views: 305
Reputation: 46
When overriding upstream CMake find modules, it depends on what needs to be overridden. In most cases the include()
can be used inside the local find module. For example, a local find module:
# cmake/modules/FindThreads.cmake
# Adjustments before including the upstream find module... For example,
# adding additional search paths, names etc.
# Find package with upstream CMake find module.
include(${CMAKE_ROOT}/Modules/FindThreads.cmake)
# Adjustments after including the upstream find module... For example,
# to add additional result variables etc.
Then local find module is used:
# CMakeLists.txt
# ...
list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR}/cmake/modules)
# ...
find_package(Threads)
In this example, the absolute path to the upstream find module is used to prevent the maximum nesting/recursion depth error on some systems, like macOS. Otherwise CMake would recursively try to include local find module if include(FindThreads)
or find_package(Threads)
would be used inside the local find module.
Upvotes: 0
Reputation: 859
You could create a macro like this:
FindPackageWrapper.cmake
:
macro(find_package_wrapper MODULE_PATH)
set(_OLD_CMAKE_MODULE_PATH "${CMAKE_MODULE_PATH}")
set(CMAKE_MODULE_PATH "${MODULE_PATH}")
find_package(${ARGN})
set(CMAKE_MODULE_PATH "${_OLD_CMAKE_MODULE_PATH}")
unset(_OLD_CMAKE_MODULE_PATH)
endmacro()
And then use it like this:
include(FindPackageWrapper.cmake)
find_package_wrapper(${CMAKE_ROOT}/Modules Threads ...)
The macro is needed to provided the created variables in the parent scope. In a function the find_package results would get lost.
Upvotes: 0
Reputation: 66061
You may set CMAKE_MODULE_PATH
before find_package
call and restore the variable after the call:
# Save old value of CMAKE_MODULE_PATH.
set(CMAKE_MODULE_PATH_OLD ${CMAKE_MODULE_PATH})
# Temporary replace CMAKE_MODULE_PATH
set(CMAKE_MODULE_PATH "${CMAKE_ROOT}/Modules")
# Call find_package() with specific CMAKE_MODULE_PATH set.
find_package(Threads ...)
# Restore CMAKE_MODULE_PATH
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH_OLD})
Note, that FindXXX.cmake
is executed in the same scope as the caller code, so restoring CMAKE_MODULE_PATH
variable is needed even if your script no longer calls find_package
but simply returns.
Also, it is better to use some unique variable's name instead of CMAKE_MODULE_PATH_OLD
: it is possible that caller already uses that variable for its own purposes. E.g. you may add some suffix to the variable's name which related to your organization or is unlikely to be used by others.
Upvotes: 3