Skip to content
This repository was archived by the owner on Nov 1, 2021. It is now read-only.

Commit cc28d36

Browse files
committed
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 ninja-build/ninja#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
1 parent 22b25a6 commit cc28d36

File tree

8 files changed

+65
-3
lines changed

8 files changed

+65
-3
lines changed

include/clang/Driver/Options.td

+5
Original file line numberDiff line numberDiff line change
@@ -384,6 +384,11 @@ def MT : JoinedOrSeparate<["-"], "MT">, Group<M_Group>, Flags<[CC1Option]>,
384384
HelpText<"Specify name of main file output in depfile">;
385385
def MV : Flag<["-"], "MV">, Group<M_Group>, Flags<[CC1Option]>,
386386
HelpText<"Use NMake/Jom format for the depfile">;
387+
def fno_canonical_system_headers : Flag<["-"], "fno-canonical-system-headers">,
388+
Group<M_Group>, Flags<[CC1Option]>,
389+
HelpText<"Do not shorten system header paths in depfiles">;
390+
def fcanonical_system_headers : Flag<["-"], "fcanonical-system-headers">,
391+
Group<M_Group>;
387392
def Mach : Flag<["-"], "Mach">, Group<Link_Group>;
388393
def O0 : Flag<["-"], "O0">, Group<O_Group>, Flags<[CC1Option, HelpHidden]>;
389394
def O4 : Flag<["-"], "O4">, Group<O_Group>, Flags<[CC1Option, HelpHidden]>;

include/clang/Frontend/DependencyOutputOptions.h

+3
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ class DependencyOutputOptions {
3030
unsigned AddMissingHeaderDeps : 1; ///< Add missing headers to dependency list
3131
unsigned PrintShowIncludes : 1; ///< Print cl.exe style /showIncludes info.
3232
unsigned IncludeModuleFiles : 1; ///< Include module file dependencies.
33+
unsigned CanonicalSystemHeaders : 1; ///< Try to output a shorter path for
34+
/// system header dependencies.
3335

3436
/// The format for the dependency file.
3537
DependencyOutputFormat OutputFormat;
@@ -67,6 +69,7 @@ class DependencyOutputOptions {
6769
AddMissingHeaderDeps = 0;
6870
PrintShowIncludes = 0;
6971
IncludeModuleFiles = 0;
72+
CanonicalSystemHeaders = 1;
7073
OutputFormat = DependencyOutputFormat::Make;
7174
}
7275
};

