]> granicus.if.org Git - clang/commitdiff
Try to shorten system header paths when using -MD depfiles
authorPeter Wu <peter@lekensteyn.nl>
Thu, 19 Oct 2017 23:53:27 +0000 (23:53 +0000)
committerPeter Wu <peter@lekensteyn.nl>
Thu, 19 Oct 2017 23:53:27 +0000 (23:53 +0000)
GCC tries to shorten system headers in depfiles using its real path
(resolving components like ".." and following symlinks). Mimic this
feature to ensure that the Ninja build tool detects the correct
dependencies when a symlink changes directory levels, see
https://github.com/ninja-build/ninja/issues/1330

An option to disable this feature is added in case "these changed header
paths may conflict with some compilation environments", see
https://gcc.gnu.org/ml/gcc-patches/2012-09/msg00287.html

Note that the original feature request for GCC
(https://gcc.gnu.org/bugzilla/show_bug.cgi?id=52974) also included paths
preprocessed output (-E) and diagnostics. That is not implemented now
since I am not sure if it breaks something else.

Differential Revision: https://reviews.llvm.org/D37954

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@316193 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Driver/Options.td
include/clang/Frontend/DependencyOutputOptions.h
lib/Driver/Job.cpp
lib/Driver/ToolChains/Clang.cpp
lib/Frontend/CompilerInvocation.cpp
lib/Frontend/DependencyFile.cpp
lib/Tooling/ArgumentsAdjusters.cpp
test/Preprocessor/dependencies-realpath.c [new file with mode: 0644]

index 526b72f792c0eb913f320f9b0f7cc47e29393f30..c87cac91bd18b0508c92628d91ac19e45a545dc3 100644 (file)
@@ -384,6 +384,11 @@ def MT : JoinedOrSeparate<["-"], "MT">, Group<M_Group>, Flags<[CC1Option]>,
     HelpText<"Specify name of main file output in depfile">;
 def MV : Flag<["-"], "MV">, Group<M_Group>, Flags<[CC1Option]>,
     HelpText<"Use NMake/Jom format for the depfile">;
+def fno_canonical_system_headers : Flag<["-"], "fno-canonical-system-headers">,
+    Group<M_Group>, Flags<[CC1Option]>,
+    HelpText<"Do not shorten system header paths in depfiles">;
+def fcanonical_system_headers : Flag<["-"], "fcanonical-system-headers">,
+    Group<M_Group>;
 def Mach : Flag<["-"], "Mach">, Group<Link_Group>;
 def O0 : Flag<["-"], "O0">, Group<O_Group>, Flags<[CC1Option, HelpHidden]>;
 def O4 : Flag<["-"], "O4">, Group<O_Group>, Flags<[CC1Option, HelpHidden]>;
index 0be36cd9aa6ea8dd491e06d990f6eaeac9890552..47016a2548c0a39bf558062701b47abf638cedbf 100644 (file)
@@ -30,6 +30,8 @@ public:
   unsigned AddMissingHeaderDeps : 1; ///< Add missing headers to dependency list
   unsigned PrintShowIncludes : 1; ///< Print cl.exe style /showIncludes info.
   unsigned IncludeModuleFiles : 1; ///< Include module file dependencies.
+  unsigned CanonicalSystemHeaders : 1; ///< Try to output a shorter path for
+                                       /// system header dependencies.
 
   /// The format for the dependency file.
   DependencyOutputFormat OutputFormat;
@@ -67,6 +69,7 @@ public:
     AddMissingHeaderDeps = 0;
     PrintShowIncludes = 0;
     IncludeModuleFiles = 0;
+    CanonicalSystemHeaders = 1;
     OutputFormat = DependencyOutputFormat::Make;
   }
 };
