Browse Source

find_package: Don't reroot prefix that is equal to a root path

When both CMAKE_FIND_ROOT_PATH and CMAKE_PREFIX_PATH are set to
/opt/my_device_sysroot, cmFindCommon::RerootPaths would only look
for packages in /opt/my_device_sysroot/opt/my_device_sysroot
but would not try to look in /opt/my_device_sysroot.

Make sure to not reroot the prefix path in such a case.

Fixes: #21937
Alexandru Croitor 4 năm trước cách đây
mục cha
commit
91ec6eee58

+ 8 - 2
Source/cmFindCommon.cxx

@@ -240,14 +240,20 @@ void cmFindCommon::RerootPaths(std::vector<std::string>& paths)
   std::vector<std::string> unrootedPaths = paths;
   paths.clear();
 
+  auto isSameDirectoryOrSubDirectory = [](std::string const& l,
+                                          std::string const& r) {
+    return (cmSystemTools::GetRealPath(l) == cmSystemTools::GetRealPath(r)) ||
+      cmSystemTools::IsSubDirectory(l, r);
+  };
+
   for (std::string const& r : roots) {
     for (std::string const& up : unrootedPaths) {
       // Place the unrooted path under the current root if it is not
       // already inside.  Skip the unrooted path if it is relative to
       // a user home directory or is empty.
       std::string rootedDir;
-      if (cmSystemTools::IsSubDirectory(up, r) ||
-          (stagePrefix && cmSystemTools::IsSubDirectory(up, *stagePrefix))) {
+      if (isSameDirectoryOrSubDirectory(up, r) ||
+          (stagePrefix && isSameDirectoryOrSubDirectory(up, *stagePrefix))) {
         rootedDir = up;
       } else if (!up.empty() && up[0] != '~') {
         // Start with the new root.

+ 16 - 0
Tests/RunCMake/find_package/FindRootPathAndPrefixPathAreEqual.cmake

@@ -0,0 +1,16 @@
+set(root "${CMAKE_CURRENT_SOURCE_DIR}/FindRootPathAndPrefixPathAreEqual")
+set(CMAKE_FIND_ROOT_PATH "${root}")
+set(CMAKE_PREFIX_PATH "${root}")
+set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE "ONLY")
+
+find_package(Foo
+             REQUIRED
+             CONFIG
+             NO_CMAKE_ENVIRONMENT_PATH
+             NO_SYSTEM_ENVIRONMENT_PATH
+             # Important because CMAKE_SYSTEM_PREFIX_PATH might contain "/" as a prefix
+             # And when "/" is rerooted onto the root above, the package is found even if
+             # CMAKE_PREFIX_PATH is empty. We want to ensure that we hit
+             # the CMAKE_FIND_ROOT_PATH == CMAKE_PREFIX_PATH code path.
+             NO_CMAKE_SYSTEM_PATH
+             )

+ 0 - 0
Tests/RunCMake/find_package/FindRootPathAndPrefixPathAreEqual/lib/cmake/Foo/FooConfig.cmake


+ 1 - 0
Tests/RunCMake/find_package/RunCMakeTest.cmake

@@ -25,6 +25,7 @@ run_cmake(PackageRootNestedModule)
 run_cmake(PolicyPush)
 run_cmake(PolicyPop)
 run_cmake(RequiredOptionValuesClash)
+run_cmake(FindRootPathAndPrefixPathAreEqual)
 run_cmake(SetFoundFALSE)
 run_cmake(WrongVersion)
 run_cmake(WrongVersionConfig)