@@ -91,6 +91,8 @@ def parseScript(test, preamble):
91
91
# Parse the test file, including custom directives
92
92
additionalCompileFlags = []
93
93
fileDependencies = []
94
+ modules = [] # The enabled modules
95
+ moduleCompileFlags = [] # The compilation flags to use modules
94
96
parsers = [
95
97
lit .TestRunner .IntegratedTestKeywordParser (
96
98
"FILE_DEPENDENCIES:" ,
@@ -102,6 +104,11 @@ def parseScript(test, preamble):
102
104
lit .TestRunner .ParserKind .SPACE_LIST ,
103
105
initial_value = additionalCompileFlags ,
104
106
),
107
+ lit .TestRunner .IntegratedTestKeywordParser (
108
+ "MODULES:" ,
109
+ lit .TestRunner .ParserKind .SPACE_LIST ,
110
+ initial_value = modules ,
111
+ ),
105
112
]
106
113
107
114
# Add conditional parsers for ADDITIONAL_COMPILE_FLAGS. This should be replaced by first
@@ -131,13 +138,62 @@ def parseScript(test, preamble):
131
138
script += preamble
132
139
script += scriptInTest
133
140
141
+ has_std_module = False
142
+ has_std_compat_module = False
143
+ for module in modules :
144
+ if module == "std" :
145
+ has_std_module = True
146
+ elif module == "std.compat" :
147
+ has_std_compat_module = True
148
+ else :
149
+ script .insert (0 , f"echo \" The module '{ module } ' is not valid, use 'std' or 'std.compat'\" " )
150
+ script .insert (1 , "false" );
151
+ return script
152
+
153
+ if modules :
154
+ # This flag is needed for both modules.
155
+ moduleCompileFlags .append ("-fprebuilt-module-path=%T" )
156
+
157
+ # Building the modules needs to happen before the other script commands
158
+ # are executed. Therefore the commands are added to the front of the
159
+ # list.
160
+ if has_std_compat_module :
161
+ script .insert (
162
+ 0 ,
163
+ "%dbg(MODULE std.compat) %{cxx} %{flags} %{compile_flags} "
164
+ "-Wno-reserved-module-identifier -Wno-reserved-user-defined-literal "
165
+ "--precompile -o %T/std.compat.pcm -c %{module}/std.compat.cppm" ,
166
+ )
167
+ moduleCompileFlags .append ("%T/std.compat.pcm" )
168
+
169
+ # Make sure the std module is added before std.compat.
170
+ # Libc++'s std.compat module will depend on its std module.
171
+ # It is not known whether the compiler expects the modules in the order
172
+ # of their dependencies. However it's trivial to provide them in that
173
+ # order.
174
+ if has_std_module :
175
+ script .insert (
176
+ 0 ,
177
+ "%dbg(MODULE std) %{cxx} %{flags} %{compile_flags} "
178
+ "-Wno-reserved-module-identifier -Wno-reserved-user-defined-literal "
179
+ "--precompile -o %T/std.pcm -c %{module}/std.cppm" ,
180
+ )
181
+ moduleCompileFlags .append ("%T/std.pcm" )
182
+
134
183
# Add compile flags specified with ADDITIONAL_COMPILE_FLAGS.
135
184
substitutions = [
136
185
(s , x + " " + " " .join (additionalCompileFlags ))
137
186
if s == "%{compile_flags}"
138
187
else (s , x )
139
188
for (s , x ) in substitutions
140
189
]
190
+ # In order to use modules additional compilation flags are required.
191
+ # Adding these to the %{compile_flags} gives a chicken and egg issue:
192
+ # - the modules need to be build with the same compilation flags as the
193
+ # tests,
194
+ # - except for the module dependency, which does not exist.
195
+ # The issue is resolved by adding a private substitution.
196
+ substitutions .append (("%{module_flags}" , " " .join (moduleCompileFlags )))
141
197
142
198
# Perform substitutions in the script itself.
143
199
script = lit .TestRunner .applySubstitutions (
@@ -191,6 +247,7 @@ class CxxStandardLibraryTest(lit.formats.FileBasedTest):
191
247
constructs:
192
248
%{cxx} - A command that can be used to invoke the compiler
193
249
%{compile_flags} - Flags to use when compiling a test case
250
+ %{module_flags} - Flags to use when compiling a test case that imports modules
194
251
%{link_flags} - Flags to use when linking a test case
195
252
%{flags} - Flags to use either when compiling or linking a test case
196
253
%{exec} - A command to prefix the execution of executables
@@ -223,6 +280,12 @@ class CxxStandardLibraryTest(lit.formats.FileBasedTest):
223
280
allows adding special compilation flags without having to use a
224
281
.sh.cpp test, which would be more powerful but perhaps overkill.
225
282
283
+ // MODULE: std std.compat
284
+
285
+ This directive will build the required C++23 standard library
286
+ modules and add the provide the additional compiler flags in
287
+ %{module_flags}. (Libc++ offers these modules in C++20 as an
288
+ extenstion.)
226
289
227
290
Additional provided substitutions and features
228
291
==============================================
@@ -288,22 +351,22 @@ def execute(self, test, litConfig):
288
351
".compile.pass.mm"
289
352
):
290
353
steps = [
291
- "%dbg(COMPILED WITH) %{cxx} %s %{flags} %{compile_flags} -fsyntax-only"
354
+ "%dbg(COMPILED WITH) %{cxx} %s %{flags} %{compile_flags} %{module_flags} -fsyntax-only"
292
355
]
293
356
return self ._executeShTest (test , litConfig , steps )
294
357
elif filename .endswith (".compile.fail.cpp" ):
295
358
steps = [
296
- "%dbg(COMPILED WITH) ! %{cxx} %s %{flags} %{compile_flags} -fsyntax-only"
359
+ "%dbg(COMPILED WITH) ! %{cxx} %s %{flags} %{compile_flags} %{module_flags} -fsyntax-only"
297
360
]
298
361
return self ._executeShTest (test , litConfig , steps )
299
362
elif filename .endswith (".link.pass.cpp" ) or filename .endswith (".link.pass.mm" ):
300
363
steps = [
301
- "%dbg(COMPILED WITH) %{cxx} %s %{flags} %{compile_flags} %{link_flags} -o %t.exe"
364
+ "%dbg(COMPILED WITH) %{cxx} %s %{flags} %{compile_flags} %{module_flags} %{ link_flags} -o %t.exe"
302
365
]
303
366
return self ._executeShTest (test , litConfig , steps )
304
367
elif filename .endswith (".link.fail.cpp" ):
305
368
steps = [
306
- "%dbg(COMPILED WITH) %{cxx} %s %{flags} %{compile_flags} -c -o %t.o" ,
369
+ "%dbg(COMPILED WITH) %{cxx} %s %{flags} %{compile_flags} %{module_flags} -c -o %t.o" ,
307
370
"%dbg(LINKED WITH) ! %{cxx} %t.o %{flags} %{link_flags} -o %t.exe" ,
308
371
]
309
372
return self ._executeShTest (test , litConfig , steps )
@@ -321,7 +384,7 @@ def execute(self, test, litConfig):
321
384
# suffixes above too.
322
385
elif filename .endswith (".pass.cpp" ) or filename .endswith (".pass.mm" ):
323
386
steps = [
324
- "%dbg(COMPILED WITH) %{cxx} %s %{flags} %{compile_flags} %{link_flags} -o %t.exe" ,
387
+ "%dbg(COMPILED WITH) %{cxx} %s %{flags} %{compile_flags} %{module_flags} %{ link_flags} -o %t.exe" ,
325
388
"%dbg(EXECUTED AS) %{exec} %t.exe" ,
326
389
]
327
390
return self ._executeShTest (test , litConfig , steps )
0 commit comments