浏览代码

find_package: Don't glob certain macOS paths

Modify cmDirectoryListGenerator to support exact matching as well as
'starts-with' matching. The latter is used to implement '<name>*' search
paths, but cmDirectoryListGenerator is also used for '<name><suffix>'
matching (via cmMacProjectDirectoryListGenerator, mainly for macOS
paths), which resulted in the latter actually matching '<name><suffix>*'
even though that is not documented and unlikely to be useful.

This also adds the ability for cmDirectoryListGenerator to match
anything (by giving an empty list of names), which isn't in use yet, but
which we will use in the future.
Matthew Woehlke 1 年之前
父节点
当前提交
e90f60f864
共有 1 个文件被更改,包括 29 次插入17 次删除
  1. 29 17
      Source/cmFindPackageCommand.cxx

+ 29 - 17
Source/cmFindPackageCommand.cxx

@@ -206,8 +206,10 @@ private:
 class cmDirectoryListGenerator
 class cmDirectoryListGenerator
 {
 {
 public:
 public:
-  cmDirectoryListGenerator(std::vector<std::string> const& names)
+  cmDirectoryListGenerator(std::vector<std::string> const& names,
+                           bool exactMatch)
     : Names{ names }
     : Names{ names }
+    , ExactMatch{ exactMatch }
     , Current{ this->Matches.cbegin() }
     , Current{ this->Matches.cbegin() }
   {
   {
   }
   }
@@ -231,20 +233,28 @@ public:
       // `isDirentryToIgnore(i)` condition to check.
       // `isDirentryToIgnore(i)` condition to check.
       for (auto i = 0ul; i < directoryLister.GetNumberOfFiles(); ++i) {
       for (auto i = 0ul; i < directoryLister.GetNumberOfFiles(); ++i) {
         const char* const fname = directoryLister.GetFile(i);
         const char* const fname = directoryLister.GetFile(i);
-        if (isDirentryToIgnore(fname)) {
+        // Skip entries to ignore or that aren't directories.
+        if (isDirentryToIgnore(fname) || !directoryLister.FileIsDirectory(i)) {
           continue;
           continue;
         }
         }
 
 
-        for (const auto& n : this->Names.get()) {
-          // NOTE Customization point for `cmMacProjectDirectoryListGenerator`
-          const auto name = this->TransformNameBeforeCmp(n);
-          // Skip entries that don't match and non-directories.
-          // ATTENTION BTW, original code also didn't check if it's a symlink
-          // to a directory!
-          const auto equal =
-            (cmsysString_strncasecmp(fname, name.c_str(), name.length()) == 0);
-          if (equal && directoryLister.FileIsDirectory(i)) {
-            this->Matches.emplace_back(fname);
+        if (!this->ExactMatch && this->Names.get().empty()) {
+          this->Matches.emplace_back(fname);
+        } else {
+          for (const auto& n : this->Names.get()) {
+            // NOTE Customization point for
+            // `cmMacProjectDirectoryListGenerator`
+            const auto name = this->TransformNameBeforeCmp(n);
+            // Skip entries that don't match.
+            const auto equal =
+              ((this->ExactMatch
+                  ? cmsysString_strcasecmp(fname, name.c_str())
+                  : cmsysString_strncasecmp(fname, name.c_str(),
+                                            name.length())) == 0);
+            if (equal) {
+              this->Matches.emplace_back(fname);
+              break;
+            }
           }
           }
         }
         }
       }
       }
@@ -273,6 +283,7 @@ protected:
   virtual std::string TransformNameBeforeCmp(std::string same) { return same; }
   virtual std::string TransformNameBeforeCmp(std::string same) { return same; }
 
 
   std::reference_wrapper<const std::vector<std::string>> Names;
   std::reference_wrapper<const std::vector<std::string>> Names;
+  bool const ExactMatch;
   std::vector<std::string> Matches;
   std::vector<std::string> Matches;
   std::vector<std::string>::const_iterator Current;
   std::vector<std::string>::const_iterator Current;
 };
 };
@@ -282,8 +293,9 @@ class cmProjectDirectoryListGenerator : public cmDirectoryListGenerator
 public:
 public:
   cmProjectDirectoryListGenerator(std::vector<std::string> const& names,
   cmProjectDirectoryListGenerator(std::vector<std::string> const& names,
                                   cmFindPackageCommand::SortOrderType so,
                                   cmFindPackageCommand::SortOrderType so,
-                                  cmFindPackageCommand::SortDirectionType sd)
-    : cmDirectoryListGenerator{ names }
+                                  cmFindPackageCommand::SortDirectionType sd,
+                                  bool exactMatch)
+    : cmDirectoryListGenerator{ names, exactMatch }
     , SortOrder{ so }
     , SortOrder{ so }
     , SortDirection{ sd }
     , SortDirection{ sd }
   {
   {
@@ -310,7 +322,7 @@ class cmMacProjectDirectoryListGenerator : public cmDirectoryListGenerator
 public:
 public:
   cmMacProjectDirectoryListGenerator(const std::vector<std::string>& names,
   cmMacProjectDirectoryListGenerator(const std::vector<std::string>& names,
                                      cm::string_view ext)
                                      cm::string_view ext)
-    : cmDirectoryListGenerator{ names }
+    : cmDirectoryListGenerator{ names, true }
     , Extension{ ext }
     , Extension{ ext }
   {
   {
   }
   }
@@ -2666,7 +2678,7 @@ bool cmFindPackageCommand::SearchPrefix(std::string const& prefix_in)
   auto iCMakeGen = cmCaseInsensitiveDirectoryListGenerator{ "cmake"_s };
   auto iCMakeGen = cmCaseInsensitiveDirectoryListGenerator{ "cmake"_s };
   auto firstPkgDirGen =
   auto firstPkgDirGen =
     cmProjectDirectoryListGenerator{ this->Names, this->SortOrder,
     cmProjectDirectoryListGenerator{ this->Names, this->SortOrder,
-                                     this->SortDirection };
+                                     this->SortDirection, false };
 
 
   // PREFIX/(cmake|CMake)/ (useful on windows or in build trees)
   // PREFIX/(cmake|CMake)/ (useful on windows or in build trees)
   if (TryGeneratedPaths(searchFn, prefix, iCMakeGen)) {
   if (TryGeneratedPaths(searchFn, prefix, iCMakeGen)) {
@@ -2685,7 +2697,7 @@ bool cmFindPackageCommand::SearchPrefix(std::string const& prefix_in)
 
 
   auto secondPkgDirGen =
   auto secondPkgDirGen =
     cmProjectDirectoryListGenerator{ this->Names, this->SortOrder,
     cmProjectDirectoryListGenerator{ this->Names, this->SortOrder,
-                                     this->SortDirection };
+                                     this->SortDirection, false };
 
 
   // PREFIX/(Foo|foo|FOO).*/(cmake|CMake)/(Foo|foo|FOO).*/
   // PREFIX/(Foo|foo|FOO).*/(cmake|CMake)/(Foo|foo|FOO).*/
   if (TryGeneratedPaths(searchFn, prefix, firstPkgDirGen, iCMakeGen,
   if (TryGeneratedPaths(searchFn, prefix, firstPkgDirGen, iCMakeGen,