Selaa lähdekoodia

Teach find_* commands to ignore some paths

Add platform configuration variable CMAKE_SYSTEM_IGNORE_PATH and user
configuration variable CMAKE_IGNORE_PATH.  These specify a set of
directories that will be ignored by all the find commands.  Update
FindPackageTest so that several cases will fail without a functioning
CMAKE_IGNORE_PATH.
Todd Gamblin 15 vuotta sitten
vanhempi
sitoutus
1221581aa8

+ 33 - 1
Source/cmDocumentVariables.cxx

@@ -587,7 +587,39 @@ void cmDocumentVariables::DefineVariables(cmake* cm)
      "directories for the current system. It is NOT intended "
      "to be modified by the project, use CMAKE_PREFIX_PATH for this. See also "
      "CMAKE_SYSTEM_INCLUDE_PATH, CMAKE_SYSTEM_LIBRARY_PATH, "
-     "CMAKE_SYSTEM_PROGRAM_PATH.", false,
+     "CMAKE_SYSTEM_PROGRAM_PATH, and CMAKE_SYSTEM_IGNORE_PATH.", false,
+     "Variables That Change Behavior");
+
+  cm->DefineProperty
+    ("CMAKE_SYSTEM_IGNORE_PATH", cmProperty::VARIABLE,
+     "Path to be ignored by FIND_XXX() commands.",
+     "Specifies directories to be ignored by searches in FIND_XXX() commands "
+     "This is useful in cross-compiled environments where some system "
+     "directories contain incompatible but possibly linkable libraries. For "
+     "example, on cross-compiled cluster environments, this allows a user to "
+     "ignore directories containing libraries meant for the front-end "
+     "machine that modules like FindX11 (and others) would normally search. "
+     "By default this contains a list of directories containing incompatible "
+     "binaries for the host system. "
+     "See also CMAKE_SYSTEM_PREFIX_PATH, CMAKE_SYSTEM_LIBRARY_PATH, "
+     "CMAKE_SYSTEM_INCLUDE_PATH, and CMAKE_SYSTEM_PROGRAM_PATH.", false,
+     "Variables That Change Behavior");
+
+  cm->DefineProperty
+    ("CMAKE_IGNORE_PATH", cmProperty::VARIABLE,
+     "Path to be ignored by FIND_XXX() commands.",
+     "Specifies directories to be ignored by searches in FIND_XXX() commands "
+     "This is useful in cross-compiled environments where some system "
+     "directories contain incompatible but possibly linkable libraries. For "
+     "example, on cross-compiled cluster environments, this allows a user to "
+     "ignore directories containing libraries meant for the front-end "
+     "machine that modules like FindX11 (and others) would normally search. "
+     "By default this is empty; it is intended to be set by the project. "
+     "Note that CMAKE_IGNORE_PATH takes a list of directory names, NOT a "
+     "list of prefixes. If you want to ignore paths under prefixes (bin, "
+     "include, lib, etc.), you'll need to specify them explicitly. "
+     "See also CMAKE_PREFIX_PATH, CMAKE_LIBRARY_PATH, CMAKE_INCLUDE_PATH, "
+     "CMAKE_PROGRAM_PATH.", false,
      "Variables That Change Behavior");
 
   cm->DefineProperty

+ 5 - 0
Source/cmFindBase.cxx

@@ -269,6 +269,11 @@ bool cmFindBase::ParseArguments(std::vector<std::string> const& argsIn)
     }
   this->ExpandPaths();
 
+  // Filter out ignored paths from the prefix list
+  std::set<std::string> ignored;
+  this->GetIgnoredPaths(ignored);
+  this->FilterPaths(this->SearchPaths, ignored);
+
   // Handle search root stuff.
   this->RerootPaths(this->SearchPaths);
 

+ 57 - 0
Source/cmFindCommon.cxx

@@ -240,6 +240,63 @@ void cmFindCommon::RerootPaths(std::vector<std::string>& paths)
     }
 }
 
