Skip to content

Commit 918bd3d

Browse files
authored
Merge pull request #71956 from benlangmuir/clang-prefix-map-consistent
[Caching] Use clang to prefix-map -fmodule-file-cache-key paths
2 parents ff11aab + 576cc8c commit 918bd3d

File tree

7 files changed

+115
-36
lines changed

7 files changed

+115
-36
lines changed

include/swift/AST/ModuleDependencies.h

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -366,7 +366,11 @@ class ClangModuleDependencyStorage : public ModuleDependencyInfoStorageBase {
366366
public:
367367
/// Destination output path
368368
const std::string pcmOutputPath;
369-
369+
370+
/// Same as \c pcmOutputPath, but possibly prefix-mapped using clang's prefix
371+
/// mapper.
372+
const std::string mappedPCMPath;
373+
370374
/// The module map file used to generate the Clang module.
371375
const std::string moduleMapFile;
372376

@@ -390,6 +394,7 @@ class ClangModuleDependencyStorage : public ModuleDependencyInfoStorageBase {
390394
std::string CASClangIncludeTreeRootID;
391395

392396
ClangModuleDependencyStorage(const std::string &pcmOutputPath,
397+
const std::string &mappedPCMPath,
393398
const std::string &moduleMapFile,
394399
const std::string &contextHash,
395400
const std::vector<std::string> &buildCommandLine,
@@ -400,9 +405,10 @@ class ClangModuleDependencyStorage : public ModuleDependencyInfoStorageBase {
400405
const std::string &moduleCacheKey)
401406
: ModuleDependencyInfoStorageBase(ModuleDependencyKind::Clang,
402407
moduleCacheKey),
403-
pcmOutputPath(pcmOutputPath), moduleMapFile(moduleMapFile),
404-
contextHash(contextHash), buildCommandLine(buildCommandLine),
405-
fileDependencies(fileDependencies), capturedPCMArgs(capturedPCMArgs),
408+
pcmOutputPath(pcmOutputPath), mappedPCMPath(mappedPCMPath),
409+
moduleMapFile(moduleMapFile), contextHash(contextHash),
410+
buildCommandLine(buildCommandLine), fileDependencies(fileDependencies),
411+
capturedPCMArgs(capturedPCMArgs),
406412
CASFileSystemRootID(CASFileSystemRootID),
407413
CASClangIncludeTreeRootID(clangIncludeTreeRoot) {}
408414

@@ -526,20 +532,18 @@ class ModuleDependencyInfo {
526532
/// Describe the module dependencies for a Clang module that can be
527533
/// built from a module map and headers.
528534
static ModuleDependencyInfo forClangModule(
529-
const std::string &pcmOutputPath,
530-
const std::string &moduleMapFile,
531-
const std::string &contextHash,
535+
const std::string &pcmOutputPath, const std::string &mappedPCMPath,
536+
const std::string &moduleMapFile, const std::string &contextHash,
532537
const std::vector<std::string> &nonPathCommandLine,
533538
const std::vector<std::string> &fileDependencies,
534539
const std::vector<std::string> &capturedPCMArgs,
535540
const std::string &CASFileSystemRootID,
536541
const std::string &clangIncludeTreeRoot,
537542
const std::string &moduleCacheKey) {
538-
return ModuleDependencyInfo(
539-
std::make_unique<ClangModuleDependencyStorage>(
540-
pcmOutputPath, moduleMapFile, contextHash,
541-
nonPathCommandLine, fileDependencies, capturedPCMArgs,
542-
CASFileSystemRootID, clangIncludeTreeRoot, moduleCacheKey));
543+
return ModuleDependencyInfo(std::make_unique<ClangModuleDependencyStorage>(
544+
pcmOutputPath, mappedPCMPath, moduleMapFile, contextHash,
545+
nonPathCommandLine, fileDependencies, capturedPCMArgs,
546+
CASFileSystemRootID, clangIncludeTreeRoot, moduleCacheKey));
543547
}
544548

545549
/// Describe a placeholder dependency swift module.

include/swift/ClangImporter/ClangImporter.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -446,7 +446,9 @@ class ClangImporter final : public ClangModuleLoader {
446446
void verifyAllModules() override;
447447

448448
using RemapPathCallback = llvm::function_ref<std::string(StringRef)>;
449-
llvm::SmallVector<std::pair<ModuleDependencyID, ModuleDependencyInfo>, 1> bridgeClangModuleDependencies(
449+
llvm::SmallVector<std::pair<ModuleDependencyID, ModuleDependencyInfo>, 1>
450+
bridgeClangModuleDependencies(
451+
clang::tooling::dependencies::DependencyScanningTool &clangScanningTool,
450452
clang::tooling::dependencies::ModuleDepsGraph &clangDependencies,
451453
StringRef moduleOutputPath, RemapPathCallback remapPath = nullptr);
452454

include/swift/DependencyScan/SerializedModuleDependencyCacheFormat.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,8 @@ using llvm::BCVBR;
3939

4040
/// Every .moddepcache file begins with these 4 bytes, for easy identification.
4141
const unsigned char MODULE_DEPENDENCY_CACHE_FORMAT_SIGNATURE[] = {'I', 'M', 'D','C'};
42-
const unsigned MODULE_DEPENDENCY_CACHE_FORMAT_VERSION_MAJOR = 5; // optionalModuleImports
42+
const unsigned MODULE_DEPENDENCY_CACHE_FORMAT_VERSION_MAJOR =
43+
6; // mappedPCMPath
4344
/// Increment this on every change.
4445
const unsigned MODULE_DEPENDENCY_CACHE_FORMAT_VERSION_MINOR = 1;
4546

@@ -182,6 +183,7 @@ using SwiftPlaceholderModuleDetailsLayout =
182183
using ClangModuleDetailsLayout =
183184
BCRecordLayout<CLANG_MODULE_DETAILS_NODE, // ID
184185
FileIDField, // pcmOutputPath
186+
FileIDField, // mappedPCMPath
185187
FileIDField, // moduleMapPath
186188
ContextHashIDField, // contextHash
187189
FlagIDArrayIDField, // commandLine

lib/ClangImporter/ClangModuleDependencyScanner.cpp

Lines changed: 35 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -127,9 +127,29 @@ static std::vector<std::string> getClangDepScanningInvocationArguments(
127127
return commandLineArgs;
128128
}
129129

130+
static std::unique_ptr<llvm::PrefixMapper>
131+
getClangPrefixMapper(DependencyScanningTool &clangScanningTool,
132+
ModuleDeps &clangModuleDep,
133+
clang::CompilerInvocation &depsInvocation) {
134+
std::unique_ptr<llvm::PrefixMapper> Mapper;
135+
if (clangModuleDep.IncludeTreeID) {
136+
Mapper = std::make_unique<llvm::PrefixMapper>();
137+
} else if (clangModuleDep.CASFileSystemRootID) {
138+
assert(clangScanningTool.getCachingFileSystem());
139+
Mapper = std::make_unique<llvm::TreePathPrefixMapper>(
140+
clangScanningTool.getCachingFileSystem());
141+
}
142+
143+
if (Mapper)
144+
DepscanPrefixMapping::configurePrefixMapper(depsInvocation, *Mapper);
145+
146+
return Mapper;
147+
}
148+
130149
ModuleDependencyVector ClangImporter::bridgeClangModuleDependencies(
131-
clang::tooling::dependencies::ModuleDepsGraph &clangDependencies,
132-
StringRef moduleOutputPath, RemapPathCallback callback) {
150+
clang::tooling::dependencies::DependencyScanningTool &clangScanningTool,
151+
clang::tooling::dependencies::ModuleDepsGraph &clangDependencies,
152+
StringRef moduleOutputPath, RemapPathCallback callback) {
133153
const auto &ctx = Impl.SwiftContext;
134154
ModuleDependencyVector result;
135155

@@ -206,6 +226,10 @@ ModuleDependencyVector ClangImporter::bridgeClangModuleDependencies(
206226
(void)success;
207227
assert(success && "clang option from dep scanner round trip failed");
208228

229+
// Create a prefix mapper that matches clang's configuration.
230+
auto Mapper =
231+
getClangPrefixMapper(clangScanningTool, clangModuleDep, depsInvocation);
232+
209233
// Clear the cache key for module. The module key is computed from clang
210234
// invocation, not swift invocation.
211235
depsInvocation.getFrontendOpts().ModuleCacheKeys.clear();
@@ -251,10 +275,14 @@ ModuleDependencyVector ClangImporter::bridgeClangModuleDependencies(
251275
swiftArgs.push_back(IncludeTree);
252276
}
253277

278+
std::string mappedPCMPath = pcmPath;
279+
if (Mapper)
280+
Mapper->mapInPlace(mappedPCMPath);
281+
254282
// Module-level dependencies.
255283
llvm::StringSet<> alreadyAddedModules;
256284
auto dependencies = ModuleDependencyInfo::forClangModule(
257-
pcmPath, clangModuleDep.ClangModuleMapFile,
285+
pcmPath, mappedPCMPath, clangModuleDep.ClangModuleMapFile,
258286
clangModuleDep.ID.ContextHash, swiftArgs, fileDeps, capturedPCMArgs,
259287
RootID, IncludeTree, /*module-cache-key*/ "");
260288
for (const auto &moduleName : clangModuleDep.ClangModuleDeps) {
@@ -414,7 +442,8 @@ ClangImporter::getModuleDependencies(Identifier moduleName,
414442
return {};
415443
}
416444

417-
return bridgeClangModuleDependencies(*clangModuleDependencies,
445+
return bridgeClangModuleDependencies(clangScanningTool,
446+
*clangModuleDependencies,
418447
moduleOutputPath, [&](StringRef path) {
419448
if (mapper)
420449
return mapper->mapToString(path);
@@ -479,8 +508,8 @@ bool ClangImporter::addBridgingHeaderDependencies(
479508

480509
// Record module dependencies for each new module we found.
481510
auto bridgedDeps = bridgeClangModuleDependencies(
482-
clangModuleDependencies->ModuleGraph, cache.getModuleOutputPath(),
483-
[&cache](StringRef path) {
511+
clangScanningTool, clangModuleDependencies->ModuleGraph,
512+
cache.getModuleOutputPath(), [&cache](StringRef path) {
484513
return cache.getScanService().remapPath(path);
485514
});
486515
cache.recordDependencies(bridgedDeps);

lib/DependencyScan/ModuleDependencyCacheSerialization.cpp

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -557,19 +557,20 @@ bool ModuleDependenciesCacheDeserializer::readGraph(SwiftDependencyScanningServi
557557
if (!hasCurrentModule)
558558
llvm::report_fatal_error("Unexpected CLANG_MODULE_DETAILS_NODE record");
559559
cache.configureForContextHash(getContextHash());
560-
unsigned pcmOutputPathID, moduleMapPathID, contextHashID, commandLineArrayID,
561-
fileDependenciesArrayID, capturedPCMArgsArrayID, CASFileSystemRootID,
562-
clangIncludeTreeRootID, moduleCacheKeyID;
563-
ClangModuleDetailsLayout::readRecord(Scratch, pcmOutputPathID, moduleMapPathID,
564-
contextHashID, commandLineArrayID,
565-
fileDependenciesArrayID,
566-
capturedPCMArgsArrayID,
567-
CASFileSystemRootID,
568-
clangIncludeTreeRootID,
569-
moduleCacheKeyID);
560+
unsigned pcmOutputPathID, mappedPCMPathID, moduleMapPathID, contextHashID,
561+
commandLineArrayID, fileDependenciesArrayID, capturedPCMArgsArrayID,
562+
CASFileSystemRootID, clangIncludeTreeRootID, moduleCacheKeyID;
563+
ClangModuleDetailsLayout::readRecord(
564+
Scratch, pcmOutputPathID, mappedPCMPathID, moduleMapPathID,
565+
contextHashID, commandLineArrayID, fileDependenciesArrayID,
566+
capturedPCMArgsArrayID, CASFileSystemRootID, clangIncludeTreeRootID,
567+
moduleCacheKeyID);
570568
auto pcmOutputPath = getIdentifier(pcmOutputPathID);
571569
if (!pcmOutputPath)
572570
llvm::report_fatal_error("Bad pcm output path");
571+
auto mappedPCMPath = getIdentifier(mappedPCMPathID);
572+
if (!mappedPCMPath)
573+
llvm::report_fatal_error("Bad mapped pcm path");
573574
auto moduleMapPath = getIdentifier(moduleMapPathID);
574575
if (!moduleMapPath)
575576
llvm::report_fatal_error("Bad module map path");
@@ -597,9 +598,9 @@ bool ModuleDependenciesCacheDeserializer::readGraph(SwiftDependencyScanningServi
597598

598599
// Form the dependencies storage object
599600
auto moduleDep = ModuleDependencyInfo::forClangModule(
600-
*pcmOutputPath, *moduleMapPath, *contextHash, *commandLineArgs,
601-
*fileDependencies, *capturedPCMArgs, *rootFileSystemID,
602-
*clangIncludeTreeRoot, *moduleCacheKey);
601+
*pcmOutputPath, *mappedPCMPath, *moduleMapPath, *contextHash,
602+
*commandLineArgs, *fileDependencies, *capturedPCMArgs,
603+
*rootFileSystemID, *clangIncludeTreeRoot, *moduleCacheKey);
603604

604605
// Add dependencies of this module
605606
for (const auto &moduleName : *currentModuleImports)
@@ -1036,6 +1037,7 @@ void ModuleDependenciesCacheSerializer::writeModuleInfo(
10361037
ClangModuleDetailsLayout::emitRecord(
10371038
Out, ScratchRecord, AbbrCodes[ClangModuleDetailsLayout::Code],
10381039
getIdentifier(clangDeps->pcmOutputPath),
1040+
getIdentifier(clangDeps->mappedPCMPath),
10391041
getIdentifier(clangDeps->moduleMapFile),
10401042
getIdentifier(clangDeps->contextHash),
10411043
getArrayID(moduleID, ModuleIdentifierArrayKind::NonPathCommandLine),
@@ -1240,6 +1242,7 @@ void ModuleDependenciesCacheSerializer::collectStringsAndArrays(
12401242
auto clangDeps = dependencyInfo->getAsClangModule();
12411243
assert(clangDeps);
12421244
addIdentifier(clangDeps->pcmOutputPath);
1245+
addIdentifier(clangDeps->mappedPCMPath);
12431246
addIdentifier(clangDeps->moduleMapFile);
12441247
addIdentifier(clangDeps->contextHash);
12451248
addStringArray(moduleID, ModuleIdentifierArrayKind::NonPathCommandLine,

lib/DependencyScan/ScanDependencies.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -286,7 +286,7 @@ static llvm::Error resolveExplicitModuleInputs(
286286
if (!resolvingDepInfo.isClangModule()) {
287287
commandLine.push_back("-Xcc");
288288
commandLine.push_back("-fmodule-file=" + depModuleID.ModuleName + "=" +
289-
remapPath(clangDepDetails->pcmOutputPath));
289+
clangDepDetails->mappedPCMPath);
290290
if (!instance.getInvocation()
291291
.getClangImporterOptions()
292292
.UseClangIncludeTree) {
@@ -307,7 +307,7 @@ static llvm::Error resolveExplicitModuleInputs(
307307
appendXclang();
308308
commandLine.push_back("-fmodule-file-cache-key");
309309
appendXclang();
310-
commandLine.push_back(remapPath(clangDepDetails->pcmOutputPath));
310+
commandLine.push_back(clangDepDetails->mappedPCMPath);
311311
appendXclang();
312312
commandLine.push_back(clangDepDetails->moduleCacheKey);
313313
}
@@ -373,7 +373,7 @@ static llvm::Error resolveExplicitModuleInputs(
373373
newCommandLine.push_back("-Xcc");
374374
newCommandLine.push_back("-fmodule-file-cache-key");
375375
newCommandLine.push_back("-Xcc");
376-
newCommandLine.push_back(remapPath(clangDep->pcmOutputPath));
376+
newCommandLine.push_back(clangDep->mappedPCMPath);
377377
newCommandLine.push_back("-Xcc");
378378
newCommandLine.push_back(clangDep->moduleCacheKey);
379379
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
// Test that after compiling a module to a path containing a symlink we still
2+
// get the same scanner output.
3+
4+
// REQUIRES: OS=macosx
5+
6+
// RUN: %empty-directory(%t)
7+
// RUN: split-file %s %t
8+
// RUN: mkdir %t/module-outputs
9+
// RUN: ln -s module-outputs %t/symlink
10+
11+
// RUN: %target-swift-frontend -scan-dependencies %t/a.swift -o %t/deps.json -module-name A -emit-dependencies -emit-dependencies-path %t/deps.d -disable-implicit-concurrency-module-import -disable-implicit-string-processing-module-import -I %t -module-cache-path %t/symlink -verify -cache-compile-job -cas-path %t/cas
12+
// Check the contents of the JSON output
13+
// RUN: %validate-json %t/deps.json | %FileCheck %s
14+
15+
// CHECK: "-fmodule-file=C=[[PCM_PATH:.*symlink.*C-.*.pcm]]"
16+
// CHECK: "-fmodule-file-cache-key"
17+
// CHECK-NEXT: "-Xcc"
18+
// CHECK-NEXT: "[[PCM_PATH]]"
19+
// CHECK-NEXT: "-Xcc"
20+
// CHECK-NEXT: "llvmcas://
21+
22+
// Emit one of the modules, which will be in the symlinked path.
23+
// RUN: %{python} %S/../CAS/Inputs/BuildCommandExtractor.py %t/deps.json clang:C > %t/C.cmd
24+
// RUN: %swift_frontend_plain @%t/C.cmd
25+
26+
// RUN: %target-swift-frontend -scan-dependencies %t/a.swift -o %t/deps2.json -module-name A -emit-dependencies -emit-dependencies-path %t/deps.d -disable-implicit-concurrency-module-import -disable-implicit-string-processing-module-import -I %t -module-cache-path %t/symlink -verify -cache-compile-job -cas-path %t/cas
27+
// RUN: diff -u %t/deps.json %t/deps2.json
28+
29+
//--- module.modulemap
30+
module B { header "B.h" }
31+
module C { header "C.h" }
32+
33+
//--- B.h
34+
#include "C.h"
35+
36+
//--- C.h
37+
38+
//--- a.swift
39+
import B

0 commit comments

Comments
 (0)