Skip to content

cmFindCommon::RerootPaths() mishandles case where CMAKE_PREFIX_PATH matches one of the roots

If an entry in CMAKE_PREFIX_PATH happens to point to the same directory as one of the entries in CMAKE_FIND_ROOT_PATH or CMAKE_STAGING_PREFIX, then cmFindCommon::RerootPaths() ends up concatenating them instead of just using the path as is (i.e. it appends the path to itself). Here is the relevant part of the code:

  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))) {
        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);
      }

      // Store the new path.
      paths.push_back(rootedDir);
    }
  }

The cmSystemTools::IsSubdirectory() calls look like they should actually be "is the same or a subdirectory".

A scenario where this can arise is where something sets CMAKE_FIND_ROOT_PATH_PACKAGE to ONLY (e.g. the NDK toolchain file does this), so anything specified by a CMAKE_PREFIX_PATH will only be used in a re-rooted form. Users may wonder why the CMAKE_PREFIX_PATH they gave was ignored, not realising that CMAKE_FIND_ROOT_PATH_PACKAGE has been set to ONLY and therefore their CMAKE_PREFIX_PATH will always be re-rooted. So they then go and set CMAKE_FIND_ROOT_PATH to the same value as CMAKE_PREFIX_PATH, hoping that will work, but it doesn't. They then set CMAKE_PREFIX_PATH to a subdirectory of CMAKE_FIND_ROOT_PATH and it does work. This is confusing for users and was actually what happened with the Qt project in the toolchain file it provides as a convenience when cross-compiling.

Edited by Craig Scott
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information