index 765c05752d8f3a12a9785085305bfd304ef2351f..241c72a2e941a2cc4cf85a704e52f490c3da2d72 100644 (file)
@@ -73,8 +73,8 @@ static bool skipArgs(const char *Flag, bool HaveCrashVFS, int &SkipNum,
 
   // These flags are all of the form -Flag and have no second argument.
   ShouldSkip = llvm::StringSwitch<bool>(Flag)
-    .Cases("-M", "-MM", "-MG", "-MP", "-MD", true)
-    .Case("-MMD", true)
+    .Cases("-M", "-MM", "-MG", "-MP", "-MD", "-MMD", true)
+    .Cases("-fno-canonical-system-headers", "-fcanonical-system-headers", true)
     .Default(false);
 
   // Match found.
index 12713f8be2faafec3002b3c216caad33622dd6c6..1304042c83a9c30ce626c75e946cf5fcfbe4108d 100644 (file)
@@ -964,6 +964,13 @@ void Clang::AddPreprocessingOptions(Compilation &C, const JobAction &JA,
   Args.AddLastArg(CmdArgs, options::OPT_C);
   Args.AddLastArg(CmdArgs, options::OPT_CC);
 
+  if (Arg *A = Args.getLastArg(options::OPT_fno_canonical_system_headers,
+                               options::OPT_fcanonical_system_headers)) {
+    if (A->getOption().matches(options::OPT_fno_canonical_system_headers)) {
+      CmdArgs.push_back("-fno-canonical-system-headers");
+    }
+  }
+
   // Handle dependency file generation.
   if ((A = Args.getLastArg(options::OPT_M, options::OPT_MM)) ||
       (A = Args.getLastArg(options::OPT_MD)) ||
index 19e26c18bfdf5a648872141131c229e14d17763e..42fd2a13313a7ee8bcd5e7ef332b9ace8edbd7e8 100644 (file)
@@ -1002,6 +1002,7 @@ static void ParseDependencyOutputArgs(DependencyOutputOptions &Opts,
   Opts.Targets = Args.getAllArgValues(OPT_MT);
   Opts.IncludeSystemHeaders = Args.hasArg(OPT_sys_header_deps);
   Opts.IncludeModuleFiles = Args.hasArg(OPT_module_file_deps);
+  Opts.CanonicalSystemHeaders = !Args.hasArg(OPT_fno_canonical_system_headers);
   Opts.UsePhonyTargets = Args.hasArg(OPT_MP);
   Opts.ShowHeaderIncludes = Args.hasArg(OPT_H);
   Opts.HeaderIncludeOutputFile = Args.getLastArgValue(OPT_header_include_file);
index 561eb9c4a3161c100181543636de1f3f2420fa0a..b6e4cfa33852b2b98a3c6c947e4f09780cf50a9a 100644 (file)
@@ -161,6 +161,7 @@ class DFGImpl : public PPCallbacks {
   bool AddMissingHeaderDeps;
   bool SeenMissingHeader;
   bool IncludeModuleFiles;
+  bool CanonicalSystemHeaders;
   DependencyOutputFormat OutputFormat;
 
 private:
@@ -176,6 +177,7 @@ public:
       AddMissingHeaderDeps(Opts.AddMissingHeaderDeps),
       SeenMissingHeader(false),
       IncludeModuleFiles(Opts.IncludeModuleFiles),
+      CanonicalSystemHeaders(Opts.CanonicalSystemHeaders),
       OutputFormat(Opts.OutputFormat) {
     for (const auto &ExtraDep : Opts.ExtraDeps) {
       AddFilename(ExtraDep);
@@ -288,6 +290,15 @@ void DFGImpl::FileChanged(SourceLocation Loc,
   if (!FileMatchesDepCriteria(Filename.data(), FileType))
     return;
 
+  // Try to shorten system header paths like GCC does (unless
+  // -fno-canonical-system-headers is given).
+  if (CanonicalSystemHeaders && isSystem(FileType)) {
+    StringRef RealPath = FE->tryGetRealPathName();
+    if (!RealPath.empty() && RealPath.size() < Filename.size()) {
+      Filename = RealPath;
+    }
+  }
+
   AddFilename(llvm::sys::path::remove_leading_dotslash(Filename));
 }
 
index ac9fd3c5cade4437473af581121fd9ffb230909c..8fcaa8afe4367f008f368a5d7609493da393267e 100644 (file)
@@ -58,7 +58,9 @@ ArgumentsAdjuster getClangStripDependencyFileAdjuster() {
       StringRef Arg = Args[i];
       // All dependency-file options begin with -M. These include -MM,
       // -MF, -MG, -MP, -MT, -MQ, -MD, and -MMD.
-      if (!Arg.startswith("-M"))
+      // The exception is -f[no-]canonical-system-headers.
+      if (!Arg.startswith("-M") && Arg != "-fno-canonical-system-headers" &&
+          Arg != "-fcanonical-system-headers")
         AdjustedArgs.push_back(Args[i]);
 
       if ((Arg == "-MF") || (Arg == "-MT") || (Arg == "-MQ") ||
diff --git a/test/Preprocessor/dependencies-realpath.c b/test/Preprocessor/dependencies-realpath.c
new file mode 100644 (file)
index 0000000..555b79f
--- /dev/null
@@ -0,0 +1,33 @@
+// RUN: mkdir -p %t/sub/dir
+// RUN: echo > %t/sub/empty.h
+
+// Test that system header paths are expanded
+//
+// RUN: %clang -fsyntax-only -MD -MF %t.d -MT foo %s -isystem %t/sub/dir/..
+// RUN: FileCheck -check-prefix=TEST1 %s < %t.d
+// TEST1: foo:
+// TEST1: sub{{/|\\}}empty.h
+
+// Test that system header paths are not expanded to a longer form
+//
+// RUN: cd %t && %clang -fsyntax-only -MD -MF %t.d -MT foo %s -isystem sub/dir/..
+// RUN: FileCheck -check-prefix=TEST2 %s < %t.d
+// TEST2: foo:
+// TEST2: sub/dir/..{{/|\\}}empty.h
+
+// Test that user header paths are not expanded
+//
+// RUN: %clang -fsyntax-only -MD -MF %t.d -MT foo %s -I %t/sub/dir/..
+// RUN: FileCheck -check-prefix=TEST3 %s < %t.d
+// TEST3: foo:
+// TEST3: sub/dir/..{{/|\\}}empty.h
+
+// Test that system header paths are not expanded with -fno-canonical-system-headers
+// (and also that the -fsystem-system-headers option is accepted)
+//
+// RUN: %clang -fsyntax-only -MD -MF %t.d -MT foo %s -I %t/sub/dir/.. -fcanonical-system-headers -fno-canonical-system-headers
+// RUN: FileCheck -check-prefix=TEST4 %s < %t.d
+// TEST4: foo:
+// TEST4: sub/dir/..{{/|\\}}empty.h
+
+#include <empty.h>