Skip to content

Commit 1b6cda4

Browse files
committed
[GR-64232] Add Web Image options to ProvidedHostedOptions
PullRequest: graal/20562
2 parents 7a75901 + 1b1a9e8 commit 1b6cda4

File tree

233 files changed

+890
-679
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

233 files changed

+890
-679
lines changed

web-image/README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,10 @@ This produces `helloworld.js` and `helloworld.js.wasm` in your working
1919
directory. The JavaScript file is a wrapper that loads and runs the WebAssembly
2020
code and can be run with [Node.js](https://nodejs.org/en) 22 or later:
2121

22+
The `--tool:svm-wasm` flag should be the first argument if possible. If any
23+
experimental options specific to the Wasm backend are used, they can only be
24+
added after the `--tool:svm-wasm` flag.
25+
2226
```bash
2327
$ node helloworld.js
2428
Hello World

web-image/ci/ci.jsonnet

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ local weekly = r.weekly;
1414
{
1515
// THE TASK CONFIGURATION
1616
task_dict:: {
17-
'style-fullbuild': mxgate('style,fullbuild,webimagehelp') + t('30:00') + r.eclipse + r.jdt + r.spotbugs + r.prettier + platforms({
17+
'style-fullbuild': mxgate('style,fullbuild,webimagehelp,webimageoptions') + t('30:00') + r.eclipse + r.jdt + r.spotbugs + r.prettier + platforms({
1818
'linux:amd64:jdk-latest': gate,
1919
}),
2020
'unittest': mxgate('webimagebuild,webimageunittest') + t('30:00') + r.node22 + platforms({

web-image/mx.web-image/mx_web_image.py

Lines changed: 144 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@
3131
from os.path import join
3232
from pathlib import Path
3333
from typing import List, Optional, Union
34-
from xml.dom import minidom
3534

3635
import mx
3736
import mx_gate
@@ -62,8 +61,65 @@
6261
"web-image:SVM_WASM_API",
6362
"web-image:SVM_WASM_JIMFS",
6463
"web-image:SVM_WASM_GUAVA",
64+
"web-image:WEBIMAGE_CLOSURE_SUPPORT",
6565
"web-image:WEBIMAGE_GOOGLE_CLOSURE",
6666
]
67+
# Hosted options defined in the web-image-enterprise suite
68+
# This list has to be kept in sync with the code (the 'webimageoptions' gate tag checks this)
69+
# See also WebImageConfiguration.hosted_options
70+
web_image_hosted_options = [
71+
"AnalyzeCompoundConditionals",
72+
"AutoRunLibraries=",
73+
"AutoRunVM",
74+
"BenchmarkName=",
75+
"ClearFreeMemory",
76+
"CLIVisualizationMonochrome",
77+
"ClosureCompiler",
78+
"ClosurePrettyPrint=",
79+
"CodeSizeDiagnostics",
80+
"DebugNames",
81+
"DisableStackTraces",
82+
"DumpCurrentCompiledFunction",
83+
"DumpPreClosure",
84+
"DumpTypeControlGraph",
85+
"EnableTruffle",
86+
"EncodeImageHeapArraysBase64",
87+
"EntryPointsConfig=",
88+
"FatalUnsupportedNodes",
89+
"ForceSinglePrecision",
90+
"GCStressTest",
91+
"GenerateSourceMap",
92+
"GenTimingCode",
93+
"GrowthTriggerThreshold=",
94+
"HeapGrowthFactor=",
95+
"ImageHeapObjectsPerFunction=",
96+
"JSComments=",
97+
"JSRuntime=",
98+
"LogFilter=",
99+
"LoggingFile=",
100+
"LoggingStyle=",
101+
"NamingConvention=",
102+
"OutlineRuntimeChecks",
103+
"ReportImageSizeBreakdown",
104+
"RuntimeDebugChecks",
105+
"SILENT_COMPILE",
106+
"SourceMapSourceRoot=",
107+
"StackSize=",
108+
"StrictWarnings",
109+
"UnsafeErrorMessages",
110+
"UseBinaryen",
111+
"UsePEA",
112+
"UseRandomForTempFiles",
113+
"UseVtable",
114+
"VerificationPhases",
115+
"VerifyAllocations",
116+
"Visualization=",
117+
"VMClassName=",
118+
"WasmAsPath=",
119+
"WasmComments=",
120+
"WasmVerifyReferences",
121+
"Wat2WasmPath=",
122+
]
67123

68124

69125
class WebImageConfiguration:
@@ -76,6 +132,24 @@ class WebImageConfiguration:
76132

77133
builder_jars = web_image_builder_jars
78134

135+
additional_modules = []
136+
"""Additional modules that are added to --add-modules for the web-image launcher"""
137+
138+
hosted_options = web_image_hosted_options
139+
"""
140+
Options added to the ProvidedHostedOptions property for the svm-wasm tool macro
141+
142+
The native-image launcher checks the validity of options in the driver (not the builder),
143+
for that it discovers all options on its classpath. This will not find the options for Wasm codegen because those
144+
jars are not on the driver's classpath (they are only added to the builder's classpath through the macro).
145+
146+
The ProvidedHostedOptions property is a way to let the driver know about additional options it should accept.
147+
The alternative, adding the Wasm codegen jars to the drivers classpath doesn't work in all cases. It works for the
148+
bash launchers, but for the native image built from the driver in releases, the available options are looked up at
149+
build-time in a Feature; there, only options available on the builder's classpath are discovered. It is not possible
150+
to add the Wasm codegen jars to builder's classpath, because that would make it produce a Wasm binary.
151+
"""
152+
79153
suite = None
80154
"""Suite used to resolve the location of the web-image executable"""
81155

@@ -95,37 +169,17 @@ def get_suite(cls) -> mx.Suite:
95169
def get_builder_jars(cls) -> List[str]:
96170
return cls.builder_jars
97171

172+
@classmethod
173+
def get_additional_modules(cls) -> List[str]:
174+
return cls.additional_modules
98175

99-
# For Web Image SVM_WASM is part of the modules implicitly available on the module-path
100-
mx_sdk_vm_impl.NativePropertiesBuildTask.implicit_excludes.append(web_image_builder)
101-
102-
103-
def concatCP(old, new):
104-
if old and new:
105-
return old + ":" + new
106-
elif old:
107-
return old
108-
elif new:
109-
return new
110-
else:
111-
return ""
112-
113-
114-
def addCP(vmargs, cp):
115-
cpIndex, cpValue = mx.find_classpath_arg(vmargs)
116-
117-
if cpIndex:
118-
vmargs[cpIndex] = concatCP(cp, cpValue)
119-
else:
120-
vmargs += ["-cp", cp]
121-
122-
return vmargs
176+
@classmethod
177+
def get_hosted_options(cls) -> List[str]:
178+
return cls.hosted_options
123179

124180

125-
def run_javac(args, out=None, err=None, cwd=None, nonZeroIsFatal=True):
126-
jdk = mx.get_jdk(tag="jvmci")
127-
cmd = [jdk.javac] + args
128-
mx.run(cmd, nonZeroIsFatal=nonZeroIsFatal, out=out, err=err, cwd=cwd)
181+
# For Web Image SVM_WASM is part of the modules implicitly available on the module-path
182+
mx_sdk_vm_impl.NativePropertiesBuildTask.implicit_excludes.append(web_image_builder)
129183

130184

131185
def web_image_main_class():
@@ -190,6 +244,7 @@ class GraalWebImageTags:
190244
webimageunittest = "webimageunittest"
191245
webimageprettier = "webimageprettier"
192246
webimagehelp = "webimagehelp"
247+
webimageoptions = "webimageoptions"
193248

194249

195250
@mx.command(_suite.name, "webimageprettier")
@@ -280,6 +335,48 @@ def prettier_runner(args=None, files=None, nonZeroIsFatal=False):
280335
return (final_rc, outCapture.data, errCapture.data)
281336

282337

338+
def hosted_options_gate() -> None:
339+
"""
340+
Checks that WebImageConfiguration.hosted_options matches the options in the code.
341+
342+
For that, there is an extra hosted option, DumpProvidedHostedOptionsAndExit, that just prints the expected
343+
contents of the ProvidedHostedOptions property.
344+
"""
345+
out = mx.LinesOutputCapture()
346+
# The driver requires a class name to invoke the builder, so we just pass an arbitrary name, the builder will exit
347+
# before it tries to load it anyway.
348+
compile_web_image(
349+
["SomeClassName", "-H:+DumpProvidedHostedOptionsAndExit"],
350+
out=out,
351+
nonZeroIsFatal=True,
352+
suite=WebImageConfiguration.get_suite(),
353+
)
354+
actual_options = sorted(out.lines)
355+
hardcoded_options = sorted(WebImageConfiguration.get_hosted_options())
356+
357+
if hardcoded_options != actual_options:
358+
actual_options_set = set(actual_options)
359+
hardcoded_options_set = set(hardcoded_options)
360+
361+
missing_hardcoded_options = list(actual_options_set - hardcoded_options_set)
362+
additional_hardcoded_options = list(hardcoded_options_set - actual_options_set)
363+
364+
mx.abort(
365+
"Mismatch in hardcoded options and options defined in the code\n"
366+
+ (
367+
"Options that are not hardcoded: " + str(missing_hardcoded_options) + "\n"
368+
if missing_hardcoded_options
369+
else ""
370+
)
371+
+ (
372+
"Hardcoded options that don't exist: " + str(additional_hardcoded_options) + "\n"
373+
if additional_hardcoded_options
374+
else ""
375+
)
376+
+ "Please update the list of hardcoded options to reflect the Web Image options declared in the codebase"
377+
)
378+
379+
283380
def determine_gate_unittest_args(gate_args):
284381
vm_options = ["-Dwebimage.test.max_failures=10"]
285382

@@ -351,6 +448,14 @@ def help_stdout_check(output):
351448
"This can happen if you add extra arguments the mx web-image call without checking if an argument was --help or --help-extra."
352449
)
353450

451+
with Task(
452+
"Check that ProvidedHostedOptions contains all Web Image options",
453+
tasks,
454+
tags=[GraalWebImageTags.webimageoptions],
455+
) as t:
456+
if t:
457+
hosted_options_gate()
458+
354459

355460
add_gate_runner(_suite, gate_runner)
356461
# Defaults to JS backend
@@ -418,16 +523,6 @@ def apply(self, config):
418523
mx_unittest.register_unittest_config(WebImageUnittestConfig())
419524

420525

421-
def pom_from_template(proj_dir):
422-
# Create pom with correct version info from template
423-
version = _suite.release_version(snapshotSuffix="SNAPSHOT")
424-
dom = minidom.parse(os.path.join(proj_dir, "template-pom.xml"))
425-
for element in dom.getElementsByTagName("webImageVersion"):
426-
element.parentNode.replaceChild(dom.createTextNode(version), element)
427-
with open(os.path.join(proj_dir, "pom.xml"), "w") as pom_file:
428-
dom.writexml(pom_file)
429-
430-
431526
class WebImageMacroBuilder(mx.ArchivableProject):
432527
"""
433528
Builds a ``native-image.properties`` file that contains the configuration needed to run the Web Image builder in the
@@ -444,6 +539,7 @@ def __init__(
444539
macro_location: str,
445540
java_args: Optional[List[str]] = None,
446541
image_provided_jars: Optional[List[str]] = None,
542+
provided_hosted_options: Optional[List[str]] = None,
447543
):
448544
"""
449545
:param builder_dists: Distributions included for the builder. Exactly these are added to
@@ -452,12 +548,14 @@ def __init__(
452548
:param macro_location: Path to the macro directory. Generated paths in the macro will be relative to this path
453549
:param java_args: Additional flags to add to ``JavaArgs``
454550
:param image_provided_jars: Distributions that should be added to ``ImageProvidedJars``
551+
:param provided_hosted_options: Options that should be added to ``ProvidedHostedOptions``
455552
"""
456553
super().__init__(suite, name, [], None, None, buildDependencies=builder_dists)
457554
self.builder_dists = builder_dists
458555
self.macro_location = macro_location
459556
self.java_args = java_args or []
460557
self.image_provided_jars = image_provided_jars or []
558+
self.provided_hosted_options = provided_hosted_options or []
461559

462560
def output_dir(self):
463561
return self.get_output_root()
@@ -549,7 +647,7 @@ def get_or_compute_lines(self) -> List[str]:
549647
lines: List[str] = [
550648
"# This file is auto-generated",
551649
"ExcludeFromAll = true",
552-
"ProvidedHostedOptions = Backend=",
650+
"ProvidedHostedOptions = " + " ".join(self.subject.provided_hosted_options + ["Backend="]),
553651
]
554652

555653
if builder_jars:
@@ -603,6 +701,7 @@ def create_web_image_macro_builder(
603701
component: mx_sdk_vm.GraalVmComponent,
604702
builder_jars: List[str],
605703
java_args: Optional[List[str]] = None,
704+
provided_hosted_options: Optional[List[str]] = None,
606705
) -> WebImageMacroBuilder:
607706
"""
608707
Creates a :class:`WebImageMacroBuilder`.
@@ -637,6 +736,7 @@ def create_web_image_macro_builder(
637736
macro_path,
638737
java_args=java_args,
639738
image_provided_jars=component.jar_distributions,
739+
provided_hosted_options=provided_hosted_options,
640740
)
641741

642742

@@ -704,8 +804,10 @@ def mx_register_dynamic_suite_constituents(register_project, register_distributi
704804
# The closure compiler is only an optional dependency and as such is not part of the
705805
# module graph by default (even if it is on the module path), it has to be added
706806
# explicitly using `--add-modules`.
807+
"--add-modules=org.graalvm.extraimage.closurecompiler",
707808
"--add-modules=org.graalvm.wrapped.google.closure",
708-
],
809+
]
810+
+ ["--add-modules=" + module for module in WebImageConfiguration.get_additional_modules()],
709811
)
710812
)
711813

@@ -716,21 +818,11 @@ def mx_register_dynamic_suite_constituents(register_project, register_distributi
716818
"svm-wasm-macro-builder",
717819
wasm_component,
718820
wasm_component.builder_jar_distributions,
821+
provided_hosted_options=WebImageConfiguration.get_hosted_options(),
719822
)
720823
)
721824

722825

723-
def assert_equals(msg, expected, actual):
724-
if expected != actual:
725-
mx.abort("Assertion failed: {} expected: {!r} but was: {!r}".format(msg, expected, actual))
726-
727-
728-
def graalvm_home():
729-
capture = mx.OutputCapture()
730-
mx.run_mx(["graalvm-home"], out=capture, quiet=True)
731-
return capture.data.strip()
732-
733-
734826
# This callback is essential for mx to generate the manifest file so that the ServiceLoader can find
735827
# the OptionDescripter defined in Web Image
736828
def mx_post_parse_cmd_line(opts):

0 commit comments

Comments
 (0)