From 23a7a800ab6053a4567531096e5006e51b5b04fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20W=C3=B6gerer?= Date: Tue, 19 Aug 2025 16:57:38 +0200 Subject: [PATCH] Ensure users see final bundle output directories in build-output --- .../com/oracle/svm/driver/BundleSupport.java | 8 ++++- .../com/oracle/svm/driver/NativeImage.java | 31 +++++++++++++++++-- 2 files changed, 36 insertions(+), 3 deletions(-) diff --git a/substratevm/src/com.oracle.svm.driver/src/com/oracle/svm/driver/BundleSupport.java b/substratevm/src/com.oracle.svm.driver/src/com/oracle/svm/driver/BundleSupport.java index 3c274093be8a..7fb5ec0bd4f4 100644 --- a/substratevm/src/com.oracle.svm.driver/src/com/oracle/svm/driver/BundleSupport.java +++ b/substratevm/src/com.oracle.svm.driver/src/com/oracle/svm/driver/BundleSupport.java @@ -583,7 +583,7 @@ void complete() { } if (writeOutput) { - Path externalOutputDir = bundlePath.resolve(bundleName + "." + outputDir.getFileName()); + Path externalOutputDir = getExternalOutputDir(); copyFiles(outputDir, externalOutputDir, true); nativeImage.showMessage(BUNDLE_INFO_MESSAGE_PREFIX + "Bundle build output written to " + externalOutputDir); } @@ -598,6 +598,12 @@ void complete() { } } + Path getExternalOutputDir() { + Objects.requireNonNull(bundlePath); + Objects.requireNonNull(bundleName); + return bundlePath.resolve(bundleName + '.' + outputDir.getFileName()); + } + void updateBundleLocation(Path bundleFile, boolean redefine) { if (redefine) { bundlePath = null; 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 9a9fb86d0389..031b08216477 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 @@ -31,6 +31,7 @@ import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; +import java.io.PrintStream; import java.lang.module.FindException; import java.lang.module.ModuleDescriptor; import java.lang.module.ModuleFinder; @@ -83,6 +84,7 @@ import com.oracle.svm.common.option.CommonOptions; import com.oracle.svm.core.FallbackExecutor; import com.oracle.svm.core.FallbackExecutor.Options; +import com.oracle.svm.core.JavaVersionUtil; import com.oracle.svm.core.NativeImageClassLoaderOptions; import com.oracle.svm.core.OS; import com.oracle.svm.core.SharedConstants; @@ -111,7 +113,6 @@ import com.oracle.svm.util.StringUtil; import jdk.graal.compiler.options.OptionKey; -import com.oracle.svm.core.JavaVersionUtil; import jdk.internal.jimage.ImageReader; public class NativeImage { @@ -1865,7 +1866,17 @@ protected int buildImage(List javaArgs, LinkedHashSet cp, LinkedHa Process p = null; try { - p = pb.inheritIO().start(); + if (!useBundle()) { + pb.inheritIO(); + } + p = pb.start(); + if (useBundle()) { + var internalOutputDir = bundleSupport.outputDir.toString(); + var externalOutputDir = bundleSupport.getExternalOutputDir().toString(); + Function filter = line -> line.replace(internalOutputDir, externalOutputDir); + ProcessOutputTransformer.attach(p.getInputStream(), filter, System.out); + ProcessOutputTransformer.attach(p.getErrorStream(), filter, System.err); + } imageBuilderPid = p.pid(); return p.waitFor(); } catch (IOException | InterruptedException e) { @@ -1877,6 +1888,22 @@ protected int buildImage(List javaArgs, LinkedHashSet cp, LinkedHa } } + private record ProcessOutputTransformer(InputStream in, Function filter, PrintStream out) implements Runnable { + + static void attach(InputStream in, Function filter, PrintStream out) { + Thread.ofVirtual().start(new ProcessOutputTransformer(in, filter, out)); + } + + @Override + public void run() { + try (BufferedReader reader = new BufferedReader(new InputStreamReader(in))) { + reader.lines().map(filter).forEach(out::println); + } catch (IOException e) { + throw showError("Unable to process stdout/stderr of image builder process", e); + } + } + } + /** * Creates a file with name 'fileName' in the {@link NativeImage#driverTempDir temporary * directory} and returns the path to the newly created file. Note: the file will be deleted if