@@ -52,6 +52,21 @@ def _executeScriptInternal(test, litConfig, commands):
52
52
return (out , err , exitCode , timeoutInfo , parsedCommands )
53
53
54
54
55
+ def _validateModuleDependencies (modules ):
56
+ for m in modules :
57
+ if m not in ("std" , "std.compat" ):
58
+ raise RuntimeError (
59
+ f"Invalid module dependency '{ m } ', only 'std' and 'std.compat' are valid"
60
+ )
61
+
62
+
63
+ def _getSubstitution (substitution , config ):
64
+ for (orig , replacement ) in config .substitutions :
65
+ if orig == substitution :
66
+ return replacement
67
+ raise ValueError ("Substitution {} is not in the config." .format (substitution ))
68
+
69
+
55
70
def parseScript (test , preamble ):
56
71
"""
57
72
Extract the script from a test, with substitutions applied.
@@ -105,7 +120,7 @@ def parseScript(test, preamble):
105
120
initial_value = additionalCompileFlags ,
106
121
),
107
122
lit .TestRunner .IntegratedTestKeywordParser (
108
- "MODULES :" ,
123
+ "MODULE_DEPENDENCIES :" ,
109
124
lit .TestRunner .ParserKind .SPACE_LIST ,
110
125
initial_value = modules ,
111
126
),
@@ -138,65 +153,62 @@ def parseScript(test, preamble):
138
153
script += preamble
139
154
script += scriptInTest
140
155
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 (
150
- 0 ,
151
- f"echo \" The module '{ module } ' is not valid, use 'std' or 'std.compat'\" " ,
152
- )
153
- script .insert (1 , "false" )
154
- return script
156
+ # Add compile flags specified with ADDITIONAL_COMPILE_FLAGS.
157
+ # Modules need to be build with the same compilation flags as the
158
+ # test. So add these flags before adding the modules.
159
+ substitutions = [
160
+ (s , x + " " + " " .join (additionalCompileFlags ))
161
+ if s == "%{compile_flags}"
162
+ else (s , x )
163
+ for (s , x ) in substitutions
164
+ ]
155
165
156
166
if modules :
167
+ _validateModuleDependencies (modules )
168
+
157
169
# This flag is needed for both modules.
158
170
moduleCompileFlags .append ("-fprebuilt-module-path=%T" )
159
171
160
- # Building the modules needs to happen before the other script commands
161
- # are executed. Therefore the commands are added to the front of the
162
- # list.
163
- if has_std_compat_module :
172
+ # The moduleCompileFlags are added to the %{compile_flags}, but
173
+ # the modules need should be built without these flags. So
174
+ # expand the compile_flags and add the expanded value to the
175
+ # build script.
176
+ compileFlags = _getSubstitution ("%{compile_flags}" , test .config )
177
+
178
+ # Building the modules needs to happen before the other script
179
+ # commands are executed. Therefore the commands are added to the
180
+ # front of the list.
181
+ if "std.compat" in modules :
164
182
script .insert (
165
183
0 ,
166
- "%dbg(MODULE std.compat) %{cxx} %{flags} %{compile_flags} "
184
+ "%dbg(MODULE std.compat) %{cxx} %{flags} "
185
+ f"{ compileFlags } "
167
186
"-Wno-reserved-module-identifier -Wno-reserved-user-defined-literal "
168
187
"--precompile -o %T/std.compat.pcm -c %{module}/std.compat.cppm" ,
169
188
)
170
189
moduleCompileFlags .append ("%T/std.compat.pcm" )
171
190
172
- # Make sure the std module is added before std.compat.
173
- # Libc++'s std.compat module will depend on its std module.
174
- # It is not known whether the compiler expects the modules in the order
175
- # of their dependencies. However it's trivial to provide them in that
176
- # order.
177
- if has_std_module :
178
- script .insert (
179
- 0 ,
180
- "%dbg(MODULE std) %{cxx} %{flags} %{compile_flags} "
181
- "-Wno-reserved-module-identifier -Wno-reserved-user-defined-literal "
182
- "--precompile -o %T/std.pcm -c %{module}/std.cppm" ,
183
- )
184
- moduleCompileFlags .append ("%T/std.pcm" )
185
-
186
- # Add compile flags specified with ADDITIONAL_COMPILE_FLAGS.
187
- substitutions = [
188
- (s , x + " " + " " .join (additionalCompileFlags ))
189
- if s == "%{compile_flags}"
190
- else (s , x )
191
- for (s , x ) in substitutions
192
- ]
193
- # In order to use modules, additional compilation flags are required.
194
- # Adding these to the %{compile_flags} gives a chicken and egg issue:
195
- # - the modules need to be built with the same compilation flags as the
196
- # tests,
197
- # - except for the module dependency, which does not exist.
198
- # The issue is resolved by adding a private substitution.
199
- substitutions .append (("%{module_flags}" , " " .join (moduleCompileFlags )))
191
+ # Make sure the std module is added before std.compat. Libc++'s
192
+ # std.compat module will depend on its std module. It is not
193
+ # known whether the compiler expects the modules in the order of
194
+ # their dependencies. However it's trivial to provide them in
195
+ # that order.
196
+ script .insert (
197
+ 0 ,
198
+ "%dbg(MODULE std) %{cxx} %{flags} "
199
+ f"{ compileFlags } "
200
+ "-Wno-reserved-module-identifier -Wno-reserved-user-defined-literal "
201
+ "--precompile -o %T/std.pcm -c %{module}/std.cppm" ,
202
+ )
203
+ moduleCompileFlags .append ("%T/std.pcm" )
204
+
205
+ # Add compile flags required for the modules.
206
+ substitutions = [
207
+ (s , x + " " + " " .join (moduleCompileFlags ))
208
+ if s == "%{compile_flags}"
209
+ else (s , x )
210
+ for (s , x ) in substitutions
211
+ ]
200
212
201
213
# Perform substitutions in the script itself.
202
214
script = lit .TestRunner .applySubstitutions (
@@ -250,7 +262,6 @@ class CxxStandardLibraryTest(lit.formats.FileBasedTest):
250
262
constructs:
251
263
%{cxx} - A command that can be used to invoke the compiler
252
264
%{compile_flags} - Flags to use when compiling a test case
253
- %{module_flags} - Flags to use when compiling a test case that imports modules
254
265
%{link_flags} - Flags to use when linking a test case
255
266
%{flags} - Flags to use either when compiling or linking a test case
256
267
%{exec} - A command to prefix the execution of executables
@@ -287,7 +298,7 @@ class CxxStandardLibraryTest(lit.formats.FileBasedTest):
287
298
288
299
This directive will build the required C++23 standard library
289
300
modules and add the additional compiler flags in
290
- %{module_flags }. (Libc++ offers these modules in C++20 as an
301
+ %{compile_flags }. (Libc++ offers these modules in C++20 as an
291
302
extension.)
292
303
293
304
Additional provided substitutions and features
@@ -354,22 +365,22 @@ def execute(self, test, litConfig):
354
365
".compile.pass.mm"
355
366
):
356
367
steps = [
357
- "%dbg(COMPILED WITH) %{cxx} %s %{flags} %{compile_flags} %{module_flags} -fsyntax-only"
368
+ "%dbg(COMPILED WITH) %{cxx} %s %{flags} %{compile_flags} -fsyntax-only"
358
369
]
359
370
return self ._executeShTest (test , litConfig , steps )
360
371
elif filename .endswith (".compile.fail.cpp" ):
361
372
steps = [
362
- "%dbg(COMPILED WITH) ! %{cxx} %s %{flags} %{compile_flags} %{module_flags} -fsyntax-only"
373
+ "%dbg(COMPILED WITH) ! %{cxx} %s %{flags} %{compile_flags} -fsyntax-only"
363
374
]
364
375
return self ._executeShTest (test , litConfig , steps )
365
376
elif filename .endswith (".link.pass.cpp" ) or filename .endswith (".link.pass.mm" ):
366
377
steps = [
367
- "%dbg(COMPILED WITH) %{cxx} %s %{flags} %{compile_flags} %{module_flags} %{ link_flags} -o %t.exe"
378
+ "%dbg(COMPILED WITH) %{cxx} %s %{flags} %{compile_flags} %{link_flags} -o %t.exe"
368
379
]
369
380
return self ._executeShTest (test , litConfig , steps )
370
381
elif filename .endswith (".link.fail.cpp" ):
371
382
steps = [
372
- "%dbg(COMPILED WITH) %{cxx} %s %{flags} %{compile_flags} %{module_flags} -c -o %t.o" ,
383
+ "%dbg(COMPILED WITH) %{cxx} %s %{flags} %{compile_flags} -c -o %t.o" ,
373
384
"%dbg(LINKED WITH) ! %{cxx} %t.o %{flags} %{link_flags} -o %t.exe" ,
374
385
]
375
386
return self ._executeShTest (test , litConfig , steps )
@@ -387,7 +398,7 @@ def execute(self, test, litConfig):
387
398
# suffixes above too.
388
399
elif filename .endswith (".pass.cpp" ) or filename .endswith (".pass.mm" ):
389
400
steps = [
390
- "%dbg(COMPILED WITH) %{cxx} %s %{flags} %{compile_flags} %{module_flags} %{ link_flags} -o %t.exe" ,
401
+ "%dbg(COMPILED WITH) %{cxx} %s %{flags} %{compile_flags} %{link_flags} -o %t.exe" ,
391
402
"%dbg(EXECUTED AS) %{exec} %t.exe" ,
392
403
]
393
404
return self ._executeShTest (test , litConfig , steps )
0 commit comments