From 0fc109509a0a662e20989242ecedecb30dec5bb4 Mon Sep 17 00:00:00 2001 From: Patrick Ziegler Date: Mon, 28 Apr 2025 14:36:58 +0200 Subject: [PATCH] Make -H:Backend= a real option Originally, it was parsed out manually because the svm.platform property was read before parsing option. This no longer seems the case and we can use the NativeImageClassLoaderPostProcessing SPI to set the property after the hosted options are parsed and before the property is read to create the platform. --- web-image/mx.web-image/mx_web_image.py | 2 +- ...osted.NativeImageClassLoaderPostProcessing | 1 + .../NativeImageWasmGeneratorRunner.java | 66 ++++--------------- .../webimage/WebImagePlatformInjector.java | 61 +++++++++++++++++ .../webimage/options/WebImageOptions.java | 9 +++ 5 files changed, 83 insertions(+), 56 deletions(-) create mode 100644 web-image/src/com.oracle.svm.hosted.webimage/src/META-INF/services/com.oracle.svm.hosted.NativeImageClassLoaderPostProcessing create mode 100644 web-image/src/com.oracle.svm.hosted.webimage/src/com/oracle/svm/hosted/webimage/WebImagePlatformInjector.java diff --git a/web-image/mx.web-image/mx_web_image.py b/web-image/mx.web-image/mx_web_image.py index 76f068d562d6..7671f68c4c48 100644 --- a/web-image/mx.web-image/mx_web_image.py +++ b/web-image/mx.web-image/mx_web_image.py @@ -647,7 +647,7 @@ def get_or_compute_lines(self) -> List[str]: lines: List[str] = [ "# This file is auto-generated", "ExcludeFromAll = true", - "ProvidedHostedOptions = " + " ".join(self.subject.provided_hosted_options + ["Backend="]), + "ProvidedHostedOptions = " + " ".join(self.subject.provided_hosted_options), ] if builder_jars: diff --git a/web-image/src/com.oracle.svm.hosted.webimage/src/META-INF/services/com.oracle.svm.hosted.NativeImageClassLoaderPostProcessing b/web-image/src/com.oracle.svm.hosted.webimage/src/META-INF/services/com.oracle.svm.hosted.NativeImageClassLoaderPostProcessing new file mode 100644 index 000000000000..9520d37fbfe2 --- /dev/null +++ b/web-image/src/com.oracle.svm.hosted.webimage/src/META-INF/services/com.oracle.svm.hosted.NativeImageClassLoaderPostProcessing @@ -0,0 +1 @@ +com.oracle.svm.hosted.webimage.WebImagePlatformInjector diff --git a/web-image/src/com.oracle.svm.hosted.webimage/src/com/oracle/svm/hosted/webimage/NativeImageWasmGeneratorRunner.java b/web-image/src/com.oracle.svm.hosted.webimage/src/com/oracle/svm/hosted/webimage/NativeImageWasmGeneratorRunner.java index ca8726f12c78..01c3c8a58e40 100644 --- a/web-image/src/com.oracle.svm.hosted.webimage/src/com/oracle/svm/hosted/webimage/NativeImageWasmGeneratorRunner.java +++ b/web-image/src/com.oracle.svm.hosted.webimage/src/com/oracle/svm/hosted/webimage/NativeImageWasmGeneratorRunner.java @@ -26,15 +26,11 @@ import java.lang.reflect.Method; import java.util.ArrayList; -import java.util.Arrays; import java.util.Comparator; -import java.util.Iterator; import java.util.List; -import java.util.Locale; import org.graalvm.collections.EconomicMap; import org.graalvm.collections.Pair; -import org.graalvm.nativeimage.Platform; import org.graalvm.nativeimage.c.type.CIntPointer; import org.graalvm.nativeimage.c.type.CShortPointer; @@ -74,60 +70,11 @@ */ public class NativeImageWasmGeneratorRunner extends NativeImageGeneratorRunner { - public static final String BACKEND_ARG = "-H:Backend(@[^=]*)?=.*"; - /** * @param args Hosted and runtime options */ public static void main(String[] args) { - List arguments = Arrays.asList(args); - arguments = extractDriverArguments(arguments); - - CompilerBackend backend; - if (WebImageOptions.isNativeImageBackend()) { - // Under native-image, selection of the Web Image backend is not allowed - backend = CompilerBackend.WASMGC; - } else { - backend = extractBackend(arguments); - } - - // installNativeImageClassLoader uses this property to create the platform instance. - System.setProperty(Platform.PLATFORM_PROPERTY_NAME, backend.platform.getName()); - new NativeImageWasmGeneratorRunner().start(arguments.toArray(String[]::new)); - } - - /** - * Extracts the {@link NativeImageWasmGeneratorRunner#BACKEND_ARG} argument as a - * {@link CompilerBackend} from the list of arguments. - * - * @param arguments The list of arguments. The backend argument will be removed from the list if - * specified. - * @return The appropriate compiler backend for the given arguments or - * {@link CompilerBackend#JS} if none was specified - */ - public static CompilerBackend extractBackend(List arguments) { - Iterator it = arguments.iterator(); - - while (it.hasNext()) { - String param = it.next(); - - if (param.matches(BACKEND_ARG)) { - it.remove(); - String[] parts = param.split("=", 2); - if (parts.length != 2) { - throw new IllegalArgumentException(BACKEND_ARG + " needs an argument"); - } - String backendName = parts[1].toUpperCase(Locale.ROOT); - try { - return CompilerBackend.valueOf(backendName); - } catch (IllegalArgumentException e) { - throw new IllegalArgumentException("No backend with name " + backendName + " exists", e); - } - } - } - - // Use JS backend by default - return CompilerBackend.JS; + new NativeImageWasmGeneratorRunner().start(args); } /** @@ -142,7 +89,16 @@ private static void dumpProvidedHostedOptions(HostedOptionParser optionParser) { List names = new ArrayList<>(); for (OptionDescriptor value : allHostedOptions.getValues()) { - if (!value.getDeclaringClass().getPackageName().contains("webimage") || WebImageOptions.DebugOptions.DumpProvidedHostedOptionsAndExit == value.getOptionKey()) { + if (!value.getDeclaringClass().getPackageName().contains("webimage")) { + continue; + } + + if (WebImageOptions.DebugOptions.DumpProvidedHostedOptionsAndExit == value.getOptionKey()) { + continue; + } + + // Do not print the Backend option, it's not available in the svm-wasm macro + if (WebImageOptions.Backend == value.getOptionKey()) { continue; } diff --git a/web-image/src/com.oracle.svm.hosted.webimage/src/com/oracle/svm/hosted/webimage/WebImagePlatformInjector.java b/web-image/src/com.oracle.svm.hosted.webimage/src/com/oracle/svm/hosted/webimage/WebImagePlatformInjector.java new file mode 100644 index 000000000000..3824149986e6 --- /dev/null +++ b/web-image/src/com.oracle.svm.hosted.webimage/src/com/oracle/svm/hosted/webimage/WebImagePlatformInjector.java @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2025, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.oracle.svm.hosted.webimage; + +import static com.oracle.svm.hosted.webimage.options.WebImageOptions.CompilerBackend; +import static com.oracle.svm.hosted.webimage.options.WebImageOptions.isNativeImageBackend; + +import org.graalvm.nativeimage.Platform; + +import com.oracle.svm.hosted.NativeImageClassLoaderPostProcessing; +import com.oracle.svm.hosted.NativeImageClassLoaderSupport; +import com.oracle.svm.hosted.webimage.options.WebImageOptions; + +/** + * Sets the {@link Platform#PLATFORM_PROPERTY_NAME} property based on which code-generation backend + * is selected. + *

+ * In the {@code native-image} launcher this is always the WasmGC backend. Under {@code web-image}, + * it is determined by the {@link WebImageOptions#Backend} option. + */ +public class WebImagePlatformInjector implements NativeImageClassLoaderPostProcessing { + @Override + public void apply(NativeImageClassLoaderSupport support) { + CompilerBackend backend; + if (isNativeImageBackend()) { + // Under native-image, selection of the Web Image backend is not allowed + backend = CompilerBackend.WASMGC; + } else { + backend = WebImageOptions.Backend.getValue(support.getParsedHostedOptions()); + } + + /* + * installNativeImageClassLoader uses this property at the end to create the platform + * instance. This method is called before that. + */ + System.setProperty(Platform.PLATFORM_PROPERTY_NAME, backend.platform.getName()); + } +} diff --git a/web-image/src/com.oracle.svm.hosted.webimage/src/com/oracle/svm/hosted/webimage/options/WebImageOptions.java b/web-image/src/com.oracle.svm.hosted.webimage/src/com/oracle/svm/hosted/webimage/options/WebImageOptions.java index e913d1ed9efa..218eccf6e537 100644 --- a/web-image/src/com.oracle.svm.hosted.webimage/src/com/oracle/svm/hosted/webimage/options/WebImageOptions.java +++ b/web-image/src/com.oracle.svm.hosted.webimage/src/com/oracle/svm/hosted/webimage/options/WebImageOptions.java @@ -135,6 +135,15 @@ public static final class DebugOptions { public static final HostedOptionKey DumpProvidedHostedOptionsAndExit = new HostedOptionKey<>(false); } + /** + * Web Image only. + *

+ * Do not read this value directly. Instead, look it up based on the selected {@link Platform} + * using {@link #getBackend}. + */ + @Option(help = "The Web Image Backend to use.") // + public static final EnumOptionKey Backend = new EnumOptionKey<>(CompilerBackend.JS); + @Option(help = "Report the code sizes of different parts of the generated JavaScript image. If the closure compiler is applied, this instruments the generated javascript code by injecting labels.")// public static final HostedOptionKey ReportImageSizeBreakdown = new HostedOptionKey<>(false);