find_*(): Add CMAKE_IGNORE_PREFIX_PATH variable

Fixes: #20878
This commit is contained in:
Kyle Edwards
2022-02-02 11:09:00 -05:00
parent bd805a51ae
commit 201d8c4298
16 changed files with 165 additions and 12 deletions
+2
View File
@@ -212,6 +212,7 @@ Variables that Change Behavior
/variable/CMAKE_FIND_USE_SYSTEM_PACKAGE_REGISTRY
/variable/CMAKE_FRAMEWORK_PATH
/variable/CMAKE_IGNORE_PATH
/variable/CMAKE_IGNORE_PREFIX_PATH
/variable/CMAKE_INCLUDE_DIRECTORIES_BEFORE
/variable/CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE
/variable/CMAKE_INCLUDE_PATH
@@ -250,6 +251,7 @@ Variables that Change Behavior
/variable/CMAKE_SYSTEM_APPBUNDLE_PATH
/variable/CMAKE_SYSTEM_FRAMEWORK_PATH
/variable/CMAKE_SYSTEM_IGNORE_PATH
/variable/CMAKE_SYSTEM_IGNORE_PREFIX_PATH
/variable/CMAKE_SYSTEM_INCLUDE_PATH
/variable/CMAKE_SYSTEM_LIBRARY_PATH
/variable/CMAKE_SYSTEM_PREFIX_PATH
@@ -0,0 +1,7 @@
cmake-ignore-prefix-path
------------------------
* :command:`find_package`, :command:`find_program`, :command:`find_library`,
:command:`find_path`, and :command:`find_file` now recognize the
:variable:`CMAKE_IGNORE_PREFIX_PATH` and
:variable:`CMAKE_SYSTEM_IGNORE_PREFIX_PATH` variables.
@@ -0,0 +1,17 @@
CMAKE_IGNORE_PREFIX_PATH
------------------------
:ref:`Semicolon-separated list <CMake Language Lists>` of prefix to be *ignored* by
the :command:`find_program`, :command:`find_library`, :command:`find_file`,
:command:`find_path`, and :command:`find_package` commands. This is useful in cross-compiling
environments where some system directories contain incompatible but
possibly linkable libraries. For example, on cross-compiled cluster
environments, this allows a user to ignore directories containing
libraries meant for the front-end machine.
By default this is empty; it is intended to be set by the project.
Note that ``CMAKE_IGNORE_PREFIX_PATH`` takes a list of prefixes, *not*
a list of directory names.
See also the :variable:`CMAKE_PREFIX_PATH`, :variable:`CMAKE_LIBRARY_PATH`,
:variable:`CMAKE_INCLUDE_PATH`, and :variable:`CMAKE_PROGRAM_PATH` variables.
@@ -0,0 +1,18 @@
CMAKE_SYSTEM_IGNORE_PREFIX_PATH
-------------------------------
:ref:`Semicolon-separated list <CMake Language Lists>` of prefixes to be *ignored* by
the :command:`find_program`, :command:`find_library`, :command:`find_file`,
:command:`find_path`, and :command:`find_package` commands. This is useful in cross-compiling
environments where some system directories contain incompatible but
possibly linkable libraries. For example, on cross-compiled cluster
environments, this allows a user to ignore directories containing
libraries meant for the front-end machine.
By default this contains a list of directories containing incompatible
binaries for the host system. See the :variable:`CMAKE_IGNORE_PREFIX_PATH` variable
that is intended to be set by the project.
See also the :variable:`CMAKE_SYSTEM_PREFIX_PATH`,
:variable:`CMAKE_SYSTEM_LIBRARY_PATH`, :variable:`CMAKE_SYSTEM_INCLUDE_PATH`,
and :variable:`CMAKE_SYSTEM_PROGRAM_PATH` variables.
+38 -8
View File
@@ -262,11 +262,13 @@ void cmFindCommon::RerootPaths(std::vector<std::string>& paths)
(stagePrefix && isSameDirectoryOrSubDirectory(up, *stagePrefix))) {
rootedDir = up;
} else if (!up.empty() && up[0] != '~') {
// Start with the new root.
rootedDir = cmStrCat(r, '/');
// Append the original path with its old root removed.
rootedDir += cmSystemTools::SplitPathRootComponent(up);
auto const* split = cmSystemTools::SplitPathRootComponent(up);
if (split && *split) {
// Start with the new root.
rootedDir = cmStrCat(r, '/', split);
} else {
rootedDir = r;
}
}
// Store the new path.
@@ -306,6 +308,31 @@ void cmFindCommon::GetIgnoredPaths(std::set<std::string>& ignore)
ignore.insert(ignoreVec.begin(), ignoreVec.end());
}
void cmFindCommon::GetIgnoredPrefixPaths(std::vector<std::string>& ignore)
{
static constexpr const char* paths[] = {
"CMAKE_SYSTEM_IGNORE_PREFIX_PATH",
"CMAKE_IGNORE_PREFIX_PATH",
};
// Construct the list of path roots with no trailing slashes.
for (const char* pathName : paths) {
// Get the list of paths to ignore from the variable.
this->Makefile->GetDefExpandList(pathName, ignore);
}
for (std::string& i : ignore) {
cmSystemTools::ConvertToUnixSlashes(i);
}
}
void cmFindCommon::GetIgnoredPrefixPaths(std::set<std::string>& ignore)
{
std::vector<std::string> ignoreVec;
this->GetIgnoredPrefixPaths(ignoreVec);
ignore.insert(ignoreVec.begin(), ignoreVec.end());
}
bool cmFindCommon::CheckCommonArgument(std::string const& arg)
{
if (arg == "NO_DEFAULT_PATH") {
@@ -369,16 +396,19 @@ static void AddTrailingSlash(std::string& s)
void cmFindCommon::ComputeFinalPaths(IgnorePaths ignorePaths)
{
// Filter out ignored paths from the prefix list
std::set<std::string> ignored;
std::set<std::string> ignoredPaths;
std::set<std::string> ignoredPrefixes;
if (ignorePaths == IgnorePaths::Yes) {
this->GetIgnoredPaths(ignored);
this->GetIgnoredPaths(ignoredPaths);
this->GetIgnoredPrefixPaths(ignoredPrefixes);
}
// Combine the separate path types, filtering out ignores
this->SearchPaths.clear();
std::vector<PathLabel>& allLabels = this->PathGroupLabelMap[PathGroup::All];
for (PathLabel const& l : allLabels) {
this->LabeledPaths[l].ExtractWithout(ignored, this->SearchPaths);
this->LabeledPaths[l].ExtractWithout(ignoredPaths, ignoredPrefixes,
this->SearchPaths);
}
// Expand list of paths inside all search roots.
+4
View File
@@ -86,6 +86,10 @@ protected:
void GetIgnoredPaths(std::vector<std::string>& ignore);
void GetIgnoredPaths(std::set<std::string>& ignore);
/** Get ignored paths from CMAKE_[SYSTEM_]IGNORE_PREFIX_PATH variables. */
void GetIgnoredPrefixPaths(std::vector<std::string>& ignore);
void GetIgnoredPrefixPaths(std::set<std::string>& ignore);
/** Compute final search path list (reroot + trailing slash). */
enum class IgnorePaths
{
+12 -1
View File
@@ -665,6 +665,16 @@ bool cmFindPackageCommand::FindPackageUsingConfigMode()
this->IgnoredPaths.clear();
this->IgnoredPaths.insert(ignored.begin(), ignored.end());
// get igonored prefix paths from vars and reroot them.
std::vector<std::string> ignoredPrefixes;
this->GetIgnoredPrefixPaths(ignoredPrefixes);
this->RerootPaths(ignoredPrefixes);
// Construct a set of ignored prefix paths
this->IgnoredPrefixPaths.clear();
this->IgnoredPrefixPaths.insert(ignoredPrefixes.begin(),
ignoredPrefixes.end());
// Find and load the package.
return this->HandlePackageMode(HandlePackageModeType::Config);
}
@@ -2291,7 +2301,8 @@ bool cmFindPackageCommand::SearchPrefix(std::string const& prefix_in)
if (prefixWithoutSlash != "/" && prefixWithoutSlash.back() == '/') {
prefixWithoutSlash.erase(prefixWithoutSlash.length() - 1);
}
if (this->IgnoredPaths.count(prefixWithoutSlash)) {
if (this->IgnoredPaths.count(prefixWithoutSlash) ||
this->IgnoredPrefixPaths.count(prefixWithoutSlash)) {
return false;
}
+1
View File
@@ -205,6 +205,7 @@ private:
std::vector<std::string> Names;
std::vector<std::string> Configs;
std::set<std::string> IgnoredPaths;
std::set<std::string> IgnoredPrefixPaths;
std::string DebugBuffer;
/*! the selected sortOrder (None by default)*/
+4 -2
View File
@@ -19,7 +19,8 @@ cmSearchPath::cmSearchPath(cmFindCommon* findCmd)
cmSearchPath::~cmSearchPath() = default;
void cmSearchPath::ExtractWithout(const std::set<std::string>& ignore,
void cmSearchPath::ExtractWithout(const std::set<std::string>& ignorePaths,
const std::set<std::string>& ignorePrefixes,
std::vector<std::string>& outPaths,
bool clear) const
{
@@ -27,7 +28,8 @@ void cmSearchPath::ExtractWithout(const std::set<std::string>& ignore,
outPaths.clear();
}
for (auto const& path : this->Paths) {
if (ignore.count(path.Path) == 0) {
if (ignorePaths.count(path.Path) == 0 &&
ignorePrefixes.count(path.Prefix) == 0) {
outPaths.push_back(path.Path);
}
}
+2 -1
View File
@@ -43,7 +43,8 @@ public:
const std::vector<PathWithPrefix>& GetPaths() const { return this->Paths; }
std::size_t size() const { return this->Paths.size(); }
void ExtractWithout(const std::set<std::string>& ignore,
void ExtractWithout(const std::set<std::string>& ignorePaths,
const std::set<std::string>& ignorePrefixes,
std::vector<std::string>& outPaths,
bool clear = false) const;
@@ -0,0 +1,26 @@
set(CMAKE_PREFIX_PATH
${CMAKE_SOURCE_DIR}/PackageRoot/foo/cmake_root
${CMAKE_SOURCE_DIR}/PackageRoot/foo/env_root
)
set(CMAKE_IGNORE_PREFIX_PATH
${CMAKE_SOURCE_DIR}/PackageRoot//foo/cmake_root// # Test double slashes
)
set(CMAKE_SYSTEM_IGNORE_PREFIX_PATH
${CMAKE_SOURCE_DIR}/PackageRoot/foo/env_root
)
find_package(Bar QUIET CONFIG)
if(Bar_FOUND)
message(SEND_ERROR "Bar should not be found, was found in ${Bar_DIR}")
endif()
set(CMAKE_PREFIX_PATH)
set(CMAKE_FIND_ROOT_PATH
${CMAKE_SOURCE_DIR}/PackageRoot/foo/cmake_root
${CMAKE_SOURCE_DIR}/PackageRoot/foo/env_root
)
set(CMAKE_IGNORE_PREFIX_PATH /)
set(CMAKE_SYSTEM_IGNORE_PREFIX_PATH)
find_package(Bar2 NAMES Bar QUIET CONFIG)
if(Bar2_FOUND)
message(SEND_ERROR "Bar2 should not be found, was found in ${Bar2_DIR}")
endif()
@@ -45,6 +45,7 @@ run_cmake(VersionRangeConfig02)
run_cmake(VersionRangeConfigStd)
run_cmake(VersionRangeConfigStd2)
run_cmake(IgnorePath)
run_cmake(IgnorePrefixPath)
if(UNIX
AND NOT MSYS # FIXME: This works on CYGWIN but not on MSYS
)
@@ -0,0 +1,30 @@
function(assert_eq var value)
if(NOT "${${var}}" STREQUAL "${value}")
message(SEND_ERROR "Expected value of ${var}:\n ${value}\nActual value:\n ${${var}}")
endif()
endfunction()
set(CMAKE_FIND_USE_SYSTEM_ENVIRONMENT_PATH FALSE)
set(CMAKE_PREFIX_PATH ${CMAKE_SOURCE_DIR}/Prefix)
set(_old_CMAKE_SYSTEM_PREFIX_PATH ${CMAKE_SYSTEM_PREFIX_PATH})
set(CMAKE_SYSTEM_PREFIX_PATH ${CMAKE_SOURCE_DIR}/SystemPrefix)
set(prog_ROOT
${CMAKE_SOURCE_DIR}/Prefix
${CMAKE_SOURCE_DIR}/SystemPrefix
)
set(CMAKE_IGNORE_PREFIX_PATH ${CMAKE_SOURCE_DIR}/Prefix)
set(CMAKE_SYSTEM_IGNORE_PREFIX_PATH ${CMAKE_SOURCE_DIR}/SystemPrefix)
find_program(prog prog)
assert_eq(prog "prog-NOTFOUND")
set(CMAKE_PREFIX_PATH)
set(CMAKE_SYSTEM_PREFIX_PATH ${_old_CMAKE_SYSTEM_PREFIX_PATH})
set(CMAKE_IGNORE_PREFIX_PATH /)
set(CMAKE_FIND_ROOT_PATH
${CMAKE_SOURCE_DIR}/Prefix
${CMAKE_SOURCE_DIR}/SystemPrefix
)
find_program(prog2 prog)
assert_eq(prog2 "prog2-NOTFOUND")
+1
View File
@@ -0,0 +1 @@
#!/bin/sh
@@ -6,6 +6,7 @@ run_cmake(NamesPerDir)
run_cmake(RelAndAbsPath)
run_cmake(Required)
run_cmake(NO_CACHE)
run_cmake(IgnorePrefixPath)
if(CMAKE_SYSTEM_NAME MATCHES "^(Windows|CYGWIN|MSYS)$")
run_cmake(WindowsCom)
+1
View File
@@ -0,0 +1 @@
#!/bin/sh