源码视角看CMake在Config模式下目录搜寻规则

先看看官方的解释:
https://cmake.org/cmake/help/v3.29/command/find_package.html

Config模式下搜索路径规则如下表:
在这里插入图片描述

其中前缀部分主要涉及的变量是:

  • <PackageName>_DIR
  • CMAKE_PREFIX_PATH
  • CMAKE_FRAMEWORK_PATH
  • CMAKE_APPBUNDLE_PATH
  • PATH(以/bin或/sbin结尾的路径条目会自动转换为它们的父目录)

W/U原文说明如下:

This set of directories is intended to work in cooperation with projects that provide configuration files in their installation trees. Directories above marked with (W) are intended for installations on Windows where the prefix may point at the top of an application’s installation directory. Those marked with (U) are intended for installations on UNIX platforms where the prefix is shared by multiple packages. This is merely a convention, so all (W) and (U) directories are still searched on all platforms. Directories marked with (A) are intended for installations on Apple platforms.

怎么理解这里的 W/U的区别呢, 下面结合源码看看,
请看源码
https://github.com/Kitware/CMake/blob/228fd59897dd2f58ecfd83e3d98348339b38b52c/Source/cmFindPackageCommand.cxx#L2636片段

// cmFindPackageCommand::SearchPrefix
bool cmFindPackageCommand::SearchPrefix(std::string const& prefix_in)
{
  assert(!prefix_in.empty() && prefix_in.back() == '/');

  // Skip this if the prefix does not exist.
  if (!cmSystemTools::FileIsDirectory(prefix_in)) {
    return false;
  }

  // Skip this if it's in ignored paths.
  std::string prefixWithoutSlash = prefix_in;
  if (prefixWithoutSlash != "/" && prefixWithoutSlash.back() == '/') {
    prefixWithoutSlash.erase(prefixWithoutSlash.length() - 1);
  }
  if (this->IgnoredPaths.count(prefixWithoutSlash) ||
      this->IgnoredPrefixPaths.count(prefixWithoutSlash)) {
    return false;
  }

  // PREFIX/ (useful on windows or in build trees)
  if (this->SearchDirectory(prefix_in)) {
    return true;
  }

  // Strip the trailing slash because the path generator is about to
  // add one.
  std::string const prefix = prefix_in.substr(0, prefix_in.size() - 1);

  auto searchFn = [this](const std::string& fullPath) -> bool {
    return this->SearchDirectory(fullPath);
  };

  auto iCMakeGen = cmCaseInsensitiveDirectoryListGenerator{ "cmake"_s };
  auto firstPkgDirGen =
    cmProjectDirectoryListGenerator{ this->Names, this->SortOrder,
                                     this->SortDirection };

  // PREFIX/(cmake|CMake)/ (useful on windows or in build trees)
  if (TryGeneratedPaths(searchFn, prefix, iCMakeGen)) {
    return true;
  }

  // PREFIX/(Foo|foo|FOO).*/
  if (TryGeneratedPaths(searchFn, prefix, firstPkgDirGen)) {
    return true;
  }

  // PREFIX/(Foo|foo|FOO).*/(cmake|CMake)/
  if (TryGeneratedPaths(searchFn, prefix, firstPkgDirGen, iCMakeGen)) {
    return true;
  }

  auto secondPkgDirGen =
    cmProjectDirectoryListGenerator{ this->Names, this->SortOrder,
                                     this->SortDirection };

  // PREFIX/(Foo|foo|FOO).*/(cmake|CMake)/(Foo|foo|FOO).*/
  if (TryGeneratedPaths(searchFn, prefix, firstPkgDirGen, iCMakeGen,
                        secondPkgDirGen)) {
    return true;
  }

  // Construct list of common install locations (lib and share).
  std::vector<cm::string_view> common;
  std::string libArch;
  if (!this->LibraryArchitecture.empty()) {
    libArch = "lib/" + this->LibraryArchitecture;
    common.emplace_back(libArch);
  }
  if (this->UseLib32Paths) {
    common.emplace_back("lib32"_s);
  }
  if (this->UseLib64Paths) {
    common.emplace_back("lib64"_s);
  }
  if (this->UseLibx32Paths) {
    common.emplace_back("libx32"_s);
  }
  common.emplace_back("lib"_s);
  common.emplace_back("share"_s);

  auto cmnGen = cmEnumPathSegmentsGenerator{ common };
  auto cmakeGen = cmAppendPathSegmentGenerator{ "cmake"_s };

  // PREFIX/(lib/ARCH|lib*|share)/cmake/(Foo|foo|FOO).*/
  if (TryGeneratedPaths(searchFn, prefix, cmnGen, cmakeGen, firstPkgDirGen)) {
    return true;
  }

  // PREFIX/(lib/ARCH|lib*|share)/(Foo|foo|FOO).*/
  if (TryGeneratedPaths(searchFn, prefix, cmnGen, firstPkgDirGen)) {
    return true;
  }

  // PREFIX/(lib/ARCH|lib*|share)/(Foo|foo|FOO).*/(cmake|CMake)/
  if (TryGeneratedPaths(searchFn, prefix, cmnGen, firstPkgDirGen, iCMakeGen)) {
    return true;
  }

  // PREFIX/(Foo|foo|FOO).*/(lib/ARCH|lib*|share)/cmake/(Foo|foo|FOO).*/
  if (TryGeneratedPaths(searchFn, prefix, firstPkgDirGen, cmnGen, cmakeGen,
                        secondPkgDirGen)) {
    return true;
  }

  // PREFIX/(Foo|foo|FOO).*/(lib/ARCH|lib*|share)/(Foo|foo|FOO).*/
  if (TryGeneratedPaths(searchFn, prefix, firstPkgDirGen, cmnGen,
                        secondPkgDirGen)) {
    return true;
  }

  // PREFIX/(Foo|foo|FOO).*/(lib/ARCH|lib*|share)/(Foo|foo|FOO).*/(cmake|CMake)/
  return TryGeneratedPaths(searchFn, prefix, firstPkgDirGen, cmnGen,
                           secondPkgDirGen, iCMakeGen);
}

读完源码, 可以看出, 所有平台上,W,U,W/U路径都会搜寻.

  • 6
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值