Skip to content

Commit 68eb3b2

Browse files
authored
[clang][deps] Collect discovered module dependencies' Link Libraries (#93588)
This will allow scanner clients to be able to compute e.g. auto-linking dependencies of the scanned translation unit.
1 parent 7b34635 commit 68eb3b2

36 files changed

+285
-9
lines changed

clang/include/clang/Tooling/DependencyScanning/ModuleDepCollector.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#define LLVM_CLANG_TOOLING_DEPENDENCYSCANNING_MODULEDEPCOLLECTOR_H
1111

1212
#include "clang/Basic/LLVM.h"
13+
#include "clang/Basic/Module.h"
1314
#include "clang/Basic/SourceManager.h"
1415
#include "clang/Frontend/CompilerInvocation.h"
1516
#include "clang/Frontend/Utils.h"
@@ -138,6 +139,10 @@ struct ModuleDeps {
138139
/// determined that the differences are benign for this compilation.
139140
std::vector<ModuleID> ClangModuleDeps;
140141

142+
/// The set of libraries or frameworks to link against when
143+
/// an entity from this module is used.
144+
llvm::SmallVector<Module::LinkLibrary, 2> LinkLibraries;
145+
141146
/// Get (or compute) the compiler invocation that can be used to build this
142147
/// module. Does not include argv[0].
143148
const std::vector<std::string> &getBuildArguments();

clang/lib/Tooling/DependencyScanning/ModuleDepCollector.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -578,6 +578,10 @@ ModuleDepCollectorPP::handleTopLevelModule(const Module *M) {
578578

579579
MD.ID.ModuleName = M->getFullModuleName();
580580
MD.IsSystem = M->IsSystem;
581+
// For modules which use export_as link name, the linked product that of the
582+
// corresponding export_as-named module.
583+
if (!M->UseExportAsModuleLinkName)
584+
MD.LinkLibraries = M->LinkLibraries;
581585

582586
ModuleMap &ModMapInfo =
583587
MDC.ScanInstance.getPreprocessor().getHeaderSearchInfo().getModuleMap();

clang/test/ClangScanDeps/diagnostics.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ module mod { header "mod.h" }
3737
// CHECK-NEXT: "[[PREFIX]]/mod.h"
3838
// CHECK-NEXT: "[[PREFIX]]/module.modulemap"
3939
// CHECK-NEXT: ],
40+
// CHECK-NEXT: "link-libraries": [],
4041
// CHECK-NEXT: "name": "mod"
4142
// CHECK-NEXT: }
4243
// CHECK-NEXT: ],

clang/test/ClangScanDeps/header-search-pruning-transitive.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ module X { header "X.h" }
7575
// CHECK-NEXT: "[[PREFIX]]/X.h",
7676
// CHECK-NEXT: "[[PREFIX]]/module.modulemap"
7777
// CHECK-NEXT: ],
78+
// CHECK-NEXT: "link-libraries": [],
7879
// CHECK-NEXT: "name": "X"
7980
// CHECK-NEXT: },
8081
// CHECK-NEXT: {
@@ -90,6 +91,7 @@ module X { header "X.h" }
9091
// CHECK-NEXT: "[[PREFIX]]/end/end.h",
9192
// CHECK-NEXT: "[[PREFIX]]/module.modulemap"
9293
// CHECK-NEXT: ],
94+
// CHECK-NEXT: "link-libraries": [],
9395
// CHECK-NEXT: "name": "Y"
9496
// CHECK-NEXT: }
9597
// CHECK-NEXT: ],
@@ -129,6 +131,7 @@ module X { header "X.h" }
129131
// CHECK-NEXT: "[[PREFIX]]/X.h",
130132
// CHECK-NEXT: "[[PREFIX]]/module.modulemap"
131133
// CHECK-NEXT: ],
134+
// CHECK-NEXT: "link-libraries": [],
132135
// CHECK-NEXT: "name": "X"
133136
// CHECK-NEXT: },
134137
// CHECK-NEXT: {
@@ -143,6 +146,7 @@ module X { header "X.h" }
143146
// CHECK-NEXT: "[[PREFIX]]/end/end.h",
144147
// CHECK-NEXT: "[[PREFIX]]/module.modulemap"
145148
// CHECK-NEXT: ],
149+
// CHECK-NEXT: "link-libraries": [],
146150
// CHECK-NEXT: "name": "Y"
147151
// CHECK-NEXT: }
148152
// CHECK-NEXT: ],

clang/test/ClangScanDeps/header-search-pruning.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
// CHECK_A-NEXT: "context-hash": "{{.*}}",
3434
// CHECK_A-NEXT: "file-deps": [
3535
// CHECK_A: ],
36+
// CHECK_A-NEXT: "link-libraries": [],
3637
// CHECK_A-NEXT: "name": "mod"
3738
// CHECK_A-NEXT: }
3839
// CHECK_A-NEXT: ]
@@ -55,6 +56,7 @@
5556
// CHECK_B-NEXT: "context-hash": "{{.*}}",
5657
// CHECK_B-NEXT: "file-deps": [
5758
// CHECK_B: ],
59+
// CHECK_B-NEXT: "link-libraries": [],
5860
// CHECK_B-NEXT: "name": "mod"
5961
// CHECK_B-NEXT: }
6062
// CHECK_B-NEXT: ]
@@ -79,6 +81,7 @@
7981
// CHECK_AB-NEXT: "context-hash": "{{.*}}",
8082
// CHECK_AB-NEXT: "file-deps": [
8183
// CHECK_AB: ],
84+
// CHECK_AB-NEXT: "link-libraries": [],
8285
// CHECK_AB-NEXT: "name": "mod"
8386
// CHECK_AB-NEXT: }
8487
// CHECK_AB-NEXT: ]
Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
// RUN: rm -rf %t
2+
// RUN: mkdir %t
3+
// RUN: mkdir %t/Inputs
4+
// RUN: cp -R %S/Inputs/frameworks %t/Inputs/frameworks
5+
// RUN: split-file %s %t
6+
7+
//--- module.modulemap
8+
module root { header "root.h" }
9+
module direct { header "direct.h" }
10+
module transitive {
11+
header "transitive.h"
12+
link framework "libTransitive"
13+
}
14+
//--- root.h
15+
#include "direct.h"
16+
#include "root/textual.h"
17+
#include "Framework/Framework.h"
18+
//--- direct.h
19+
#include "transitive.h"
20+
//--- transitive.h
21+
// empty
22+
23+
//--- root/textual.h
24+
// This is here to verify that the "root" directory doesn't clash with name of
25+
// the "root" module.
26+
27+
//--- cdb.json.template
28+
[{
29+
"file": "",
30+
"directory": "DIR",
31+
"command": "clang -fmodules -fmodules-cache-path=DIR/cache -FDIR/Inputs/frameworks -I DIR -x c"
32+
}]
33+
34+
// RUN: sed "s|DIR|%/t|g" %t/cdb.json.template > %t/cdb.json
35+
// RUN: clang-scan-deps -compilation-database %t/cdb.json -format experimental-full -module-name=root > %t/result.json
36+
// RUN: cat %t/result.json | sed 's:\\\\\?:/:g' | FileCheck -DPREFIX=%/t %s
37+
38+
// CHECK: {
39+
// CHECK-NEXT: "modules": [
40+
// CHECK-NEXT: {
41+
// CHECK-NEXT: "clang-module-deps": [],
42+
// CHECK-NEXT: "clang-modulemap-file": "{{.*}}/__inferred_module.map",
43+
// CHECK-NEXT: "command-line": [
44+
// CHECK: ],
45+
// CHECK-NEXT: "context-hash": "{{.*}}",
46+
// CHECK-NEXT: "file-deps": [
47+
// CHECK-NEXT: "{{.*}}/Framework.h"
48+
// CHECK-NEXT: "{{.*}}/__inferred_module.map"
49+
// CHECK-NEXT: "{{.*}}/module.modulemap"
50+
// CHECK-NEXT: ],
51+
// CHECK-NEXT: "link-libraries": [
52+
// CHECK-NEXT: {
53+
// CHECK-NEXT: "isFramework": true,
54+
// CHECK-NEXT: "link-name": "Framework"
55+
// CHECK-NEXT: }
56+
// CHECK-NEXT: ],
57+
// CHECK-NEXT: "name": "Framework"
58+
// CHECK-NEXT: },
59+
// CHECK-NEXT: {
60+
// CHECK-NEXT: "clang-module-deps": [
61+
// CHECK-NEXT: {
62+
// CHECK-NEXT: "context-hash": "{{.*}}",
63+
// CHECK-NEXT: "module-name": "transitive"
64+
// CHECK-NEXT: }
65+
// CHECK-NEXT: ],
66+
// CHECK-NEXT: "clang-modulemap-file": "[[PREFIX]]/module.modulemap",
67+
// CHECK-NEXT: "command-line": [
68+
// CHECK: ],
69+
// CHECK-NEXT: "context-hash": "{{.*}}",
70+
// CHECK-NEXT: "file-deps": [
71+
// CHECK-NEXT: "[[PREFIX]]/direct.h"
72+
// CHECK-NEXT: "[[PREFIX]]/module.modulemap"
73+
// CHECK-NEXT: ],
74+
// CHECK-NEXT: "link-libraries": [],
75+
// CHECK-NEXT: "name": "direct"
76+
// CHECK-NEXT: },
77+
// CHECK-NEXT: {
78+
// CHECK-NEXT: "clang-module-deps": [
79+
// CHECK-NEXT: {
80+
// CHECK-NEXT: "context-hash": "{{.*}}",
81+
// CHECK-NEXT: "module-name": "Framework"
82+
// CHECK-NEXT: },
83+
// CHECK-NEXT: {
84+
// CHECK-NEXT: "context-hash": "{{.*}}",
85+
// CHECK-NEXT: "module-name": "direct"
86+
// CHECK-NEXT: }
87+
// CHECK-NEXT: ],
88+
// CHECK-NEXT: "clang-modulemap-file": "[[PREFIX]]/module.modulemap",
89+
// CHECK-NEXT: "command-line": [
90+
// CHECK: ],
91+
// CHECK-NEXT: "context-hash": "{{.*}}",
92+
// CHECK-NEXT: "file-deps": [
93+
// CHECK-NEXT: "[[PREFIX]]/Inputs/frameworks/module.modulemap"
94+
// CHECK-NEXT: "[[PREFIX]]/module.modulemap"
95+
// CHECK-NEXT: "[[PREFIX]]/root.h"
96+
// CHECK-NEXT: "[[PREFIX]]/root/textual.h"
97+
// CHECK-NEXT: ],
98+
// CHECK-NEXT: "link-libraries": [],
99+
// CHECK-NEXT: "name": "root"
100+
// CHECK-NEXT: },
101+
// CHECK-NEXT: {
102+
// CHECK-NEXT: "clang-module-deps": [],
103+
// CHECK-NEXT: "clang-modulemap-file": "[[PREFIX]]/module.modulemap",
104+
// CHECK-NEXT: "command-line": [
105+
// CHECK: ],
106+
// CHECK-NEXT: "context-hash": "{{.*}}",
107+
// CHECK-NEXT: "file-deps": [
108+
// CHECK-NEXT: "[[PREFIX]]/module.modulemap"
109+
// CHECK-NEXT: "[[PREFIX]]/transitive.h"
110+
// CHECK-NEXT: ],
111+
// CHECK-NEXT: "link-libraries": [
112+
// CHECK-NEXT: {
113+
// CHECK-NEXT: "isFramework": true,
114+
// CHECK-NEXT: "link-name": "libTransitive"
115+
// CHECK-NEXT: }
116+
// CHECK-NEXT: ],
117+
// CHECK-NEXT: "name": "transitive"
118+
// CHECK-NEXT: }
119+
// CHECK-NEXT: ],
120+
// CHECK-NEXT: "translation-units": []
121+
// CHECK-NEXT: }

clang/test/ClangScanDeps/modules-canononical-module-map-case.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,12 @@ framework module FW {
6565
// CHECK-NEXT: "context-hash": "{{.*}}",
6666
// CHECK-NEXT: "file-deps": [
6767
// CHECK: ],
68+
// CHECK-NEXT: "link-libraries": [
69+
// CHECK-NEXT: {
70+
// CHECK-NEXT: "isFramework": true,
71+
// CHECK-NEXT: "link-name": "FW"
72+
// CHECK-NEXT: }
73+
// CHECK-NEXT: ],
6874
// CHECK-NEXT: "name": "FW"
6975
// CHECK-NEXT: }
7076
// CHECK-NEXT: ]

clang/test/ClangScanDeps/modules-context-hash.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
// CHECK-NEXT: "[[PREFIX]]/mod.h",
3939
// CHECK-NEXT: "[[PREFIX]]/module.modulemap"
4040
// CHECK-NEXT: ],
41+
// CHECK-NEXT: "link-libraries": [],
4142
// CHECK-NEXT: "name": "mod"
4243
// CHECK-NEXT: }
4344
// CHECK-NEXT: ],
@@ -75,6 +76,7 @@
7576
// CHECK-NEXT: "[[PREFIX]]/mod.h",
7677
// CHECK-NEXT: "[[PREFIX]]/module.modulemap"
7778
// CHECK-NEXT: ],
79+
// CHECK-NEXT: "link-libraries": [],
7880
// CHECK-NEXT: "name": "mod"
7981
// CHECK-NEXT: }
8082
// CHECK-NEXT: ],

clang/test/ClangScanDeps/modules-dep-args.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ module Direct { header "direct.h" }
6161
// CHECK-NEXT: "[[PREFIX]]/direct.h",
6262
// CHECK-NEXT: "[[PREFIX]]/module.modulemap"
6363
// CHECK-NEXT: ],
64+
// CHECK-NEXT: "link-libraries": [],
6465
// CHECK-NEXT: "name": "Direct"
6566
// CHECK-NEXT: },
6667
// CHECK-NEXT: {
@@ -73,6 +74,7 @@ module Direct { header "direct.h" }
7374
// CHECK-NEXT: "[[PREFIX]]/module.modulemap",
7475
// CHECK-NEXT: "[[PREFIX]]/transitive.h"
7576
// CHECK-NEXT: ],
77+
// CHECK-NEXT: "link-libraries": [],
7678
// CHECK-NEXT: "name": "Transitive"
7779
// CHECK-NEXT: }
7880
// CHECK-NEXT: ],

clang/test/ClangScanDeps/modules-excluded-header.m

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
// CHECK-NEXT: "context-hash": "{{.*}}",
4343
// CHECK-NEXT: "file-deps": [
4444
// CHECK: ],
45+
// CHECK-NEXT: "link-libraries": [],
4546
// CHECK-NEXT: "name": "Mod"
4647
// CHECK-NEXT: }
4748
// CHECK-NEXT: ]

clang/test/ClangScanDeps/modules-extern-submodule.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ module third {}
5454
// CHECK-NEXT: "[[PREFIX]]/second/second/module.modulemap",
5555
// CHECK-NEXT: "[[PREFIX]]/second/second/sub.modulemap"
5656
// CHECK-NEXT: ],
57+
// CHECK-NEXT: "link-libraries": [],
5758
// CHECK-NEXT: "name": "first"
5859
// CHECK-NEXT: },
5960
// CHECK-NEXT: {
@@ -76,6 +77,7 @@ module third {}
7677
// CHECK-NEXT: "[[PREFIX]]/second/second/sub.modulemap",
7778
// CHECK-NEXT: "[[PREFIX]]/third/module.modulemap"
7879
// CHECK-NEXT: ],
80+
// CHECK-NEXT: "link-libraries": [],
7981
// CHECK-NEXT: "name": "second"
8082
// CHECK-NEXT: },
8183
// CHECK-NEXT: {
@@ -90,6 +92,7 @@ module third {}
9092
// CHECK-NEXT: "file-deps": [
9193
// CHECK-NEXT: "[[PREFIX]]/third/module.modulemap"
9294
// CHECK-NEXT: ],
95+
// CHECK-NEXT: "link-libraries": [],
9396
// CHECK-NEXT: "name": "third"
9497
// CHECK-NEXT: }
9598
// CHECK-NEXT: ],

clang/test/ClangScanDeps/modules-extern-unrelated.m

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
// CHECK-NEXT: "file-deps": [
4141
// CHECK-NEXT: "[[PREFIX]]/first/module.modulemap"
4242
// CHECK-NEXT: ],
43+
// CHECK-NEXT: "link-libraries": [],
4344
// CHECK-NEXT: "name": "first"
4445
// CHECK-NEXT: },
4546
// CHECK-NEXT: {
@@ -52,6 +53,7 @@
5253
// CHECK-NEXT: "[[PREFIX]]/first/first_other.h",
5354
// CHECK-NEXT: "[[PREFIX]]/first/module.modulemap"
5455
// CHECK-NEXT: ],
56+
// CHECK-NEXT: "link-libraries": [],
5557
// CHECK-NEXT: "name": "first_other"
5658
// CHECK-NEXT: },
5759
// CHECK-NEXT: {
@@ -71,6 +73,7 @@
7173
// CHECK-NEXT: "[[PREFIX]]/second/second.h",
7274
// CHECK-NEXT: "[[PREFIX]]/second/second.modulemap"
7375
// CHECK-NEXT: ],
76+
// CHECK-NEXT: "link-libraries": [],
7477
// CHECK-NEXT: "name": "second"
7578
// CHECK-NEXT: },
7679
// CHECK-NEXT: {
@@ -95,6 +98,7 @@
9598
// CHECK-NEXT: "[[PREFIX]]/zeroth/module.modulemap",
9699
// CHECK-NEXT: "[[PREFIX]]/zeroth/zeroth.h"
97100
// CHECK-NEXT: ],
101+
// CHECK-NEXT: "link-libraries": [],
98102
// CHECK-NEXT: "name": "zeroth"
99103
// CHECK-NEXT: }
100104
// CHECK-NEXT: ],

clang/test/ClangScanDeps/modules-file-path-isolation.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
// CHECK-NEXT: "{{.*}}A.h",
2121
// CHECK-NEXT: "{{.*}}module.modulemap"
2222
// CHECK-NEXT: ],
23+
// CHECK-NEXT: "link-libraries": [],
2324
// CHECK-NEXT: "name": "A"
2425
// CHECK-NEXT: }
2526

clang/test/ClangScanDeps/modules-fmodule-name-no-module-built.m

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
// CHECK-NEXT: "[[PREFIX]]/Inputs/header2.h",
2929
// CHECK-NEXT: "[[PREFIX]]/Inputs/module.modulemap"
3030
// CHECK-NEXT: ],
31+
// CHECK-NEXT: "link-libraries": [],
3132
// CHECK-NEXT: "name": "header2"
3233
// CHECK-NEXT: }
3334
// CHECK-NEXT: ],

clang/test/ClangScanDeps/modules-full-by-mod-name.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ module transitive { header "transitive.h" }
4545
// CHECK-NEXT: "[[PREFIX]]/direct.h"
4646
// CHECK-NEXT: "[[PREFIX]]/module.modulemap"
4747
// CHECK-NEXT: ],
48+
// CHECK-NEXT: "link-libraries": [],
4849
// CHECK-NEXT: "name": "direct"
4950
// CHECK-NEXT: },
5051
// CHECK-NEXT: {
@@ -63,6 +64,7 @@ module transitive { header "transitive.h" }
6364
// CHECK-NEXT: "[[PREFIX]]/root.h"
6465
// CHECK-NEXT: "[[PREFIX]]/root/textual.h"
6566
// CHECK-NEXT: ],
67+
// CHECK-NEXT: "link-libraries": [],
6668
// CHECK-NEXT: "name": "root"
6769
// CHECK-NEXT: },
6870
// CHECK-NEXT: {
@@ -75,6 +77,7 @@ module transitive { header "transitive.h" }
7577
// CHECK-NEXT: "[[PREFIX]]/module.modulemap"
7678
// CHECK-NEXT: "[[PREFIX]]/transitive.h"
7779
// CHECK-NEXT: ],
80+
// CHECK-NEXT: "link-libraries": [],
7881
// CHECK-NEXT: "name": "transitive"
7982
// CHECK-NEXT: }
8083
// CHECK-NEXT: ],

clang/test/ClangScanDeps/modules-full.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@
4444
// CHECK-NEXT: "[[PREFIX]]/Inputs/header.h",
4545
// CHECK-NEXT: "[[PREFIX]]/Inputs/module.modulemap"
4646
// CHECK-NEXT: ],
47+
// CHECK-NEXT: "link-libraries": [],
4748
// CHECK-NEXT: "name": "header1"
4849
// CHECK-NEXT: },
4950
// CHECK-NEXT: {
@@ -62,6 +63,7 @@
6263
// CHECK-NEXT: "[[PREFIX]]/Inputs/header.h",
6364
// CHECK-NEXT: "[[PREFIX]]/Inputs/module.modulemap"
6465
// CHECK-NEXT: ],
66+
// CHECK-NEXT: "link-libraries": [],
6567
// CHECK-NEXT: "name": "header1"
6668
// CHECK-NEXT: },
6769
// CHECK-NEXT: {
@@ -80,6 +82,7 @@
8082
// CHECK-NEXT: "[[PREFIX]]/Inputs/header2.h",
8183
// CHECK-NEXT: "[[PREFIX]]/Inputs/module.modulemap"
8284
// CHECK-NEXT: ],
85+
// CHECK-NEXT: "link-libraries": [],
8386
// CHECK-NEXT: "name": "header2"
8487
// CHECK-NEXT: }
8588
// CHECK-NEXT: ],

0 commit comments

Comments
 (0)