+//----------------------------------------------------------------------------
+void cmFindCommon::FilterPaths(std::vector<std::string>& paths,
+                               const std::set<std::string>& ignore)
+{
+  // Now filter out anything that's in the ignore set.
+  std::vector<std::string> unfiltered;
+  unfiltered.swap(paths);
+
+  for(std::vector<std::string>::iterator pi = unfiltered.begin();
+      pi != unfiltered.end(); ++pi)
+    {
+    if (ignore.count(*pi) == 0)
+      {
+      paths.push_back(*pi);
+      }
+    }
+}
+
+
+//----------------------------------------------------------------------------
+void cmFindCommon::GetIgnoredPaths(std::vector<std::string>& ignore)
+{
+  // null-terminated list of paths.
+  static const char *paths[] =
+    { "CMAKE_SYSTEM_IGNORE_PATH", "CMAKE_IGNORE_PATH", 0 };
+
+  // Construct the list of path roots with no trailing slashes.
+  for(const char **pathName = paths; *pathName; ++pathName)
+    {
+    // Get the list of paths to ignore from the variable.
+    const char* ignorePath = this->Makefile->GetDefinition(*pathName);
+    if((ignorePath == 0) || (strlen(ignorePath) == 0))
+      {
+      continue;
+      }
+
+    cmSystemTools::ExpandListArgument(ignorePath, ignore);
+    }
+
+  for(std::vector<std::string>::iterator i = ignore.begin();
+      i != ignore.end(); ++i)
+    {
+    cmSystemTools::ConvertToUnixSlashes(*i);
+    }
+}
+
+
+//----------------------------------------------------------------------------
+void cmFindCommon::GetIgnoredPaths(std::set<std::string>& ignore)
+{
+  std::vector<std::string> ignoreVec;
+  GetIgnoredPaths(ignoreVec);
+  ignore.insert(ignoreVec.begin(), ignoreVec.end());
+}
+
+
+
 //----------------------------------------------------------------------------
 bool cmFindCommon::CheckCommonArgument(std::string const& arg)
 {

+ 8 - 0
Source/cmFindCommon.h

@@ -39,6 +39,14 @@ protected:
   /** Place a set of search paths under the search roots.  */
   void RerootPaths(std::vector<std::string>& paths);
 
+  /** Get ignored paths from CMAKE_[SYSTEM_]IGNORE_path variables.  */
+  void GetIgnoredPaths(std::vector<std::string>& ignore);
+  void GetIgnoredPaths(std::set<std::string>& ignore);
+
+  /** Remove paths in the ignore set from the supplied vector.  */
+  void FilterPaths(std::vector<std::string>& paths,
+                   const std::set<std::string>& ignore);
+
   /** Add trailing slashes to all search paths.  */
   void AddTrailingSlashes(std::vector<std::string>& paths);
 

+ 14 - 0
Source/cmFindPackageCommand.cxx

@@ -596,6 +596,15 @@ bool cmFindPackageCommand
       }
     }
 
+  // get igonored paths from vars and reroot them.
+  std::vector<std::string> ignored;
+  this->GetIgnoredPaths(ignored);
+  this->RerootPaths(ignored);
+
+  // Construct a set of ignored paths
+  this->IgnoredPaths.clear();
+  this->IgnoredPaths.insert(ignored.begin(), ignored.end());
+
   // Find and load the package.
   bool result = this->HandlePackageMode();
   this->AppendSuccessInformation();
@@ -1431,6 +1440,11 @@ bool cmFindPackageCommand::CheckDirectory(std::string const& dir)
 bool cmFindPackageCommand::FindConfigFile(std::string const& dir,
                                           std::string& file)
 {
+  if (this->IgnoredPaths.count(dir))
+    {
+    return false;
+    }
+
   for(std::vector<std::string>::const_iterator ci = this->Configs.begin();
       ci != this->Configs.end(); ++ci)
     {

+ 1 - 0
Source/cmFindPackageCommand.h

@@ -136,6 +136,7 @@ private:
   bool PolicyScope;
   std::vector<std::string> Names;
   std::vector<std::string> Configs;
+  std::set<std::string> IgnoredPaths;
 };
 
 #endif

+ 4 - 0
Tests/FindPackageTest/CMakeLists.txt

@@ -54,6 +54,10 @@ SET(CMAKE_FIND_APPBUNDLE FIRST)
 # Set the wrong answer for a find to make sure it re-finds.
 set(VersionedA_DIR ${CMAKE_CURRENT_SOURCE_DIR}/lib/cmake/zot-4.0)
 
+# Test that CMAKE_IGNORE_PATH can ignore the purposely bad package
+# files in the lib/cmake/zot-3.1 directory.
+set(CMAKE_IGNORE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/lib/cmake/zot-3.1)
+
 # Look for packages with new-style signatures.
 FIND_PACKAGE(foo NO_MODULE)
 FIND_PACKAGE(Foo CONFIGS FooConfig.cmake)

+ 4 - 0
Tests/FindPackageTest/lib/cmake/zot-3.1/zot-config-version.cmake

@@ -0,0 +1,4 @@
+# Claim to be any version to test that CMAKE_IGNORE_PATH hides us.
+SET(PACKAGE_VERSION 3.1)
+SET(PACKAGE_VERSION_COMPATIBLE 1)
+SET(PACKAGE_VERSION_EXACT 1)

+ 2 - 0
Tests/FindPackageTest/lib/cmake/zot-3.1/zot-config.cmake

@@ -0,0 +1,2 @@
+# Test config file.
+message(WARNING "CMAKE_IGNORE_PATH failed to ignore this file!")