Răsfoiți Sursa

Order SYSTEM include directories after non-system directories

An effect of the `-isystem` flag is to search the directory after those
specified via `-I` flags.  Make behavior more consistent on compilers
that do not have any `-isystem` flag by explicitly moving system include
directories to the end.
Ephi Sinowitz 7 ani în urmă
părinte
comite
76ad2ecb50

+ 7 - 0
Help/release/dev/reorder-sys-includes.rst

@@ -0,0 +1,7 @@
+reorder-sys-includes
+--------------------
+
+* Include directories marked as ``SYSTEM`` are now moved after non-system
+  directories.  The ``-isystem`` flag does this automatically, so moving
+  them explicitly to the end makes the behavior consistent on compilers
+  that do not have any ``-isystem`` flag.

+ 22 - 1
Source/cmLocalGenerator.cxx

@@ -202,6 +202,22 @@ void cmLocalGenerator::ComputeObjectMaxPath()
   this->ObjectMaxPathViolations.clear();
 }
 
+void cmLocalGenerator::MoveSystemIncludesToEnd(
+  std::vector<std::string>& includeDirs, const std::string& config,
+  const std::string& lang, const cmGeneratorTarget* target) const
+{
+  if (!target) {
+    return;
+  }
+
+  std::stable_sort(
+    includeDirs.begin(), includeDirs.end(),
+    [&target, &config, &lang](std::string const& a, std::string const& b) {
+      return !target->IsSystemIncludeDirectory(a, config, lang) &&
+        target->IsSystemIncludeDirectory(b, config, lang);
+    });
+}
+
 void cmLocalGenerator::TraceDependencies()
 {
   std::vector<std::string> configs;
@@ -651,7 +667,7 @@ std::string cmLocalGenerator::ConvertToIncludeReference(
 }
 
 std::string cmLocalGenerator::GetIncludeFlags(
-  const std::vector<std::string>& includes, cmGeneratorTarget* target,
+  const std::vector<std::string>& includeDirs, cmGeneratorTarget* target,
   const std::string& lang, bool forceFullPaths, bool forResponseFile,
   const std::string& config)
 {
@@ -659,6 +675,9 @@ std::string cmLocalGenerator::GetIncludeFlags(
     return "";
   }
 
+  std::vector<std::string> includes = includeDirs;
+  this->MoveSystemIncludesToEnd(includes, config, lang, target);
+
   OutputFormat shellFormat = forResponseFile ? RESPONSE : SHELL;
   std::ostringstream includeFlags;
 
@@ -924,6 +943,8 @@ void cmLocalGenerator::GetIncludeDirectories(std::vector<std::string>& dirs,
     }
   }
 
+  this->MoveSystemIncludesToEnd(dirs, config, lang, target);
+
   // Add standard include directories for this language.
   // We do not filter out implicit directories here.
   std::string const standardIncludesVar =

+ 4 - 0
Source/cmLocalGenerator.h

@@ -411,6 +411,10 @@ private:
                                    int targetType);
 
   void ComputeObjectMaxPath();
+  void MoveSystemIncludesToEnd(std::vector<std::string>& includeDirs,
+                               const std::string& config,
+                               const std::string& lang,
+                               cmGeneratorTarget const* target) const;
 };
 
 #if defined(CMAKE_BUILD_WITH_CMAKE)

+ 4 - 0
Tests/IncludeDirectories/CMakeLists.txt

@@ -65,6 +65,10 @@ else()
     PROPERTIES COMPILE_FLAGS "-ITarProp")
 endif()
 
+add_library(ordertest ordertest.cpp)
+target_include_directories(ordertest SYSTEM PUBLIC SystemIncludeDirectories/systemlib)
+target_include_directories(ordertest PUBLIC SystemIncludeDirectories/userlib)
+
 add_subdirectory(StandardIncludeDirectories)
 add_subdirectory(TargetIncludeDirectories)
 

+ 1 - 0
Tests/IncludeDirectories/SystemIncludeDirectories/systemlib/ordertest.h

@@ -0,0 +1 @@
+#error ordertest.h includes from systemlib

+ 1 - 0
Tests/IncludeDirectories/SystemIncludeDirectories/userlib/ordertest.h

@@ -0,0 +1 @@
+/* empty file */

+ 1 - 0
Tests/IncludeDirectories/ordertest.cpp

@@ -0,0 +1 @@
+#include "ordertest.h"