Skip to content

Commit 8a3842b

Browse files
committed
[clang][depscan] Support prefix mappings when deciding modules that come
from "stable" directories To support compiler caching, clang may strip out common prefixes from paths like the sysroot. When this happens, include both the initial input paths that would get mapped away and the resulting mapped prefix for determining module dependencies that come from stable directories. This is to handle all of the ways paths may come streaming. For example, input paths that represented included headers will contain an absolute paths for handling indirections like vfsoverlays but sysroot's from `CompilerInstance`'s will be mapped.
1 parent bf481f3 commit 8a3842b

6 files changed

+122
-10
lines changed

clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp

+19
Original file line numberDiff line numberDiff line change
@@ -586,6 +586,11 @@ class DependencyScanningAction : public tooling::ToolAction {
586586
auto *FileMgr = ScanInstance.createFileManager(FS);
587587
ScanInstance.createSourceManager(*FileMgr);
588588

589+
// Initialize PrefixMapper incase mappings exist.
590+
DepscanPrefixMapping::configurePrefixMapper(
591+
ScanInstance.getFrontendOpts().PathPrefixMappings,
592+
ScanInstance.getPrefixMapper());
593+
589594
// Create a collection of stable directories derived from the ScanInstance
590595
// for determining whether module dependencies would fully resolve from
591596
// those directories.
@@ -595,6 +600,20 @@ class DependencyScanningAction : public tooling::ToolAction {
595600
(llvm::sys::path::root_directory(Sysroot) != Sysroot))
596601
StableDirs = {Sysroot, ScanInstance.getHeaderSearchOpts().ResourceDir};
597602

603+
// When remapping is disabled, the stable directory paths are references to
604+
// strings tied to the CompilerInstance. Otherwise, these potentially mapped
605+
// strings need to be allocated. To reduce the number of downstream changes
606+
// required to this support allocation, tie the lifetime of these strings to
607+
// visiting all dependencies of a prebuilt module.
608+
llvm::PrefixMapper &Mapper = ScanInstance.getPrefixMapper();
609+
llvm::BumpPtrAllocator Allocator;
610+
llvm::StringSaver StableDirStorage(Allocator);
611+
if (!StableDirs.empty() && !Mapper.empty()) {
612+
StableDirs.push_back(StableDirStorage.save(Mapper.mapToString(Sysroot)));
613+
StableDirs.push_back(StableDirStorage.save(
614+
Mapper.mapToString(ScanInstance.getHeaderSearchOpts().ResourceDir)));
615+
}
616+
598617
// Store a mapping of prebuilt module files and their properties like header
599618
// search options. This will prevent the implicit build to create duplicate
600619
// modules and will force reuse of the existing prebuilt module files

clang/lib/Tooling/DependencyScanning/ModuleDepCollector.cpp

+4-5
Original file line numberDiff line numberDiff line change
@@ -255,12 +255,11 @@ bool dependencies::isPathInStableDir(const ArrayRef<StringRef> Directories,
255255

256256
bool dependencies::areOptionsInStableDir(const ArrayRef<StringRef> Directories,
257257
const HeaderSearchOptions &HSOpts) {
258-
// FIXME: This breaks CAS prefix mapping tests.
259-
// assert(isPathInStableDir(Directories, HSOpts.Sysroot) &&
260-
// "Sysroots differ between module dependencies and current TU");
258+
assert(isPathInStableDir(Directories, HSOpts.Sysroot) &&
259+
"Sysroots differ between module dependencies and current TU");
261260

262-
// assert(isPathInStableDir(Directories, HSOpts.ResourceDir) &&
263-
// "ResourceDirs differ between module dependencies and current TU");
261+
assert(isPathInStableDir(Directories, HSOpts.ResourceDir) &&
262+
"ResourceDirs differ between module dependencies and current TU");
264263

265264
for (const auto &Entry : HSOpts.UserEntries) {
266265
if (!Entry.IgnoreSysRoot)

clang/test/ClangScanDeps/include-tree-with-pch.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
// RUN: split-file %s %t
44
// RUN: sed -e "s|DIR|%/t|g" %t/cdb.json.template > %t/cdb.json
55

6-
// RUN: %clang -x c-header %t/prefix.h -target x86_64-apple-macos12 -o %t/prefix.pch -fdepscan=inline -fdepscan-include-tree -Xclang -fcas-path -Xclang %t/cas
6+
// RUN: %clang -x c-header %t/prefix.h -target x86_64-apple-macos12 -isysroot %t -o %t/prefix.pch -fdepscan=inline -fdepscan-include-tree -Xclang -fcas-path -Xclang %t/cas
77
// RUN: clang-scan-deps -compilation-database %t/cdb.json -format experimental-include-tree -cas-path %t/cas > %t/result.txt
88
// RUN: FileCheck %s -input-file %t/result.txt -DPREFIX=%/t
99

clang/test/ClangScanDeps/modules-cas-trees-input-files.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@
3737
[
3838
{
3939
"directory" : "DIR",
40-
"command" : "clang_tool -I DIR -x c-header DIR/prefix.h -o DIR/prefix.h.pch -fmodules -fimplicit-modules -fimplicit-module-maps -fmodules-cache-path=DIR/module-cache -Rcompile-job-cache",
40+
"command" : "clang -I DIR -x c-header DIR/prefix.h -o DIR/prefix.h.pch -fmodules -fimplicit-modules -fimplicit-module-maps -fmodules-cache-path=DIR/module-cache -Rcompile-job-cache",
4141
"file" : "DIR/prefix.h"
4242
},
4343
]
@@ -46,7 +46,7 @@
4646
[
4747
{
4848
"directory" : "DIR",
49-
"command" : "clang_tool -I DIR -fsyntax-only DIR/tu.c -include DIR/prefix.h -fmodules -fimplicit-modules -fimplicit-module-maps -fmodules-cache-path=DIR/module-cache -Rcompile-job-cache",
49+
"command" : "clang -I DIR -fsyntax-only DIR/tu.c -include DIR/prefix.h -fmodules -fimplicit-modules -fimplicit-module-maps -fmodules-cache-path=DIR/module-cache -Rcompile-job-cache",
5050
"file" : "DIR/tu.c"
5151
},
5252
]

clang/test/ClangScanDeps/modules-cas-trees-with-pch.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -191,7 +191,7 @@
191191
[
192192
{
193193
"directory" : "DIR",
194-
"command" : "clang_tool -x c-header DIR/prefix.h -o DIR/prefix.h.pch -fmodules -fimplicit-modules -fimplicit-module-maps -fmodules-cache-path=DIR/module-cache -Rcompile-job-cache",
194+
"command" : "clang -x c-header DIR/prefix.h -o DIR/prefix.h.pch -fmodules -fimplicit-modules -fimplicit-module-maps -fmodules-cache-path=DIR/module-cache -Rcompile-job-cache",
195195
"file" : "DIR/prefix.h"
196196
},
197197
]
@@ -200,7 +200,7 @@
200200
[
201201
{
202202
"directory" : "DIR",
203-
"command" : "clang_tool -fsyntax-only DIR/tu.c -include DIR/prefix.h -fmodules -fimplicit-modules -fimplicit-module-maps -fmodules-cache-path=DIR/module-cache -Rcompile-job-cache",
203+
"command" : "clang -fsyntax-only DIR/tu.c -include DIR/prefix.h -fmodules -fimplicit-modules -fimplicit-module-maps -fmodules-cache-path=DIR/module-cache -Rcompile-job-cache",
204204
"file" : "DIR/tu.c"
205205
},
206206
]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
// This test verifies modules that are entirely comprised from stable directory inputs are captured in
2+
// dependency information when paths are prefix mapped.
3+
4+
// REQUIRES: shell,ondisk_cas
5+
6+
// RUN: rm -rf %t
7+
// RUN: split-file %s %t
8+
// RUN: sed -e "s|DIR|%/t|g" %t/overlay.json.template > %t/overlay.json
9+
// RUN: sed -e "s|DIR|%/t|g" %t/compile.json.in > %t/compile.json
10+
11+
// RUN: clang-scan-deps -compilation-database %t/compile.json \
12+
// RUN: -prefix-map=%t/modules=/^modules -prefix-map=%t=/^src -prefix-map-sdk=/^sdk -prefix-map-toolchain=/^tc \
13+
// RUN: -cas-path %t/cas -module-files-dir %t/modules \
14+
// RUN: -j 1 -format experimental-full > %t/deps.db
15+
16+
// RUN: cat %t/deps.db | sed 's:\\\\\?:/:g' | FileCheck %s -DPREFIX=%/t --check-prefix DEP
17+
18+
// DEP: "is-in-stable-directories": true
19+
// DEP: "name": "A"
20+
21+
// CHECK-NOT: "is-in-stable-directories": true
22+
// CHECK-NOT: warning:
23+
// CHECK-NOT: error:
24+
25+
//--- compile.json.in
26+
[
27+
{
28+
"directory": "DIR",
29+
"command": "clang -x c -c DIR/client.c -isysroot DIR/MacOSX.sdk -IDIR/BuildDir -ivfsoverlay DIR/overlay.json -IDIR/MacOSX.sdk/usr/include -fmodules -fmodules-cache-path=DIR/module-cache -fimplicit-module-maps -o DIR/client.c.o",
30+
"file": "DIR/client.c"
31+
}
32+
]
33+
34+
//--- overlay.json.template
35+
{
36+
"version": 0,
37+
"case-sensitive": "false",
38+
"roots": [
39+
{
40+
"external-contents": "DIR/BuildDir/B_vfs.h",
41+
"name": "DIR/MacOSX.sdk/usr/include/B/B_vfs.h",
42+
"type": "file"
43+
}
44+
]
45+
}
46+
47+
//--- MacOSX.sdk/usr/include/A/module.modulemap
48+
module A [system] {
49+
umbrella "."
50+
}
51+
52+
//--- MacOSX.sdk/usr/include/A/A.h
53+
typedef int A_type;
54+
55+
//--- MacOSX.sdk/usr/include/B/module.modulemap
56+
module B [system] {
57+
umbrella "."
58+
}
59+
60+
//--- MacOSX.sdk/usr/include/B/B.h
61+
#include <B/B_vfs.h>
62+
63+
//--- BuildDir/B_vfs.h
64+
typedef int local_t;
65+
66+
//--- MacOSX.sdk/usr/include/sys/sys.h
67+
#include <A/A.h>
68+
typedef int sys_t_m;
69+
70+
//--- MacOSX.sdk/usr/include/sys/module.modulemap
71+
module sys [system] {
72+
umbrella "."
73+
}
74+
75+
//--- MacOSX.sdk/usr/include/B_transitive/B.h
76+
#include <B/B.h>
77+
78+
//--- MacOSX.sdk/usr/include/B_transitive/module.modulemap
79+
module B_transitive [system] {
80+
umbrella "."
81+
}
82+
83+
//--- MacOSX.sdk/usr/include/C/module.modulemap
84+
module C [system] {
85+
umbrella "."
86+
}
87+
88+
//--- MacOSX.sdk/usr/include/C/C.h
89+
#include <B_transitive/B.h>
90+
91+
92+
//--- client.c
93+
#include <A/A.h>
94+
#include <C/C.h> // This dependency transitively depends on a local header.

0 commit comments

Comments
 (0)