Merge topic 'find-package-prefer-config'

26a99da206 find_package: Add option to prefer Config mode
c365243a3a find_package: Factor out module and config find_package methods

Acked-by: Kitware Robot <kwrobot@kitware.com>
Acked-by: Ruslan Baratov <ruslan_baratov@yahoo.com>
Merge-request: !3339
This commit is contained in:
Brad King
2019-05-22 14:28:42 +00:00
committed by Kitware Robot
10 changed files with 154 additions and 50 deletions

View File

@@ -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
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

View File

@@ -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

View 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.

View 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.

View File

@@ -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``.

View File

@@ -498,57 +498,80 @@ bool cmFindPackageCommand::InitialPass(std::vector<std::string> const& args,
this->SetModuleVariables(components);
// See if there is a Find<PackageName>.cmake module.
if (this->UseFindModules) {
bool foundModule = false;
if (!this->FindModule(foundModule)) {
this->AppendSuccessInformation();
return false;
bool loadedPackage = false;
if (this->Makefile->IsOn("CMAKE_FIND_PACKAGE_PREFER_CONFIG")) {
if (this->UseConfigFiles && this->FindPackageUsingConfigMode()) {
loadedPackage = true;
} else if (this->FindPackageUsingModuleMode()) {
loadedPackage = true;
}
if (foundModule) {
this->AppendSuccessInformation();
return true;
}
}
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 {
if (this->UseFindModules && this->FindPackageUsingModuleMode()) {
loadedPackage = true;
} 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.";
// 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;
}
}
aw << "\n"
"(Variable CMAKE_FIND_PACKAGE_WARN_NO_MODULE enabled this warning.)";
this->Makefile->IssueMessage(MessageType::AUTHOR_WARNING, aw.str());
}
// No find module. Assume the project has a CMake config file. Use
// a <PackageName>_DIR cache variable to locate it.
this->AppendSuccessInformation();
return loadedPackage;
}
bool cmFindPackageCommand::FindPackageUsingModuleMode()
{
bool foundModule = false;
if (!this->FindModule(foundModule)) {
return false;
}
return foundModule;
}
bool cmFindPackageCommand::FindPackageUsingConfigMode()
{
this->Variable = this->Name;
this->Variable += "_DIR";
@@ -580,9 +603,7 @@ bool cmFindPackageCommand::InitialPass(std::vector<std::string> const& args,
this->IgnoredPaths.insert(ignored.begin(), ignored.end());
// Find and load the package.
bool result = this->HandlePackageMode();
this->AppendSuccessInformation();
return result;
return this->HandlePackageMode();
}
void cmFindPackageCommand::SetModuleVariables(const std::string& components)

View File

@@ -90,6 +90,9 @@ private:
static PathLabel SystemRegistry;
};
bool FindPackageUsingModuleMode();
bool FindPackageUsingConfigMode();
// Add additional search path labels and groups not present in the
// parent class
void AppendSearchPathGroups();

View File

@@ -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)

View File

@@ -0,0 +1 @@
set(ABC_FOUND TRUE)

View File

@@ -0,0 +1 @@
set(ABC_FOUND TRUE)