From 154c7b6f03df05c24f4ef1703b04c7f85a1cb248 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20W=C3=B6gerer?= Date: Thu, 12 Jan 2023 23:27:06 +0100 Subject: [PATCH] Allow support for --bundle-update --- .../resources/HelpExtra.txt | 4 + .../com/oracle/svm/driver/BundleSupport.java | 79 +++++++++++-------- .../com/oracle/svm/driver/NativeImage.java | 4 + 3 files changed, 55 insertions(+), 32 deletions(-) diff --git a/substratevm/src/com.oracle.svm.driver/resources/HelpExtra.txt b/substratevm/src/com.oracle.svm.driver/resources/HelpExtra.txt index 693eb7d28c92..8ba4e0c71884 100644 --- a/substratevm/src/com.oracle.svm.driver/resources/HelpExtra.txt +++ b/substratevm/src/com.oracle.svm.driver/resources/HelpExtra.txt @@ -26,6 +26,10 @@ Non-standard options help: an image will be built from the given bundle with the exact same arguments and files that have been passed to native-image originally to create the bundle. + --bundle-update bundle-file + same as --bundle-apply but given extra arguments add to the arguments + provided by the bundle. After image build the additional arguments + are incorporated into an updated bundle file. -V= provide values for placeholders in native-image.properties files 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 2bb4051af909..b635d951e1dd 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 @@ -35,6 +35,7 @@ import java.nio.file.StandardCopyOption; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.List; @@ -61,16 +62,19 @@ final class BundleSupport { static final String BUNDLE_OPTION = "--bundle"; enum BundleStatus { - prepare(false, false), - create(false, false), - apply(true, true); + prepare(false, false, true), + create(false, false, true), + update(false, true, true), + apply(true, true, false); final boolean hidden; final boolean loadBundle; + final boolean writeBundle; - BundleStatus(boolean hidden, boolean loadBundle) { + BundleStatus(boolean hidden, boolean loadBundle, boolean writeBundle) { this.hidden = hidden; this.loadBundle = loadBundle; + this.writeBundle = writeBundle; } boolean show() { @@ -95,6 +99,7 @@ boolean show() { Map pathSubstitutions = new HashMap<>(); private final List buildArgs; + private Collection updatedBuildArgs; private static final String bundleTempDirPrefix = "bundleRoot-"; private static final String bundleFileExtension = ".nib"; @@ -130,26 +135,9 @@ static BundleSupport create(NativeImage nativeImage, String bundleArg, NativeIma bundleSupport = new BundleSupport(nativeImage, bundleStatus, bundleFilename); List buildArgs = bundleSupport.getBuildArgs(); for (int i = buildArgs.size() - 1; i >= 0; i--) { - String buildArg = buildArgs.get(i); - if (buildArg.startsWith(BUNDLE_OPTION)) { - assert !BundleStatus.valueOf(buildArg.substring(BUNDLE_OPTION.length() + 1)).loadBundle; - continue; - } - if (buildArg.startsWith(nativeImage.oHPath)) { - continue; - } - if (buildArg.equals(DefaultOptionHandler.verboseOption)) { - continue; - } - if (buildArg.startsWith("-Dllvm.bin.dir=")) { - Optional existing = nativeImage.config.getBuildArgs().stream().filter(arg -> arg.startsWith("-Dllvm.bin.dir=")).findFirst(); - if (existing.isPresent() && !existing.get().equals(buildArg)) { - throw NativeImage.showError("Bundle native-image argument '" + buildArg + "' conflicts with existing '" + existing.get() + "'."); - } - continue; - } - args.push(buildArg); + args.push(buildArgs.get(i)); } + bundleSupport.updatedBuildArgs = args.snapshot(); } else { bundleSupport = new BundleSupport(nativeImage, bundleStatus); } @@ -261,10 +249,6 @@ private BundleSupport(NativeImage nativeImage, BundleStatus status, String bundl } } - public boolean isBundleCreation() { - return !status.loadBundle; - } - public List getBuildArgs() { return buildArgs; } @@ -455,9 +439,7 @@ void complete() { } try { - if (isBundleCreation()) { - writeBundle(); - } + writeBundle(); } finally { nativeImage.deleteAllFiles(rootDir); } @@ -469,7 +451,19 @@ public void setBundleLocation(Path imagePath, String imageName) { } void writeBundle() { - assert isBundleCreation(); + if (!status.writeBundle) { + return; + } + + String originalOutputDirName = outputDir.getFileName().toString() + originalDirExtension; + Path originalOutputDir = rootDir.resolve(originalOutputDirName); + if (Files.exists(originalOutputDir)) { + nativeImage.deleteAllFiles(originalOutputDir); + } + Path metaInfDir = rootDir.resolve("META-INF"); + if (Files.exists(metaInfDir)) { + nativeImage.deleteAllFiles(metaInfDir); + } Path pathCanonicalizationsFile = stageDir.resolve("path_canonicalizations.json"); try (JsonWriter writer = new JsonWriter(pathCanonicalizationsFile)) { @@ -488,8 +482,29 @@ void writeBundle() { Path buildArgsFile = stageDir.resolve("build.json"); try (JsonWriter writer = new JsonWriter(buildArgsFile)) { + ArrayList cleanBuildArgs = new ArrayList<>(); + for (String buildArg : updatedBuildArgs != null ? updatedBuildArgs : buildArgs) { + if (buildArg.startsWith(BUNDLE_OPTION)) { + assert !BundleStatus.valueOf(buildArg.substring(BUNDLE_OPTION.length() + 1)).loadBundle; + continue; + } + if (buildArg.startsWith(nativeImage.oHPath)) { + continue; + } + if (buildArg.equals(DefaultOptionHandler.verboseOption)) { + continue; + } + if (buildArg.startsWith("-Dllvm.bin.dir=")) { + Optional existing = nativeImage.config.getBuildArgs().stream().filter(arg -> arg.startsWith("-Dllvm.bin.dir=")).findFirst(); + if (existing.isPresent() && !existing.get().equals(buildArg)) { + throw NativeImage.showError("Bundle native-image argument '" + buildArg + "' conflicts with existing '" + existing.get() + "'."); + } + continue; + } + cleanBuildArgs.add(buildArg); + } /* Printing as list with defined sort-order ensures useful diffs are possible */ - JsonPrinter.printCollection(writer, buildArgs, null, BundleSupport::printBuildArg); + JsonPrinter.printCollection(writer, cleanBuildArgs, null, BundleSupport::printBuildArg); } catch (IOException e) { throw NativeImage.showError("Failed to write bundle-file " + pathSubstitutionsFile, e); } 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 735c15a033a4..c3823d73ce37 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 @@ -176,6 +176,10 @@ public boolean isEmpty() { public int size() { return queue.size(); } + + public List snapshot() { + return new ArrayList<>(queue); + } } abstract static class OptionHandler {