先看看官方的解释:
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路径都会搜寻.