find_*: Avoid searching prefix derived from CMake's own source tree

When `cmake` is running from its own build tree, `CMAKE_ROOT` is in
the source tree and should not be used to derive a search prefix.

Fixes: #27853
This commit is contained in:
Daksh Mamodiya
2026-06-03 10:11:21 -04:00
committed by Brad King
parent 43b1af11a1
commit fd660330e0
8 changed files with 91 additions and 10 deletions
+14 -4
View File
@@ -40,9 +40,16 @@ endif()
# The rest of this file is based on UnixPaths.cmake, adjusted for Cray
# add the install directory of the running cmake to the search directories
# CMAKE_ROOT is CMAKE_INSTALL_PREFIX/share/cmake, so we need to go two levels up
# CMAKE_ROOT is CMAKE_INSTALL_PREFIX/share/cmake, so we need to go two levels up.
# When CMake runs from its build tree, CMAKE_ROOT is the source tree instead.
get_filename_component(__cmake_install_dir "${CMAKE_ROOT}" PATH)
get_filename_component(__cmake_install_dir "${__cmake_install_dir}" PATH)
get_property(__cmake_running_in_build_tree GLOBAL PROPERTY
_CMAKE_RUNNING_IN_BUILD_TREE)
if(__cmake_running_in_build_tree)
set(__cmake_install_dir "")
endif()
unset(__cmake_running_in_build_tree)
# Note: Some Cray's have the SYSROOT_DIR variable defined, pointing to a copy
# of the NIDs userland. If so, then we'll use it. Otherwise, just assume
@@ -53,10 +60,13 @@ get_filename_component(__cmake_install_dir "${__cmake_install_dir}" PATH)
list(APPEND CMAKE_SYSTEM_PREFIX_PATH
# Standard
$ENV{SYSROOT_DIR}/usr/local $ENV{SYSROOT_DIR}/usr $ENV{SYSROOT_DIR}/
# CMake install location
"${__cmake_install_dir}"
)
if(__cmake_install_dir)
list(APPEND CMAKE_SYSTEM_PREFIX_PATH
# CMake install location
"${__cmake_install_dir}"
)
endif()
if (NOT CMAKE_FIND_NO_INSTALL_PREFIX)
list(APPEND CMAKE_SYSTEM_PREFIX_PATH
# Project install destination.
+14 -4
View File
@@ -18,9 +18,16 @@ set(__UNIX_PATHS_INCLUDED 1)
set(UNIX 1)
# also add the install directory of the running cmake to the search directories
# CMAKE_ROOT is CMAKE_INSTALL_PREFIX/share/cmake, so we need to go two levels up
# CMAKE_ROOT is CMAKE_INSTALL_PREFIX/share/cmake, so we need to go two levels up.
# When CMake runs from its build tree, CMAKE_ROOT is the source tree instead.
get_filename_component(_CMAKE_INSTALL_DIR "${CMAKE_ROOT}" PATH)
get_filename_component(_CMAKE_INSTALL_DIR "${_CMAKE_INSTALL_DIR}" PATH)
get_property(_cmake_running_in_build_tree GLOBAL PROPERTY
_CMAKE_RUNNING_IN_BUILD_TREE)
if(_cmake_running_in_build_tree)
set(_CMAKE_INSTALL_DIR "")
endif()
unset(_cmake_running_in_build_tree)
# List common installation prefixes. These will be used for all
# search types.
@@ -31,10 +38,13 @@ get_filename_component(_CMAKE_INSTALL_DIR "${_CMAKE_INSTALL_DIR}" PATH)
list(APPEND CMAKE_SYSTEM_PREFIX_PATH
# Standard
/usr/local /usr /
# CMake install location
"${_CMAKE_INSTALL_DIR}"
)
if(_CMAKE_INSTALL_DIR)
list(APPEND CMAKE_SYSTEM_PREFIX_PATH
# CMake install location
"${_CMAKE_INSTALL_DIR}"
)
endif()
if (NOT CMAKE_FIND_NO_INSTALL_PREFIX)
list(APPEND CMAKE_SYSTEM_PREFIX_PATH
# Project install destination.
+16 -2
View File
@@ -50,9 +50,19 @@ endif()
unset(_programfiles)
# Add the CMake install location.
# CMAKE_ROOT is CMAKE_INSTALL_PREFIX/share/cmake, so we need to go two levels up.
# When CMake runs from its build tree, CMAKE_ROOT is the source tree instead.
get_filename_component(_CMAKE_INSTALL_DIR "${CMAKE_ROOT}" PATH)
get_filename_component(_CMAKE_INSTALL_DIR "${_CMAKE_INSTALL_DIR}" PATH)
list(APPEND CMAKE_SYSTEM_PREFIX_PATH "${_CMAKE_INSTALL_DIR}")
get_property(_cmake_running_in_build_tree GLOBAL PROPERTY
_CMAKE_RUNNING_IN_BUILD_TREE)
if(_cmake_running_in_build_tree)
set(_CMAKE_INSTALL_DIR "")
endif()
unset(_cmake_running_in_build_tree)
if(_CMAKE_INSTALL_DIR)
list(APPEND CMAKE_SYSTEM_PREFIX_PATH "${_CMAKE_INSTALL_DIR}")
endif()
if (NOT CMAKE_FIND_NO_INSTALL_PREFIX)
# Add other locations.
@@ -88,8 +98,12 @@ if (NOT CMAKE_FIND_NO_INSTALL_PREFIX)
)
endif()
endif()
if(_CMAKE_INSTALL_DIR)
list(APPEND CMAKE_SYSTEM_LIBRARY_PATH
"${_CMAKE_INSTALL_DIR}/bin"
)
endif()
list(APPEND CMAKE_SYSTEM_LIBRARY_PATH
"${_CMAKE_INSTALL_DIR}/bin"
/bin
)
+3
View File
@@ -673,6 +673,9 @@ cmValue cmState::GetGlobalProperty(std::string const& prop)
this->SetGlobalProperty("ENABLED_LANGUAGES", langs);
} else if (prop == "CMAKE_ROLE") {
this->SetGlobalProperty("CMAKE_ROLE", this->GetRoleString());
} else if (prop == "_CMAKE_RUNNING_IN_BUILD_TREE") {
this->SetGlobalProperty("_CMAKE_RUNNING_IN_BUILD_TREE",
cmSystemTools::GetCMakeInBuildTree() ? "1" : "0");
}
#define STRING_LIST_ELEMENT(F) ";" #F
if (prop == "CMAKE_C_KNOWN_FEATURES") {
+10
View File
@@ -2889,6 +2889,8 @@ std::string InitLogicalWorkingDirectory()
return cwd;
}
bool cmSystemToolsCMakeInBuildTree = false;
std::string cmSystemToolsLogicalWorkingDirectory =
InitLogicalWorkingDirectory();
@@ -3013,6 +3015,7 @@ void FindCMakeResourcesInBuildTree(std::string const& exe_dir)
if (fin && cmSystemTools::GetLineFromStream(fin, src_dir) &&
cmSystemTools::FileIsDirectory(src_dir)) {
cmSystemToolsCMakeRoot = src_dir;
cmSystemToolsCMakeInBuildTree = true;
} else {
dir = cmSystemTools::GetFilenamePath(dir);
src_dir_txt = cmStrCat(dir, "/CMakeFiles/CMakeSourceDir.txt");
@@ -3020,6 +3023,7 @@ void FindCMakeResourcesInBuildTree(std::string const& exe_dir)
if (fin2 && cmSystemTools::GetLineFromStream(fin2, src_dir) &&
cmSystemTools::FileIsDirectory(src_dir)) {
cmSystemToolsCMakeRoot = src_dir;
cmSystemToolsCMakeInBuildTree = true;
}
}
if (!cmSystemToolsCMakeRoot.empty() && cmSystemToolsHTMLDoc.empty() &&
@@ -3037,6 +3041,7 @@ void cmSystemTools::FindCMakeResources(char const* argv0)
#ifdef CMAKE_BOOTSTRAP
// The bootstrap cmake knows its resource locations.
cmSystemToolsCMakeRoot = CMAKE_BOOTSTRAP_SOURCE_DIR;
cmSystemToolsCMakeInBuildTree = true;
cmSystemToolsCMakeCommand = exe;
// The bootstrap cmake does not provide the other tools,
// so use the directory where they are about to be built.
@@ -3120,6 +3125,11 @@ std::string const& cmSystemTools::GetCMakeRoot()
return cmSystemToolsCMakeRoot;
}
bool cmSystemTools::GetCMakeInBuildTree()
{
return cmSystemToolsCMakeInBuildTree;
}
std::string const& cmSystemTools::GetHTMLDoc()
{
return cmSystemToolsHTMLDoc;
+1
View File
@@ -560,6 +560,7 @@ public:
static std::string const& GetCMakeCursesCommand();
static std::string const& GetCMClDepsCommand();
static std::string const& GetCMakeRoot();
static bool GetCMakeInBuildTree();
static std::string const& GetHTMLDoc();
/** Get the CMake config directory **/
@@ -0,0 +1,32 @@
# Regression net for the build-tree prefix leak fixed in the Platform modules.
# When CMake runs from its build tree, CMAKE_ROOT is the source tree rather
# than an install-tree resource directory. In that case, the historical
# dirname(dirname(CMAKE_ROOT)) install-prefix calculation must not be added to
# CMAKE_SYSTEM_PREFIX_PATH.
get_property(_cmake_running_in_build_tree GLOBAL PROPERTY
_CMAKE_RUNNING_IN_BUILD_TREE)
if(_cmake_running_in_build_tree)
get_filename_component(_leak_root_dir "${CMAKE_ROOT}" PATH)
get_filename_component(_leak_prefix "${_leak_root_dir}" PATH)
# Empty means there is no candidate. "/" is already a standard entry, not
# evidence of this leak.
if(_leak_prefix AND
NOT _leak_prefix STREQUAL "/" AND
_leak_prefix IN_LIST CMAKE_SYSTEM_PREFIX_PATH)
# Corner case intentionally not excluded: checking the CMake *source* tree
# out into a system prefix such as /usr/src or /opt/<x> would make
# _leak_prefix a standard root and trip this assertion. Those are
# install/system trees, not dev/CI workspaces, so the corner is treated as
# an unsupported layout.
message(FATAL_ERROR
"CMAKE_SYSTEM_PREFIX_PATH leaked dirname(dirname(CMAKE_ROOT))=\"${_leak_prefix}\" "
"(CMAKE_ROOT=\"${CMAKE_ROOT}\"); the Platform/*.cmake build-tree guard regressed.")
endif()
endif()
unset(_cmake_running_in_build_tree)
unset(_leak_root_dir)
unset(_leak_prefix)
@@ -3,6 +3,7 @@ include(RunCMake)
run_cmake(ConfigureLogTransitions)
run_cmake(ConfigureLogTransitionsSuppressed)
run_cmake(Created)
run_cmake(BuildTreePrefixNoLeak)
run_cmake(FromPrefixPath)
run_cmake(FromPATHEnv)
run_cmake_with_options(IgnoreInstallPrefix "-DCMAKE_INSTALL_PREFIX=${RunCMake_BINARY_DIR}/IgnoreInstallPrefix-build/")