find_package: Add option to prefer Config mode
Add a `CMAKE_FIND_PACKAGE_PREFER_CONFIG` variable to tell `find_package` calls to look for a package configuration file first even if a find module is available. Fixes: #16805, #19236
This commit is contained in:
parent
c365243a3a
commit
26a99da206
@ -59,6 +59,13 @@ for finding the package, checking the version, and producing any needed
|
||||
messages. Some find-modules provide limited or no support for versioning;
|
||||
check the module documentation.
|
||||
|
||||
If the ``MODULE`` option is not specfied in the above signature,
|
||||
CMake first searches for the package using Module mode. Then, if the
|
||||
package is not found, it searches again using Config mode. A user
|
||||
may set the variable :variable:`CMAKE_FIND_PACKAGE_PREFER_CONFIG` to
|
||||
``TRUE`` to direct CMake first search using Config mode before falling
|
||||
back to Module mode.
|
||||
|
||||
Full Signature and Config Mode
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
|
@ -172,6 +172,7 @@ Variables that Change Behavior
|
||||
/variable/CMAKE_FIND_NO_INSTALL_PREFIX
|
||||
/variable/CMAKE_FIND_PACKAGE_NO_PACKAGE_REGISTRY
|
||||
/variable/CMAKE_FIND_PACKAGE_NO_SYSTEM_PACKAGE_REGISTRY
|
||||
/variable/CMAKE_FIND_PACKAGE_PREFER_CONFIG
|
||||
/variable/CMAKE_FIND_PACKAGE_RESOLVE_SYMLINKS
|
||||
/variable/CMAKE_FIND_PACKAGE_WARN_NO_MODULE
|
||||
/variable/CMAKE_FIND_ROOT_PATH
|
||||
|
6
Help/release/dev/find-package-prefer-config.rst
Normal file
6
Help/release/dev/find-package-prefer-config.rst
Normal file
@ -0,0 +1,6 @@
|
||||
find-package-prefer-config
|
||||
--------------------------
|
||||
|
||||
* Variable :variable:`CMAKE_FIND_PACKAGE_PREFER_CONFIG` was added to tell
|
||||
:command:`find_package` calls to look for a package configuration
|
||||
file first even if a find module is available.
|
27
Help/variable/CMAKE_FIND_PACKAGE_PREFER_CONFIG.rst
Normal file
27
Help/variable/CMAKE_FIND_PACKAGE_PREFER_CONFIG.rst
Normal file
@ -0,0 +1,27 @@
|
||||
CMAKE_FIND_PACKAGE_PREFER_CONFIG
|
||||
---------------------------------
|
||||
|
||||
Tell :command:`find_package` to try "Config" mode before "Module" mode if no
|
||||
mode was specified.
|
||||
|
||||
The command :command:`find_package` operates without an explicit mode when
|
||||
the reduced signature is used without the ``MODULE`` option. In this case,
|
||||
by default, CMake first tries Module mode by searching for a
|
||||
``Find<pkg>.cmake`` module. If it fails, CMake then searches for the package
|
||||
using Config mode.
|
||||
|
||||
Set ``CMAKE_FIND_PACKAGE_PREFER_CONFIG`` to ``TRUE`` to tell
|
||||
:command:`find_package` to first search using Config mode before falling back
|
||||
to Module mode.
|
||||
|
||||
This variable may be useful when a developer has compiled a custom version of
|
||||
a common library and wishes to link it to a dependent project. If this
|
||||
variable is set to ``TRUE``, it would prevent a dependent project's call
|
||||
to :command:`find_package` from selecting the default library located by the
|
||||
system's ``Find<pkg>.cmake`` module before finding the developer's custom
|
||||
built library.
|
||||
|
||||
Once this variable is set, it is the responsibility of the exported
|
||||
``<pkg>Config.cmake`` files to provide the same result variables as the
|
||||
``Find<pkg>.cmake`` modules so that dependent projects can use them
|
||||
interchangeably.
|
@ -17,3 +17,6 @@ Set ``CMAKE_FIND_PACKAGE_WARN_NO_MODULE`` to ``TRUE`` to tell
|
||||
:command:`find_package` to warn when it implicitly assumes Config mode. This
|
||||
helps developers enforce use of an explicit mode in all calls to
|
||||
:command:`find_package` within a project.
|
||||
|
||||
This variable has no effect if :variable:`CMAKE_FIND_PACKAGE_PREFER_CONFIG` is
|
||||
set to ``TRUE``.
|
||||
|
@ -499,50 +499,61 @@ bool cmFindPackageCommand::InitialPass(std::vector<std::string> const& args,
|
||||
|
||||
// See if there is a Find<PackageName>.cmake module.
|
||||
bool loadedPackage = false;
|
||||
if (this->UseFindModules && this->FindPackageUsingModuleMode()) {
|
||||
loadedPackage = true;
|
||||
} else {
|
||||
// Handle CMAKE_FIND_PACKAGE_WARN_NO_MODULE (warn when CONFIG mode is
|
||||
// implicitly assumed)
|
||||
if (this->UseFindModules && this->UseConfigFiles &&
|
||||
this->Makefile->IsOn("CMAKE_FIND_PACKAGE_WARN_NO_MODULE")) {
|
||||
std::ostringstream aw;
|
||||
if (this->RequiredCMakeVersion >= CMake_VERSION_ENCODE(2, 8, 8)) {
|
||||
aw << "find_package called without either MODULE or CONFIG option and "
|
||||
"no Find"
|
||||
<< this->Name
|
||||
<< ".cmake module is in CMAKE_MODULE_PATH. "
|
||||
"Add MODULE to exclusively request Module mode and fail if "
|
||||
"Find"
|
||||
<< this->Name
|
||||
<< ".cmake is missing. "
|
||||
"Add CONFIG to exclusively request Config mode and search for a "
|
||||
"package configuration file provided by "
|
||||
<< this->Name << " (" << this->Name << "Config.cmake or "
|
||||
<< cmSystemTools::LowerCase(this->Name) << "-config.cmake). ";
|
||||
} else {
|
||||
aw << "find_package called without NO_MODULE option and no "
|
||||
"Find"
|
||||
<< this->Name
|
||||
<< ".cmake module is in CMAKE_MODULE_PATH. "
|
||||
"Add NO_MODULE to exclusively request Config mode and search "
|
||||
"for a "
|
||||
"package configuration file provided by "
|
||||
<< this->Name << " (" << this->Name << "Config.cmake or "
|
||||
<< cmSystemTools::LowerCase(this->Name)
|
||||
<< "-config.cmake). "
|
||||
"Otherwise make Find"
|
||||
<< this->Name
|
||||
<< ".cmake available in "
|
||||
"CMAKE_MODULE_PATH.";
|
||||
}
|
||||
aw << "\n"
|
||||
"(Variable CMAKE_FIND_PACKAGE_WARN_NO_MODULE enabled this "
|
||||
"warning.)";
|
||||
this->Makefile->IssueMessage(MessageType::AUTHOR_WARNING, aw.str());
|
||||
}
|
||||
if (this->FindPackageUsingConfigMode()) {
|
||||
if (this->Makefile->IsOn("CMAKE_FIND_PACKAGE_PREFER_CONFIG")) {
|
||||
if (this->UseConfigFiles && this->FindPackageUsingConfigMode()) {
|
||||
loadedPackage = true;
|
||||
} else if (this->FindPackageUsingModuleMode()) {
|
||||
loadedPackage = true;
|
||||
}
|
||||
} else {
|
||||
if (this->UseFindModules && this->FindPackageUsingModuleMode()) {
|
||||
loadedPackage = true;
|
||||
} else {
|
||||
// Handle CMAKE_FIND_PACKAGE_WARN_NO_MODULE (warn when CONFIG mode is
|
||||
// implicitly assumed)
|
||||
if (this->UseFindModules && this->UseConfigFiles &&
|
||||
this->Makefile->IsOn("CMAKE_FIND_PACKAGE_WARN_NO_MODULE")) {
|
||||
std::ostringstream aw;
|
||||
if (this->RequiredCMakeVersion >= CMake_VERSION_ENCODE(2, 8, 8)) {
|
||||
aw << "find_package called without either MODULE or CONFIG option "
|
||||
"and "
|
||||
"no Find"
|
||||
<< this->Name
|
||||
<< ".cmake module is in CMAKE_MODULE_PATH. "
|
||||
"Add MODULE to exclusively request Module mode and fail if "
|
||||
"Find"
|
||||
<< this->Name
|
||||
<< ".cmake is missing. "
|
||||
"Add CONFIG to exclusively request Config mode and search for "
|
||||
"a "
|
||||
"package configuration file provided by "
|
||||
<< this->Name << " (" << this->Name << "Config.cmake or "
|
||||
<< cmSystemTools::LowerCase(this->Name) << "-config.cmake). ";
|
||||
} else {
|
||||
aw << "find_package called without NO_MODULE option and no "
|
||||
"Find"
|
||||
<< this->Name
|
||||
<< ".cmake module is in CMAKE_MODULE_PATH. "
|
||||
"Add NO_MODULE to exclusively request Config mode and search "
|
||||
"for a "
|
||||
"package configuration file provided by "
|
||||
<< this->Name << " (" << this->Name << "Config.cmake or "
|
||||
<< cmSystemTools::LowerCase(this->Name)
|
||||
<< "-config.cmake). "
|
||||
"Otherwise make Find"
|
||||
<< this->Name
|
||||
<< ".cmake available in "
|
||||
"CMAKE_MODULE_PATH.";
|
||||
}
|
||||
aw << "\n"
|
||||
"(Variable CMAKE_FIND_PACKAGE_WARN_NO_MODULE enabled this "
|
||||
"warning.)";
|
||||
this->Makefile->IssueMessage(MessageType::AUTHOR_WARNING, aw.str());
|
||||
}
|
||||
|
||||
if (this->FindPackageUsingConfigMode()) {
|
||||
loadedPackage = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -541,7 +541,41 @@ endif()
|
||||
set(SortLib_DIR "" CACHE FILEPATH "Wipe out find results for testing." FORCE)
|
||||
unset(SortLib_VERSION)
|
||||
|
||||
|
||||
unset(CMAKE_FIND_PACKAGE_SORT_ORDER)
|
||||
unset(CMAKE_FIND_PACKAGE_SORT_DIRECTION)
|
||||
set(CMAKE_PREFIX_PATH )
|
||||
|
||||
############################################################################
|
||||
##Test FIND_PACKAGE CMAKE_FIND_PACKAGE_PREFER_CONFIG
|
||||
|
||||
set(CMAKE_PREFIX_PATH ${CMAKE_CURRENT_SOURCE_DIR}/PreferConfig)
|
||||
set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/PreferConfig)
|
||||
|
||||
# prefer module mode
|
||||
set(CMAKE_FIND_PACKAGE_PREFER_CONFIG OFF)
|
||||
unset(ABC_FOUND)
|
||||
unset(ABC_CONFIG)
|
||||
|
||||
find_package(ABC)
|
||||
if(NOT ABC_FOUND)
|
||||
message(SEND_ERROR "Did not find ABC package")
|
||||
endif()
|
||||
if(ABC_CONFIG)
|
||||
message(SEND_ERROR "Incorrectly found ABC in CONFIG mode, expected to find it with MODULE mode")
|
||||
endif()
|
||||
|
||||
# Now prefer config mode
|
||||
set(CMAKE_FIND_PACKAGE_PREFER_CONFIG ON)
|
||||
unset(ABC_FOUND)
|
||||
unset(ABC_CONFIG)
|
||||
|
||||
find_package(ABC)
|
||||
if(NOT ABC_FOUND)
|
||||
message(SEND_ERROR "Did not find ABC package")
|
||||
endif()
|
||||
if(NOT ABC_CONFIG)
|
||||
message(SEND_ERROR "Incorrectly found ABC in MODULE mode, expected to find it with CONFIG mode")
|
||||
endif()
|
||||
|
||||
set(CMAKE_FIND_PACKAGE_PREFER_CONFIG OFF)
|
||||
set(CMAKE_PREFIX_PATH)
|
||||
|
1
Tests/FindPackageTest/PreferConfig/ABCConfig.cmake
Normal file
1
Tests/FindPackageTest/PreferConfig/ABCConfig.cmake
Normal file
@ -0,0 +1 @@
|
||||
set(ABC_FOUND TRUE)
|
1
Tests/FindPackageTest/PreferConfig/FindABC.cmake
Normal file
1
Tests/FindPackageTest/PreferConfig/FindABC.cmake
Normal file
@ -0,0 +1 @@
|
||||
set(ABC_FOUND TRUE)
|
Loading…
Reference in New Issue
Block a user