xref: /llvm-project/clang/test/ClangScanDeps/P1689.cppm (revision c0c8679f047e78fbf5d6baa3e9640a3d7e155620)
1// UNSUPPORTED: target={{.*}}-aix{{.*}}
2//
3// The slash direction in linux and windows are different.
4// UNSUPPORTED: system-windows
5//
6// RUN: rm -fr %t
7// RUN: mkdir -p %t
8// RUN: split-file %s %t
9//
10// RUN: sed "s|DIR|%/t|g" %t/P1689.json.in > %t/P1689.json
11// RUN: clang-scan-deps -compilation-database %t/P1689.json -format=p1689 | FileCheck %t/Checks.cpp -DPREFIX=%/t
12// RUN: clang-scan-deps --mode=preprocess-dependency-directives -compilation-database %t/P1689.json -format=p1689 | FileCheck %t/Checks.cpp -DPREFIX=%/t
13//
14// Check the separated dependency format. This is required by CMake for the case
15// that we have non-exist files in a fresh build and potentially out-of-date after that.
16// So the build system need to wrtie a compilation database just for scanning purposes,
17// which is not so good. So here is the per file mode for P1689.
18// RUN: clang-scan-deps -format=p1689 \
19// RUN:   -- %clang++ -std=c++20 -c -fprebuilt-module-path=%t %t/M.cppm -o %t/M.o \
20// RUN:   | FileCheck %t/M.cppm -DPREFIX=%/t
21// RUN: clang-scan-deps -format=p1689 \
22// RUN:   -- %clang++ -std=c++20 -c -fprebuilt-module-path=%t %t/Impl.cpp -o %t/Impl.o \
23// RUN:   | FileCheck %t/Impl.cpp -DPREFIX=%/t
24// RUN: clang-scan-deps -format=p1689 \
25// RUN:   -- %clang++ -std=c++20 -c -fprebuilt-module-path=%t %t/impl_part.cppm -o %t/impl_part.o \
26// RUN:   | FileCheck %t/impl_part.cppm -DPREFIX=%/t
27// RUN: clang-scan-deps -format=p1689 \
28// RUN:   -- %clang++ -std=c++20 -c -fprebuilt-module-path=%t %t/interface_part.cppm -o %t/interface_part.o \
29// RUN:   | FileCheck %t/interface_part.cppm -DPREFIX=%/t
30// RUN: clang-scan-deps -format=p1689 \
31// RUN:   -- %clang++ -std=c++20 -c -fprebuilt-module-path=%t %t/User.cpp -o %t/User.o \
32// RUN:   | FileCheck %t/User.cpp -DPREFIX=%/t
33//
34// Check we can generate the make-style dependencies as expected.
35// RUN: clang-scan-deps -format=p1689 \
36// RUN:   -- %clang++ -std=c++20 -c -fprebuilt-module-path=%t %t/impl_part.cppm -o %t/impl_part.o \
37// RUN:      -MT %t/impl_part.o.ddi -MD -MF %t/impl_part.dep
38// RUN:   cat %t/impl_part.dep | FileCheck %t/impl_part.cppm -DPREFIX=%/t --check-prefix=CHECK-MAKE
39//
40// Check that we can generate multiple make-style dependency information with compilation database.
41// RUN: cat %t/P1689.dep | FileCheck %t/Checks.cpp -DPREFIX=%/t --check-prefix=CHECK-MAKE
42//
43// Check that we can mix the use of -format=p1689 and -fmodules.
44// RUN: clang-scan-deps -format=p1689 \
45// RUN:   -- %clang++ -std=c++20 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/cache -c %t/impl_part.cppm -o %t/impl_part.o \
46// RUN:   | FileCheck %t/impl_part.cppm -DPREFIX=%/t
47//
48// Check the path in the make style dependencies are generated in relative path form
49// RUN: cd %t
50// RUN: clang-scan-deps -format=p1689 \
51// RUN:   -- %clang++ -std=c++20 -c -fprebuilt-module-path=%t impl_part.cppm -o impl_part.o \
52// RUN:      -MT impl_part.o.ddi -MD -MF impl_part.dep
53// RUN:   cat impl_part.dep | FileCheck impl_part.cppm -DPREFIX=%/t --check-prefix=CHECK-MAKE-RELATIVE
54
55
56//--- P1689.json.in
57[
58{
59  "directory": "DIR",
60  "command": "clang++ -std=c++20 DIR/M.cppm -c -o DIR/M.o -MT DIR/M.o.ddi -MD -MF DIR/P1689.dep",
61  "file": "DIR/M.cppm",
62  "output": "DIR/M.o"
63},
64{
65  "directory": "DIR",
66  "command": "clang++ -std=c++20 DIR/Impl.cpp -c -o DIR/Impl.o -MT DIR/Impl.o.ddi -MD -MF DIR/P1689.dep",
67  "file": "DIR/Impl.cpp",
68  "output": "DIR/Impl.o"
69},
70{
71  "directory": "DIR",
72  "command": "clang++ -std=c++20 DIR/impl_part.cppm -c -o DIR/impl_part.o -MT DIR/impl_part.o.ddi -MD -MF DIR/P1689.dep",
73  "file": "DIR/impl_part.cppm",
74  "output": "DIR/impl_part.o"
75},
76{
77  "directory": "DIR",
78  "command": "clang++ -std=c++20 DIR/interface_part.cppm -c -o DIR/interface_part.o -MT DIR/interface_part.o.ddi -MD -MF DIR/P1689.dep",
79  "file": "DIR/interface_part.cppm",
80  "output": "DIR/interface_part.o"
81},
82{
83  "directory": "DIR",
84  "command": "clang++ -std=c++20 DIR/User.cpp -c -o DIR/User.o -MT DIR/User.o.ddi -MD -MF DIR/P1689.dep",
85  "file": "DIR/User.cpp",
86  "output": "DIR/User.o"
87}
88]
89
90//--- M.cppm
91export module M;
92export import :interface_part;
93import :impl_part;
94export void Hello();
95
96// CHECK: {
97// CHECK-NEXT:   "revision": 0,
98// CHECK-NEXT:   "rules": [
99// CHECK-NEXT:     {
100// CHECK-NEXT:       "primary-output": "[[PREFIX]]/M.o",
101// CHECK-NEXT:       "provides": [
102// CHECK-NEXT:         {
103// CHECK-NEXT:           "is-interface": true,
104// CHECK-NEXT:           "logical-name": "M",
105// CHECK-NEXT:           "source-path": "[[PREFIX]]/M.cppm"
106// CHECK-NEXT:         }
107// CHECK-NEXT:       ],
108// CHECK-NEXT:       "requires": [
109// CHECK-NEXT:         {
110// CHECK-NEXT:           "logical-name": "M:interface_part"
111// CHECK-NEXT:         },
112// CHECK-NEXT:         {
113// CHECK-NEXT:           "logical-name": "M:impl_part"
114// CHECK-NEXT:         }
115// CHECK-NEXT:       ]
116// CHECK-NEXT:     }
117// CHECK-NEXT:   ],
118// CHECK-NEXT:   "version": 1
119// CHECK-NEXT: }
120
121//--- Impl.cpp
122module;
123#include "header.mock"
124module M;
125void Hello() {
126    std::cout << "Hello ";
127}
128
129// CHECK: {
130// CHECK-NEXT:   "revision": 0,
131// CHECK-NEXT:   "rules": [
132// CHECK-NEXT:     {
133// CHECK-NEXT:       "primary-output": "[[PREFIX]]/Impl.o",
134// CHECK-NEXT:       "requires": [
135// CHECK-NEXT:         {
136// CHECK-NEXT:           "logical-name": "M"
137// CHECK-NEXT:         }
138// CHECK-NEXT:       ]
139// CHECK-NEXT:     }
140// CHECK-NEXT:   ],
141// CHECK-NEXT:   "version": 1
142// CHECK-NEXT: }
143
144//--- impl_part.cppm
145module;
146#include "header.mock"
147module M:impl_part;
148import :interface_part;
149
150std::string W = "World.";
151void World() {
152    std::cout << W << std::endl;
153}
154
155// CHECK: {
156// CHECK-NEXT:   "revision": 0,
157// CHECK-NEXT:   "rules": [
158// CHECK-NEXT:     {
159// CHECK-NEXT:       "primary-output": "[[PREFIX]]/impl_part.o",
160// CHECK-NEXT:       "provides": [
161// CHECK-NEXT:         {
162// CHECK-NEXT:           "is-interface": false,
163// CHECK-NEXT:           "logical-name": "M:impl_part",
164// CHECK-NEXT:           "source-path": "[[PREFIX]]/impl_part.cppm"
165// CHECK-NEXT:         }
166// CHECK-NEXT:       ],
167// CHECK-NEXT:       "requires": [
168// CHECK-NEXT:         {
169// CHECK-NEXT:           "logical-name": "M:interface_part"
170// CHECK-NEXT:         }
171// CHECK-NEXT:       ]
172// CHECK-NEXT:     }
173// CHECK-NEXT:   ],
174// CHECK-NEXT:   "version": 1
175// CHECK-NEXT: }
176
177// CHECK-MAKE: [[PREFIX]]/impl_part.o.ddi:
178// CHECK-MAKE:   [[PREFIX]]/impl_part.cppm
179// CHECK-MAKE:   [[PREFIX]]/header.mock
180
181// CHECK-MAKE-RELATIVE: impl_part.o.ddi: impl_part.cppm header.mock
182
183//--- interface_part.cppm
184export module M:interface_part;
185export void World();
186
187// CHECK: {
188// CHECK-NEXT:   "revision": 0,
189// CHECK-NEXT:   "rules": [
190// CHECK-NEXT:     {
191// CHECK-NEXT:       "primary-output": "[[PREFIX]]/interface_part.o",
192// CHECK-NEXT:       "provides": [
193// CHECK-NEXT:         {
194// CHECK-NEXT:           "is-interface": true,
195// CHECK-NEXT:           "logical-name": "M:interface_part",
196// CHECK-NEXT:           "source-path": "[[PREFIX]]/interface_part.cppm"
197// CHECK-NEXT:         }
198// CHECK-NEXT:       ]
199// CHECK-NEXT:     }
200// CHECK-NEXT:   ],
201// CHECK-NEXT:   "version": 1
202// CHECK-NEXT: }
203
204//--- User.cpp
205import M;
206import third_party_module;
207int main() {
208    Hello();
209    World();
210    return 0;
211}
212
213// CHECK: {
214// CHECK-NEXT:   "revision": 0,
215// CHECK-NEXT:   "rules": [
216// CHECK-NEXT:     {
217// CHECK-NEXT:       "primary-output": "[[PREFIX]]/User.o",
218// CHECK-NEXT:       "requires": [
219// CHECK-NEXT:         {
220// CHECK-NEXT:           "logical-name": "M"
221// CHECK-NEXT:         },
222// CHECK-NEXT:         {
223// CHECK-NEXT:           "logical-name": "third_party_module"
224// CHECK-NEXT:         }
225// CHECK-NEXT:       ]
226// CHECK-NEXT:     }
227// CHECK-NEXT:   ],
228// CHECK-NEXT:   "version": 1
229// CHECK-NEXT: }
230
231//--- Checks.cpp
232// CHECK: {
233// CHECK-NEXT:   "revision": 0,
234// CHECK-NEXT:   "rules": [
235// CHECK-NEXT:     {
236// CHECK-NEXT:       "primary-output": "[[PREFIX]]/Impl.o",
237// CHECK-NEXT:       "requires": [
238// CHECK-NEXT:         {
239// CHECK-NEXT:           "logical-name": "M",
240// CHECK-NEXT:           "source-path": "[[PREFIX]]/M.cppm"
241// CHECK-NEXT:         }
242// CHECK-NEXT:       ]
243// CHECK-NEXT:     },
244// CHECK-NEXT:     {
245// CHECK-NEXT:       "primary-output": "[[PREFIX]]/M.o",
246// CHECK-NEXT:       "provides": [
247// CHECK-NEXT:         {
248// CHECK-NEXT:           "is-interface": true,
249// CHECK-NEXT:           "logical-name": "M",
250// CHECK-NEXT:           "source-path": "[[PREFIX]]/M.cppm"
251// CHECK-NEXT:         }
252// CHECK-NEXT:       ],
253// CHECK-NEXT:       "requires": [
254// CHECK-NEXT:         {
255// CHECK-NEXT:           "logical-name": "M:interface_part",
256// CHECK-NEXT:           "source-path": "[[PREFIX]]/interface_part.cppm"
257// CHECK-NEXT:         },
258// CHECK-NEXT:         {
259// CHECK-NEXT:           "logical-name": "M:impl_part",
260// CHECK-NEXT:           "source-path": "[[PREFIX]]/impl_part.cppm"
261// CHECK-NEXT:         }
262// CHECK-NEXT:       ]
263// CHECK-NEXT:     },
264// CHECK-NEXT:     {
265// CHECK-NEXT:       "primary-output": "[[PREFIX]]/User.o",
266// CHECK-NEXT:       "requires": [
267// CHECK-NEXT:         {
268// CHECK-NEXT:           "logical-name": "M",
269// CHECK-NEXT:           "source-path": "[[PREFIX]]/M.cppm"
270// CHECK-NEXT:         },
271// CHECK-NEXT:         {
272// CHECK-NEXT:           "logical-name": "third_party_module"
273// CHECK-NEXT:         }
274// CHECK-NEXT:       ]
275// CHECK-NEXT:     },
276// CHECK-NEXT:     {
277// CHECK-NEXT:       "primary-output": "[[PREFIX]]/impl_part.o",
278// CHECK-NEXT:       "provides": [
279// CHECK-NEXT:         {
280// CHECK-NEXT:           "is-interface": false,
281// CHECK-NEXT:           "logical-name": "M:impl_part",
282// CHECK-NEXT:           "source-path": "[[PREFIX]]/impl_part.cppm"
283// CHECK-NEXT:         }
284// CHECK-NEXT:       ],
285// CHECK-NEXT:       "requires": [
286// CHECK-NEXT:         {
287// CHECK-NEXT:           "logical-name": "M:interface_part",
288// CHECK-NEXT:           "source-path": "[[PREFIX]]/interface_part.cppm"
289// CHECK-NEXT:         }
290// CHECK-NEXT:       ]
291// CHECK-NEXT:     },
292// CHECK-NEXT:     {
293// CHECK-NEXT:       "primary-output": "[[PREFIX]]/interface_part.o",
294// CHECK-NEXT:       "provides": [
295// CHECK-NEXT:         {
296// CHECK-NEXT:           "is-interface": true,
297// CHECK-NEXT:           "logical-name": "M:interface_part",
298// CHECK-NEXT:           "source-path": "[[PREFIX]]/interface_part.cppm"
299// CHECK-NEXT:         }
300// CHECK-NEXT:       ]
301// CHECK-NEXT:     }
302// CHECK-NEXT:   ],
303// CHECK-NEXT:   "version": 1
304// CHECK-NEXT: }
305
306// CHECK-MAKE-DAG: [[PREFIX]]/impl_part.o.ddi: \
307// CHECK-MAKE-DAG-NEXT:   [[PREFIX]]/impl_part.cppm \
308// CHECK-MAKE-DAG-NEXT:   [[PREFIX]]/header.mock
309// CHECK-MAKE-DAG: [[PREFIX]]/interface_part.o.ddi: \
310// CHECK-MAKE-DAG-NEXT:   [[PREFIX]]/interface_part.cppm
311// CHECK-MAKE-DAG: [[PREFIX]]/M.o.ddi: \
312// CHECK-MAKE-DAG-NEXT:   [[PREFIX]]/M.cppm
313// CHECK-MAKE-DAG: [[PREFIX]]/User.o.ddi: \
314// CHECK-MAKE-DAG-NEXT:   [[PREFIX]]/User.cpp
315// CHECK-MAKE-DAG: [[PREFIX]]/Impl.o.ddi: \
316// CHECK-MAKE-DAG-NEXT:   [[PREFIX]]/Impl.cpp \
317// CHECK-MAKE-DAG-NEXT:   [[PREFIX]]/header.mock
318
319//--- module.modulemap
320module Mock { header "header.mock" }
321
322//--- header.mock
323