From 9795ca57e60560229004a168f2c28ef532a1fdda Mon Sep 17 00:00:00 2001 From: Christian Wirth Date: Tue, 26 Aug 2025 18:04:35 +0200 Subject: [PATCH 1/2] track warnings in Native Image build and list their count at the very end of the build --- .../src/com/oracle/svm/core/SubstrateOptions.java | 4 ++++ .../src/com/oracle/svm/driver/NativeImage.java | 2 ++ .../src/com/oracle/svm/hosted/ProgressReporter.java | 13 +++++++++++++ .../src/com/oracle/svm/util/LogUtils.java | 11 +++++++++++ 4 files changed, 30 insertions(+) diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/SubstrateOptions.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/SubstrateOptions.java index 1a66d93608b1..643340aa14b1 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/SubstrateOptions.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/SubstrateOptions.java @@ -1711,4 +1711,8 @@ private static void validateEnableFallbackCompilation(HostedOptionKey o public static boolean canEnableFallbackCompilation() { return !EnableFallbackCompilation.getValue() && !useEconomyCompilerConfig(); } + + @Option(help = "Passes the numbers of warnings that occurred in the driver phase to the builder.", type = OptionType.Debug, stability = OptionStability.STABLE) // + public static final HostedOptionKey DriverWarningsCount = new HostedOptionKey<>(0); + } diff --git a/substratevm/src/com.oracle.svm.driver/src/com/oracle/svm/driver/NativeImage.java b/substratevm/src/com.oracle.svm.driver/src/com/oracle/svm/driver/NativeImage.java index c55462e3ebab..20576cf10217 100644 --- a/substratevm/src/com.oracle.svm.driver/src/com/oracle/svm/driver/NativeImage.java +++ b/substratevm/src/com.oracle.svm.driver/src/com/oracle/svm/driver/NativeImage.java @@ -1492,6 +1492,8 @@ private int completeImageBuild() { // allow native access for all modules on the image builder module path var enableNativeAccessModules = getModulesFromPath(imageBuilderModulePath).keySet(); imageBuilderJavaArgs.add("--enable-native-access=" + String.join(",", enableNativeAccessModules)); + // pass the number of warnings to the builder process + imageBuilderArgs.add(oH(SubstrateOptions.DriverWarningsCount)+LogUtils.getWarningsCount()); boolean useColorfulOutput = configureBuildOutput(); diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ProgressReporter.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ProgressReporter.java index 412497976c87..eabc87cb1349 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ProgressReporter.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ProgressReporter.java @@ -54,6 +54,7 @@ import java.util.stream.Stream; import com.oracle.svm.core.RuntimeAssertionsSupport; +import com.oracle.svm.util.LogUtils; import org.graalvm.nativeimage.ImageSingletons; import org.graalvm.nativeimage.hosted.Feature; import org.graalvm.nativeimage.impl.ImageSingletonsSupport; @@ -795,6 +796,7 @@ public void printEpilog(Optional optionalImageName, Optional optionalUnhandledThrowable, OptionValues parsedHostedOptions) { if (optionalUnhandledThrowable.isEmpty()) { return; diff --git a/substratevm/src/com.oracle.svm.util/src/com/oracle/svm/util/LogUtils.java b/substratevm/src/com.oracle.svm.util/src/com/oracle/svm/util/LogUtils.java index 7d26232850f9..58f9541db41f 100644 --- a/substratevm/src/com.oracle.svm.util/src/com/oracle/svm/util/LogUtils.java +++ b/substratevm/src/com.oracle.svm.util/src/com/oracle/svm/util/LogUtils.java @@ -29,6 +29,12 @@ // Checkstyle: Allow raw info or warning printing - begin public class LogUtils { + /** + * Number of warnings seen during image build. Note this is limited to the current process, i.e. there is a split + * between Driver and Builder. + */ + private static int warningsCount = 0; + /** * Print an info message. */ @@ -66,6 +72,7 @@ public static void prefixInfo(String prefix, String format, Object... args) { */ public static void warning(String message) { System.out.println("Warning: " + message); + warningsCount++; } /** @@ -87,4 +94,8 @@ public static void warning(String format, Object... args) { public static void warningDeprecatedEnvironmentVariable(String environmentVariableName) { warning("The " + environmentVariableName + " environment variable is deprecated and might be removed in a future release. Please refer to the GraalVM release notes."); } + + public static int getWarningsCount() { + return warningsCount; + } } From 6a75f11bfa63e8ccf6c0eaf2e605cd6d8673404f Mon Sep 17 00:00:00 2001 From: Christian Wirth Date: Mon, 1 Sep 2025 16:00:46 +0200 Subject: [PATCH 2/2] add option -Werror to fail when a warning occurs --- .../com/oracle/svm/core/SubstrateOptions.java | 11 ++++++ .../com/oracle/svm/driver/NativeImage.java | 2 +- .../oracle/svm/hosted/ProgressReporter.java | 35 +++++++++++++++++-- .../src/com/oracle/svm/util/LogUtils.java | 4 +-- 4 files changed, 47 insertions(+), 5 deletions(-) diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/SubstrateOptions.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/SubstrateOptions.java index 643340aa14b1..e6452bdc5000 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/SubstrateOptions.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/SubstrateOptions.java @@ -1715,4 +1715,15 @@ public static boolean canEnableFallbackCompilation() { @Option(help = "Passes the numbers of warnings that occurred in the driver phase to the builder.", type = OptionType.Debug, stability = OptionStability.STABLE) // public static final HostedOptionKey DriverWarningsCount = new HostedOptionKey<>(0); + @APIOption(name = "-Werror", defaultValue = "all")// + @Option(help = "Treat warnings as errors and terminate build.")// + public static final HostedOptionKey TreatWarningsAsError = new HostedOptionKey<>(AccumulatingLocatableMultiOptionValue.Strings.build(), key -> { + key.getValue().getValuesWithOrigins().forEach(option -> { + if (!option.origin().commandLineLike()) { + throw UserError.abort("Option '%s' provided by %s can only be used on the command line.", + SubstrateOptionsParser.commandArgument(key, option.value()), option.origin()); + } + }); + }); + } diff --git a/substratevm/src/com.oracle.svm.driver/src/com/oracle/svm/driver/NativeImage.java b/substratevm/src/com.oracle.svm.driver/src/com/oracle/svm/driver/NativeImage.java index 20576cf10217..8989d33dbf88 100644 --- a/substratevm/src/com.oracle.svm.driver/src/com/oracle/svm/driver/NativeImage.java +++ b/substratevm/src/com.oracle.svm.driver/src/com/oracle/svm/driver/NativeImage.java @@ -1493,7 +1493,7 @@ private int completeImageBuild() { var enableNativeAccessModules = getModulesFromPath(imageBuilderModulePath).keySet(); imageBuilderJavaArgs.add("--enable-native-access=" + String.join(",", enableNativeAccessModules)); // pass the number of warnings to the builder process - imageBuilderArgs.add(oH(SubstrateOptions.DriverWarningsCount)+LogUtils.getWarningsCount()); + imageBuilderArgs.add(oH(SubstrateOptions.DriverWarningsCount) + LogUtils.getWarningsCount()); boolean useColorfulOutput = configureBuildOutput(); diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ProgressReporter.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ProgressReporter.java index eabc87cb1349..0ee75aebf5c7 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ProgressReporter.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ProgressReporter.java @@ -54,6 +54,7 @@ import java.util.stream.Stream; import com.oracle.svm.core.RuntimeAssertionsSupport; +import com.oracle.svm.core.util.UserError; import com.oracle.svm.util.LogUtils; import org.graalvm.nativeimage.ImageSingletons; import org.graalvm.nativeimage.hosted.Feature; @@ -796,8 +797,9 @@ public void printEpilog(Optional optionalImageName, Optional { + if (artifactType != ArtifactType.BUILD_INFO) { + for (Path path : paths) { + try { + if (path.startsWith(SubstrateOptions.getImagePath())) { + java.nio.file.Files.delete(path); + } else { + LogUtils.warning("Cleaning up due to -Werror failed: Cannot delete artifacts not in " + SubstrateOptions.getImagePath() + ". Invalid: " + path); + } + } catch (IOException ex) { + LogUtils.warning("Cleaning up due to -Werror failed: cannot delete " + path + ": " + ex.getMessage()); + } + } + } + }); + } + private void printErrorMessage(Optional optionalUnhandledThrowable, OptionValues parsedHostedOptions) { if (optionalUnhandledThrowable.isEmpty()) { return; diff --git a/substratevm/src/com.oracle.svm.util/src/com/oracle/svm/util/LogUtils.java b/substratevm/src/com.oracle.svm.util/src/com/oracle/svm/util/LogUtils.java index 58f9541db41f..0ec76859a095 100644 --- a/substratevm/src/com.oracle.svm.util/src/com/oracle/svm/util/LogUtils.java +++ b/substratevm/src/com.oracle.svm.util/src/com/oracle/svm/util/LogUtils.java @@ -30,8 +30,8 @@ // Checkstyle: Allow raw info or warning printing - begin public class LogUtils { /** - * Number of warnings seen during image build. Note this is limited to the current process, i.e. there is a split - * between Driver and Builder. + * Number of warnings seen during image build. Note this is limited to the current process, i.e. + * there is a split between Driver and Builder. */ private static int warningsCount = 0;