Skip to content

Commit 3a9de0b

Browse files
committed
[clang] Absoultify paths in dependency file output
This fixes #117438. If paths in dependency file are not absoulte, make (or ninja) will canonicalize them. While their canonicalization does not involves symbolic links expansion (for IO performance concerns), leaving a non-absolute path in dependency file may lead to unexpected canonicalization. For example, '/a/../b', where '/a' is a symlink to '/c/d', it should be '/c/b' but make (and ninja) canonicalizes it as '/b', and fails for file not found. Signed-off-by: Bingwu Zhang <[email protected]>
1 parent dc4c8de commit 3a9de0b

File tree

2 files changed

+14
-4
lines changed

2 files changed

+14
-4
lines changed

clang/include/clang/Frontend/Utils.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,7 @@ class DependencyFileGenerator : public DependencyCollector {
120120
private:
121121
void outputDependencyFile(DiagnosticsEngine &Diags);
122122

123+
llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS;
123124
std::string OutputFile;
124125
std::vector<std::string> Targets;
125126
bool IncludeSystemHeaders;

clang/lib/Frontend/DependencyFile.cpp

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,11 @@
1010
//
1111
//===----------------------------------------------------------------------===//
1212

13-
#include "clang/Frontend/Utils.h"
1413
#include "clang/Basic/FileManager.h"
1514
#include "clang/Basic/SourceManager.h"
1615
#include "clang/Frontend/DependencyOutputOptions.h"
1716
#include "clang/Frontend/FrontendDiagnostic.h"
17+
#include "clang/Frontend/Utils.h"
1818
#include "clang/Lex/DirectoryLookup.h"
1919
#include "clang/Lex/ModuleMap.h"
2020
#include "clang/Lex/PPCallbacks.h"
@@ -23,6 +23,7 @@
2323
#include "llvm/ADT/StringSet.h"
2424
#include "llvm/Support/FileSystem.h"
2525
#include "llvm/Support/Path.h"
26+
#include "llvm/Support/VirtualFileSystem.h"
2627
#include "llvm/Support/raw_ostream.h"
2728
#include <optional>
2829

@@ -236,6 +237,7 @@ void DependencyFileGenerator::attachToPreprocessor(Preprocessor &PP) {
236237
PP.SetSuppressIncludeNotFoundError(true);
237238

238239
DependencyCollector::attachToPreprocessor(PP);
240+
FS = PP.getFileManager().getVirtualFileSystemPtr();
239241
}
240242

241243
bool DependencyFileGenerator::sawDependency(StringRef Filename, bool FromModule,
@@ -312,11 +314,18 @@ void DependencyFileGenerator::finishedMainFile(DiagnosticsEngine &Diags) {
312314
/// https://msdn.microsoft.com/en-us/library/dd9y37ha.aspx for NMake info,
313315
/// https://msdn.microsoft.com/en-us/library/windows/desktop/aa365247(v=vs.85).aspx
314316
/// for Windows file-naming info.
315-
static void PrintFilename(raw_ostream &OS, StringRef Filename,
317+
static void PrintFilename(raw_ostream &OS, llvm::vfs::FileSystem *FS,
318+
StringRef Filename,
316319
DependencyOutputFormat OutputFormat) {
317320
// Convert filename to platform native path
318321
llvm::SmallString<256> NativePath;
319322
llvm::sys::path::native(Filename.str(), NativePath);
323+
// Make path absolute. Make and Ninja canonicalize paths without checking for
324+
// symbolic links in the path, for performance concerns.
325+
// If there is something like `/bin/../lib64` -> `/usr/lib64`
326+
// (where `/bin` links to `/usr/bin`), Make will see them as `/lib64`.
327+
if (FS != nullptr && llvm::sys::path::is_absolute(NativePath))
328+
FS->makeAbsolute(NativePath);
320329

321330
if (OutputFormat == DependencyOutputFormat::NMake) {
322331
// Add quotes if needed. These are the characters listed as "special" to
@@ -400,7 +409,7 @@ void DependencyFileGenerator::outputDependencyFile(llvm::raw_ostream &OS) {
400409
Columns = 2;
401410
}
402411
OS << ' ';
403-
PrintFilename(OS, File, OutputFormat);
412+
PrintFilename(OS, FS.get(), File, OutputFormat);
404413
Columns += N + 1;
405414
}
406415
OS << '\n';
@@ -411,7 +420,7 @@ void DependencyFileGenerator::outputDependencyFile(llvm::raw_ostream &OS) {
411420
for (auto I = Files.begin(), E = Files.end(); I != E; ++I) {
412421
if (Index++ == InputFileIndex)
413422
continue;
414-
PrintFilename(OS, *I, OutputFormat);
423+
PrintFilename(OS, FS.get(), *I, OutputFormat);
415424
OS << ":\n";
416425
}
417426
}

0 commit comments

Comments
 (0)