lib/Driver/Job.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -73,8 +73,8 @@ static bool skipArgs(const char *Flag, bool HaveCrashVFS, int &SkipNum,
7373

7474
// These flags are all of the form -Flag and have no second argument.
7575
ShouldSkip = llvm::StringSwitch<bool>(Flag)
76-
.Cases("-M", "-MM", "-MG", "-MP", "-MD", true)
77-
.Case("-MMD", true)
76+
.Cases("-M", "-MM", "-MG", "-MP", "-MD", "-MMD", true)
77+
.Cases("-fno-canonical-system-headers", "-fcanonical-system-headers", true)
7878
.Default(false);
7979

8080
// Match found.

lib/Driver/ToolChains/Clang.cpp

+7
Original file line numberDiff line numberDiff line change
@@ -964,6 +964,13 @@ void Clang::AddPreprocessingOptions(Compilation &C, const JobAction &JA,
964964
Args.AddLastArg(CmdArgs, options::OPT_C);
965965
Args.AddLastArg(CmdArgs, options::OPT_CC);
966966

967+
if (Arg *A = Args.getLastArg(options::OPT_fno_canonical_system_headers,
968+
options::OPT_fcanonical_system_headers)) {
969+
if (A->getOption().matches(options::OPT_fno_canonical_system_headers)) {
970+
CmdArgs.push_back("-fno-canonical-system-headers");
971+
}
972+
}
973+
967974
// Handle dependency file generation.
968975
if ((A = Args.getLastArg(options::OPT_M, options::OPT_MM)) ||
969976
(A = Args.getLastArg(options::OPT_MD)) ||

lib/Frontend/CompilerInvocation.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -1002,6 +1002,7 @@ static void ParseDependencyOutputArgs(DependencyOutputOptions &Opts,
10021002
Opts.Targets = Args.getAllArgValues(OPT_MT);
10031003
Opts.IncludeSystemHeaders = Args.hasArg(OPT_sys_header_deps);
10041004
Opts.IncludeModuleFiles = Args.hasArg(OPT_module_file_deps);
1005+
Opts.CanonicalSystemHeaders = !Args.hasArg(OPT_fno_canonical_system_headers);
10051006
Opts.UsePhonyTargets = Args.hasArg(OPT_MP);
10061007
Opts.ShowHeaderIncludes = Args.hasArg(OPT_H);
10071008
Opts.HeaderIncludeOutputFile = Args.getLastArgValue(OPT_header_include_file);

lib/Frontend/DependencyFile.cpp

+11
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,7 @@ class DFGImpl : public PPCallbacks {
161161
bool AddMissingHeaderDeps;
162162
bool SeenMissingHeader;
163163
bool IncludeModuleFiles;
164+
bool CanonicalSystemHeaders;
164165
DependencyOutputFormat OutputFormat;
165166

166167
private:
@@ -176,6 +177,7 @@ class DFGImpl : public PPCallbacks {
176177
AddMissingHeaderDeps(Opts.AddMissingHeaderDeps),
177178
SeenMissingHeader(false),
178179
IncludeModuleFiles(Opts.IncludeModuleFiles),
180+
CanonicalSystemHeaders(Opts.CanonicalSystemHeaders),
179181
OutputFormat(Opts.OutputFormat) {
180182
for (const auto &ExtraDep : Opts.ExtraDeps) {
181183
AddFilename(ExtraDep);
@@ -288,6 +290,15 @@ void DFGImpl::FileChanged(SourceLocation Loc,
288290
if (!FileMatchesDepCriteria(Filename.data(), FileType))
289291
return;
290292

293+
// Try to shorten system header paths like GCC does (unless
294+
// -fno-canonical-system-headers is given).
295+
if (CanonicalSystemHeaders && isSystem(FileType)) {
296+
StringRef RealPath = FE->tryGetRealPathName();
297+
if (!RealPath.empty() && RealPath.size() < Filename.size()) {
298+
Filename = RealPath;
299+
}
300+
}
301+
291302
AddFilename(llvm::sys::path::remove_leading_dotslash(Filename));
292303
}
293304

lib/Tooling/ArgumentsAdjusters.cpp

+3-1
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,9 @@ ArgumentsAdjuster getClangStripDependencyFileAdjuster() {
5858
StringRef Arg = Args[i];
5959
// All dependency-file options begin with -M. These include -MM,
6060
// -MF, -MG, -MP, -MT, -MQ, -MD, and -MMD.
61-
if (!Arg.startswith("-M"))
61+
// The exception is -f[no-]canonical-system-headers.
62+
if (!Arg.startswith("-M") && Arg != "-fno-canonical-system-headers" &&
63+
Arg != "-fcanonical-system-headers")
6264
AdjustedArgs.push_back(Args[i]);
6365

6466
if ((Arg == "-MF") || (Arg == "-MT") || (Arg == "-MQ") ||
+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
// RUN: mkdir -p %t/sub/dir
2+
// RUN: echo > %t/sub/empty.h
3+
4+
// Test that system header paths are expanded
5+
//
6+
// RUN: %clang -fsyntax-only -MD -MF %t.d -MT foo %s -isystem %t/sub/dir/..
7+
// RUN: FileCheck -check-prefix=TEST1 %s < %t.d
8+
// TEST1: foo:
9+
// TEST1: sub{{/|\\}}empty.h
10+
11+
// Test that system header paths are not expanded to a longer form
12+
//
13+
// RUN: cd %t && %clang -fsyntax-only -MD -MF %t.d -MT foo %s -isystem sub/dir/..
14+
// RUN: FileCheck -check-prefix=TEST2 %s < %t.d
15+
// TEST2: foo:
16+
// TEST2: sub/dir/..{{/|\\}}empty.h
17+
18+
// Test that user header paths are not expanded
19+
//
20+
// RUN: %clang -fsyntax-only -MD -MF %t.d -MT foo %s -I %t/sub/dir/..
21+
// RUN: FileCheck -check-prefix=TEST3 %s < %t.d
22+
// TEST3: foo:
23+
// TEST3: sub/dir/..{{/|\\}}empty.h
24+
25+
// Test that system header paths are not expanded with -fno-canonical-system-headers
26+
// (and also that the -fsystem-system-headers option is accepted)
27+
//
28+
// RUN: %clang -fsyntax-only -MD -MF %t.d -MT foo %s -I %t/sub/dir/.. -fcanonical-system-headers -fno-canonical-system-headers
29+
// RUN: FileCheck -check-prefix=TEST4 %s < %t.d
30+
// TEST4: foo:
31+
// TEST4: sub/dir/..{{/|\\}}empty.h
32+
33+
#include <empty.h>

0 commit comments

Comments
 (0)