From: Peter Wu Date: Thu, 19 Oct 2017 23:53:27 +0000 (+0000) Subject: Try to shorten system header paths when using -MD depfiles X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=cc28d36809ee131966e1bd25939748d9f7cc07a4;p=clang Try to shorten system header paths when using -MD depfiles 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 --- diff --git a/include/clang/Driver/Options.td b/include/clang/Driver/Options.td index 526b72f792..c87cac91bd 100644 --- a/include/clang/Driver/Options.td +++ b/include/clang/Driver/Options.td @@ -384,6 +384,11 @@ def MT : JoinedOrSeparate<["-"], "MT">, Group, Flags<[CC1Option]>, HelpText<"Specify name of main file output in depfile">; def MV : Flag<["-"], "MV">, Group, Flags<[CC1Option]>, HelpText<"Use NMake/Jom format for the depfile">; +def fno_canonical_system_headers : Flag<["-"], "fno-canonical-system-headers">, + Group, Flags<[CC1Option]>, + HelpText<"Do not shorten system header paths in depfiles">; +def fcanonical_system_headers : Flag<["-"], "fcanonical-system-headers">, + Group; def Mach : Flag<["-"], "Mach">, Group; def O0 : Flag<["-"], "O0">, Group, Flags<[CC1Option, HelpHidden]>; def O4 : Flag<["-"], "O4">, Group, Flags<[CC1Option, HelpHidden]>; diff --git a/include/clang/Frontend/DependencyOutputOptions.h b/include/clang/Frontend/DependencyOutputOptions.h index 0be36cd9aa..47016a2548 100644 --- a/include/clang/Frontend/DependencyOutputOptions.h +++ b/include/clang/Frontend/DependencyOutputOptions.h @@ -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; } }; diff --git a/lib/Driver/Job.cpp b/lib/Driver/Job.cpp index 765c05752d..241c72a2e9 100644 --- a/lib/Driver/Job.cpp +++ b/lib/Driver/Job.cpp @@ -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(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. diff --git a/lib/Driver/ToolChains/Clang.cpp b/lib/Driver/ToolChains/Clang.cpp index 12713f8be2..1304042c83 100644 --- a/lib/Driver/ToolChains/Clang.cpp +++ b/lib/Driver/ToolChains/Clang.cpp @@ -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)) || diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp index 19e26c18bf..42fd2a1331 100644 --- a/lib/Frontend/CompilerInvocation.cpp +++ b/lib/Frontend/CompilerInvocation.cpp @@ -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); diff --git a/lib/Frontend/DependencyFile.cpp b/lib/Frontend/DependencyFile.cpp index 561eb9c4a3..b6e4cfa338 100644 --- a/lib/Frontend/DependencyFile.cpp +++ b/lib/Frontend/DependencyFile.cpp @@ -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)); } diff --git a/lib/Tooling/ArgumentsAdjusters.cpp b/lib/Tooling/ArgumentsAdjusters.cpp index ac9fd3c5ca..8fcaa8afe4 100644 --- a/lib/Tooling/ArgumentsAdjusters.cpp +++ b/lib/Tooling/ArgumentsAdjusters.cpp @@ -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 index 0000000000..555b79fc13 --- /dev/null +++ b/test/Preprocessor/dependencies-realpath.c @@ -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