From d0c0b530daedaea1aaa118c362212e74fa3a695b Mon Sep 17 00:00:00 2001 From: Foivos Zakkak Date: Fri, 18 Dec 2020 02:13:01 +0200 Subject: [PATCH 1/5] Update documentation of container-build property --- .../src/main/java/io/quarkus/deployment/pkg/NativeConfig.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/deployment/src/main/java/io/quarkus/deployment/pkg/NativeConfig.java b/core/deployment/src/main/java/io/quarkus/deployment/pkg/NativeConfig.java index ce4d24084b8f2..7717fd5d137e1 100644 --- a/core/deployment/src/main/java/io/quarkus/deployment/pkg/NativeConfig.java +++ b/core/deployment/src/main/java/io/quarkus/deployment/pkg/NativeConfig.java @@ -166,8 +166,8 @@ public class NativeConfig { public boolean dumpProxies; /** - * If this build should be done using a container runtime. If this is set docker will be used by default, - * unless container-runtime is also set. + * If this build should be done using a container runtime. Unless container-runtime is also set, docker will be + * used by default. If docker is not available or is an alias to podman, podman will be used instead as the default. */ @ConfigItem public boolean containerBuild; From 609d216fab8ad39b4229b5cadf474979331fe343 Mon Sep 17 00:00:00 2001 From: Foivos Zakkak Date: Tue, 2 Mar 2021 14:50:08 +0200 Subject: [PATCH 2/5] Change the way the builder image is used on remote docker daemons This patch creates a volume for /project where we can copy files to/from using `docker cp`. The volume is create in the prebuild step, then used in the build step, and finally removed in the postbuild step. The new approach allows us to execute more than one commands using `docker run --rm` on the same files in /project. --- .../NativeImageBuildContainerRunner.java | 2 +- .../NativeImageBuildLocalContainerRunner.java | 2 +- ...NativeImageBuildRemoteContainerRunner.java | 63 +++++++++++++------ 3 files changed, 46 insertions(+), 21 deletions(-) diff --git a/core/deployment/src/main/java/io/quarkus/deployment/pkg/steps/NativeImageBuildContainerRunner.java b/core/deployment/src/main/java/io/quarkus/deployment/pkg/steps/NativeImageBuildContainerRunner.java index 6aa30b51ea184..bd734cb694d87 100644 --- a/core/deployment/src/main/java/io/quarkus/deployment/pkg/steps/NativeImageBuildContainerRunner.java +++ b/core/deployment/src/main/java/io/quarkus/deployment/pkg/steps/NativeImageBuildContainerRunner.java @@ -30,7 +30,7 @@ public NativeImageBuildContainerRunner(NativeConfig nativeConfig, Path outputDir containerRuntime = nativeConfig.containerRuntime.orElseGet(NativeImageBuildContainerRunner::detectContainerRuntime); log.infof("Using %s to run the native image builder", containerRuntime.getExecutableName()); - this.baseContainerRuntimeArgs = new String[] { "--env", "LANG=C" }; + this.baseContainerRuntimeArgs = new String[] { "--env", "LANG=C", "--rm" }; outputPath = outputDir == null ? null : outputDir.toAbsolutePath().toString(); diff --git a/core/deployment/src/main/java/io/quarkus/deployment/pkg/steps/NativeImageBuildLocalContainerRunner.java b/core/deployment/src/main/java/io/quarkus/deployment/pkg/steps/NativeImageBuildLocalContainerRunner.java index ec8e6ee6cb4e2..f1e09c4c7a483 100644 --- a/core/deployment/src/main/java/io/quarkus/deployment/pkg/steps/NativeImageBuildLocalContainerRunner.java +++ b/core/deployment/src/main/java/io/quarkus/deployment/pkg/steps/NativeImageBuildLocalContainerRunner.java @@ -35,7 +35,7 @@ protected List getContainerRuntimeBuildArgs() { } } - Collections.addAll(containerRuntimeArgs, "--rm", "-v", + Collections.addAll(containerRuntimeArgs, "-v", volumeOutputPath + ":" + NativeImageBuildStep.CONTAINER_BUILD_VOLUME_PATH + ":z"); return containerRuntimeArgs; } diff --git a/core/deployment/src/main/java/io/quarkus/deployment/pkg/steps/NativeImageBuildRemoteContainerRunner.java b/core/deployment/src/main/java/io/quarkus/deployment/pkg/steps/NativeImageBuildRemoteContainerRunner.java index 34c20b4b2a31f..7645808509944 100644 --- a/core/deployment/src/main/java/io/quarkus/deployment/pkg/steps/NativeImageBuildRemoteContainerRunner.java +++ b/core/deployment/src/main/java/io/quarkus/deployment/pkg/steps/NativeImageBuildRemoteContainerRunner.java @@ -4,6 +4,8 @@ import java.io.IOException; import java.io.InputStreamReader; import java.nio.file.Path; +import java.util.Arrays; +import java.util.Collections; import java.util.List; import org.jboss.logging.Logger; @@ -13,6 +15,7 @@ public class NativeImageBuildRemoteContainerRunner extends NativeImageBuildContainerRunner { private static final Logger log = Logger.getLogger(NativeImageBuildRemoteContainerRunner.class); + private static final String CONTAINER_BUILD_VOLUME_NAME = "quarkus-native-builder-image-project-volume"; private final String resultingExecutableName; private String containerId; @@ -24,41 +27,63 @@ public NativeImageBuildRemoteContainerRunner(NativeConfig nativeConfig, Path out @Override protected void preBuild(List buildArgs) throws InterruptedException, IOException { - List containerRuntimeArgs = getContainerRuntimeBuildArgs(); - String[] createContainerCommand = buildCommand("create", containerRuntimeArgs, buildArgs); - log.info(String.join(" ", createContainerCommand).replace("$", "\\$")); - Process createContainerProcess = new ProcessBuilder(createContainerCommand).start(); - if (createContainerProcess.waitFor() != 0) { - throw new RuntimeException("Failed to create builder container."); - } - try (BufferedReader reader = new BufferedReader(new InputStreamReader(createContainerProcess.getInputStream()))) { - containerId = reader.readLine(); - } + // docker volume rm + rmVolume(null); + // docker create -v :/project + final List containerRuntimeArgs = Arrays.asList("-v", + CONTAINER_BUILD_VOLUME_NAME + ":" + NativeImageBuildStep.CONTAINER_BUILD_VOLUME_PATH); + final String[] createTempContainerCommand = buildCommand("create", containerRuntimeArgs, Collections.emptyList()); + containerId = runCommandAndReadOutput(createTempContainerCommand, "Failed to create temp container."); + // docker cp :/project String[] copyCommand = new String[] { containerRuntime.getExecutableName(), "cp", outputPath + "/.", containerId + ":" + NativeImageBuildStep.CONTAINER_BUILD_VOLUME_PATH }; runCommand(copyCommand, "Failed to copy source-jar and libs from host to builder container", null); super.preBuild(buildArgs); } - @Override - protected String[] getBuildCommand(List args) { - return new String[] { containerRuntime.getExecutableName(), "start", "--attach", containerId }; + private String runCommandAndReadOutput(String[] command, String errorMsg) throws IOException, InterruptedException { + log.info(String.join(" ", command).replace("$", "\\$")); + Process process = new ProcessBuilder(command).start(); + if (process.waitFor() != 0) { + throw new RuntimeException(errorMsg); + } + try (BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()))) { + return reader.readLine(); + } } @Override - protected void postBuild() throws InterruptedException, IOException { - copyFromBuilder(resultingExecutableName, "Failed to copy native executable from container back to the host."); + protected void postBuild() { + copyFromContainerVolume(resultingExecutableName, "Failed to copy native image from container volume back to the host."); if (nativeConfig.debug.enabled) { - copyFromBuilder("sources", "Failed to copy sources from container back to the host."); + copyFromContainerVolume("sources", "Failed to copy sources from container volume back to the host."); } - String[] removeCommand = new String[] { containerRuntime.getExecutableName(), "container", "rm", "--volumes", + // docker container rm + final String[] rmTempContainerCommand = new String[] { containerRuntime.getExecutableName(), "container", "rm", containerId }; - runCommand(removeCommand, "Failed to remove container: " + containerId, null); + runCommand(rmTempContainerCommand, "Failed to remove container: " + containerId, null); + // docker volume rm + rmVolume("Failed to remove volume: " + CONTAINER_BUILD_VOLUME_NAME); } - private void copyFromBuilder(String path, String errorMsg) throws IOException, InterruptedException { + private void rmVolume(String errorMsg) { + final String[] rmVolumeCommand = new String[] { containerRuntime.getExecutableName(), "volume", "rm", + CONTAINER_BUILD_VOLUME_NAME }; + runCommand(rmVolumeCommand, errorMsg, null); + } + + private void copyFromContainerVolume(String path, String errorMsg) { + // docker cp :/project/ String[] copyCommand = new String[] { containerRuntime.getExecutableName(), "cp", containerId + ":" + NativeImageBuildStep.CONTAINER_BUILD_VOLUME_PATH + "/" + path, outputPath }; runCommand(copyCommand, errorMsg, null); } + + @Override + protected List getContainerRuntimeBuildArgs() { + List containerRuntimeArgs = super.getContainerRuntimeBuildArgs(); + Collections.addAll(containerRuntimeArgs, "-v", + CONTAINER_BUILD_VOLUME_NAME + ":" + NativeImageBuildStep.CONTAINER_BUILD_VOLUME_PATH); + return containerRuntimeArgs; + } } From 1bc84bcef3cc41630fec6811b0e64bd201bb2d57 Mon Sep 17 00:00:00 2001 From: Foivos Zakkak Date: Tue, 2 Mar 2021 15:34:03 +0200 Subject: [PATCH 3/5] Run objcopy in builder-image when using it --- .../NativeImageBuildContainerRunner.java | 11 +++ .../steps/NativeImageBuildLocalRunner.java | 33 +++++++- ...NativeImageBuildRemoteContainerRunner.java | 2 + .../pkg/steps/NativeImageBuildRunner.java | 35 ++++++++- .../pkg/steps/NativeImageBuildStep.java | 75 +++---------------- 5 files changed, 89 insertions(+), 67 deletions(-) diff --git a/core/deployment/src/main/java/io/quarkus/deployment/pkg/steps/NativeImageBuildContainerRunner.java b/core/deployment/src/main/java/io/quarkus/deployment/pkg/steps/NativeImageBuildContainerRunner.java index bd734cb694d87..b20e35e8b0106 100644 --- a/core/deployment/src/main/java/io/quarkus/deployment/pkg/steps/NativeImageBuildContainerRunner.java +++ b/core/deployment/src/main/java/io/quarkus/deployment/pkg/steps/NativeImageBuildContainerRunner.java @@ -70,6 +70,17 @@ protected String[] getBuildCommand(List args) { return buildCommand("run", getContainerRuntimeBuildArgs(), args); } + @Override + protected void objcopy(String... args) { + final List containerRuntimeBuildArgs = getContainerRuntimeBuildArgs(); + Collections.addAll(containerRuntimeBuildArgs, "--entrypoint", "/bin/bash"); + final ArrayList objcopyCommand = new ArrayList<>(2); + objcopyCommand.add("-c"); + objcopyCommand.add("objcopy " + String.join(" ", args)); + final String[] command = buildCommand("run", containerRuntimeBuildArgs, objcopyCommand); + runCommand(command, null, null); + } + protected List getContainerRuntimeBuildArgs() { List containerRuntimeArgs = new ArrayList<>(); nativeConfig.containerRuntimeOptions.ifPresent(containerRuntimeArgs::addAll); diff --git a/core/deployment/src/main/java/io/quarkus/deployment/pkg/steps/NativeImageBuildLocalRunner.java b/core/deployment/src/main/java/io/quarkus/deployment/pkg/steps/NativeImageBuildLocalRunner.java index 4a2c8a123e30b..e693a90b34e55 100644 --- a/core/deployment/src/main/java/io/quarkus/deployment/pkg/steps/NativeImageBuildLocalRunner.java +++ b/core/deployment/src/main/java/io/quarkus/deployment/pkg/steps/NativeImageBuildLocalRunner.java @@ -1,14 +1,17 @@ package io.quarkus.deployment.pkg.steps; +import java.io.File; import java.util.List; import java.util.stream.Stream; public class NativeImageBuildLocalRunner extends NativeImageBuildRunner { private final String nativeImageExecutable; + private final File workingDirectory; - public NativeImageBuildLocalRunner(String nativeImageExecutable) { + public NativeImageBuildLocalRunner(String nativeImageExecutable, File workingDirectory) { this.nativeImageExecutable = nativeImageExecutable; + this.workingDirectory = workingDirectory; } @Override @@ -21,6 +24,34 @@ protected String[] getBuildCommand(List args) { return buildCommand(args); } + @Override + protected void objcopy(String... args) { + final String[] command = new String[args.length + 1]; + command[0] = "objcopy"; + System.arraycopy(args, 0, command, 1, args.length); + runCommand(command, null, workingDirectory); + } + + @Override + protected boolean objcopyExists() { + // System path + String systemPath = System.getenv("PATH"); + if (systemPath != null) { + String[] pathDirs = systemPath.split(File.pathSeparator); + for (String pathDir : pathDirs) { + File dir = new File(pathDir); + if (dir.isDirectory()) { + File file = new File(dir, "objcopy"); + if (file.exists()) { + return true; + } + } + } + } + + return false; + } + private String[] buildCommand(List args) { return Stream.concat(Stream.of(nativeImageExecutable), args.stream()).toArray(String[]::new); } diff --git a/core/deployment/src/main/java/io/quarkus/deployment/pkg/steps/NativeImageBuildRemoteContainerRunner.java b/core/deployment/src/main/java/io/quarkus/deployment/pkg/steps/NativeImageBuildRemoteContainerRunner.java index 7645808509944..393c6a378ed06 100644 --- a/core/deployment/src/main/java/io/quarkus/deployment/pkg/steps/NativeImageBuildRemoteContainerRunner.java +++ b/core/deployment/src/main/java/io/quarkus/deployment/pkg/steps/NativeImageBuildRemoteContainerRunner.java @@ -57,6 +57,8 @@ protected void postBuild() { copyFromContainerVolume(resultingExecutableName, "Failed to copy native image from container volume back to the host."); if (nativeConfig.debug.enabled) { copyFromContainerVolume("sources", "Failed to copy sources from container volume back to the host."); + String symbols = String.format("%s.debug", nativeImageName); + copyFromContainerVolume(symbols, "Failed to copy debug symbols from container volume back to the host."); } // docker container rm final String[] rmTempContainerCommand = new String[] { containerRuntime.getExecutableName(), "container", "rm", diff --git a/core/deployment/src/main/java/io/quarkus/deployment/pkg/steps/NativeImageBuildRunner.java b/core/deployment/src/main/java/io/quarkus/deployment/pkg/steps/NativeImageBuildRunner.java index b3b7014ce1b09..07f08ac524cb7 100644 --- a/core/deployment/src/main/java/io/quarkus/deployment/pkg/steps/NativeImageBuildRunner.java +++ b/core/deployment/src/main/java/io/quarkus/deployment/pkg/steps/NativeImageBuildRunner.java @@ -42,7 +42,8 @@ public GraalVM.Version getGraalVMVersion() { public void setup(boolean processInheritIODisabled) { } - public int build(List args, Path outputDir, boolean processInheritIODisabled) + public int build(List args, String nativeImageName, Path outputDir, boolean debugEnabled, + boolean processInheritIODisabled) throws InterruptedException, IOException { preBuild(args); try { @@ -57,16 +58,44 @@ public int build(List args, Path outputDir, boolean processInheritIODisa errorReportLatch)); executor.shutdown(); errorReportLatch.await(); - return process.waitFor(); + int exitCode = process.waitFor(); + if (exitCode != 0) { + return exitCode; + } + + if (objcopyExists()) { + if (debugEnabled) { + splitDebugSymbols(nativeImageName); + } else { + // Strip debug symbols regardless, because the underlying JDK might contain them + objcopy("--strip-debug", nativeImageName); + } + } else { + log.warn("objcopy executable not found in PATH. Debug symbols will not be separated from executable."); + log.warn("That will result in a larger native image with debug symbols embedded in it."); + } + return 0; } finally { postBuild(); } } + private void splitDebugSymbols(String executable) { + String symbols = String.format("%s.debug", executable); + objcopy("--only-keep-debug", executable, symbols); + objcopy(String.format("--add-gnu-debuglink=%s", symbols), executable); + } + protected abstract String[] getGraalVMVersionCommand(List args); protected abstract String[] getBuildCommand(List args); + protected boolean objcopyExists() { + return true; + } + + protected abstract void objcopy(String... args); + protected void preBuild(List buildArgs) throws IOException, InterruptedException { } @@ -81,7 +110,7 @@ protected void postBuild() throws InterruptedException, IOException { * If {@code null} the failure is ignored, but logged. * @param workingDirectory The directory in which to run the command */ - void runCommand(String[] command, String errorMsg, File workingDirectory) { + static void runCommand(String[] command, String errorMsg, File workingDirectory) { log.info(String.join(" ", command).replace("$", "\\$")); Process process = null; try { diff --git a/core/deployment/src/main/java/io/quarkus/deployment/pkg/steps/NativeImageBuildStep.java b/core/deployment/src/main/java/io/quarkus/deployment/pkg/steps/NativeImageBuildStep.java index b5eaa22e5a9c1..dddbb78fa01ca 100644 --- a/core/deployment/src/main/java/io/quarkus/deployment/pkg/steps/NativeImageBuildStep.java +++ b/core/deployment/src/main/java/io/quarkus/deployment/pkg/steps/NativeImageBuildStep.java @@ -10,7 +10,6 @@ import java.nio.file.Paths; import java.nio.file.StandardCopyOption; import java.util.ArrayList; -import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.List; @@ -184,7 +183,8 @@ public NativeImageBuildItem build(NativeConfig nativeConfig, NativeImageSourceJa List nativeImageArgs = commandAndExecutable.args; - int exitCode = buildRunner.build(nativeImageArgs, outputDir, processInheritIODisabled.isPresent()); + int exitCode = buildRunner.build(nativeImageArgs, nativeImageName, outputDir, nativeConfig.debug.enabled, + processInheritIODisabled.isPresent()); if (exitCode != 0) { throw imageGenerationFailed(exitCode, nativeImageArgs); } @@ -193,6 +193,11 @@ public NativeImageBuildItem build(NativeConfig nativeConfig, NativeImageSourceJa IoUtils.copy(generatedExecutablePath, finalExecutablePath); Files.delete(generatedExecutablePath); if (nativeConfig.debug.enabled) { + final String symbolsName = String.format("%s.debug", nativeImageName); + Path generatedSymbols = outputDir.resolve(symbolsName); + Path finalSymbolsPath = outputTargetBuildItem.getOutputDirectory().resolve(symbolsName); + IoUtils.copy(generatedSymbols, finalSymbolsPath); + Files.delete(generatedSymbols); final String sources = "sources"; final Path generatedSources = outputDir.resolve(sources); final Path finalSources = outputTargetBuildItem.getOutputDirectory().resolve(sources); @@ -201,17 +206,6 @@ public NativeImageBuildItem build(NativeConfig nativeConfig, NativeImageSourceJa } System.setProperty("native.image.path", finalExecutablePath.toAbsolutePath().toString()); - if (objcopyExists()) { - if (nativeConfig.debug.enabled) { - splitDebugSymbols(finalExecutablePath); - } - // Strip debug symbols regardless, because the underlying JDK might contain them - objcopy("--strip-debug", finalExecutablePath.toString()); - } else { - log.warn("objcopy executable not found in PATH. Debug symbols will not be separated from executable."); - log.warn("That will result in a larger native image with debug symbols embedded in it."); - } - return new NativeImageBuildItem(finalExecutablePath, new NativeImageBuildItem.GraalVMVersion(graalVMVersion.fullVersion, graalVMVersion.major, graalVMVersion.minor, @@ -246,7 +240,7 @@ public static boolean isContainerBuild(NativeConfig nativeConfig) { private static NativeImageBuildRunner getNativeImageBuildRunner(NativeConfig nativeConfig, Path outputDir, String resultingExecutableName) { if (!isContainerBuild(nativeConfig)) { - NativeImageBuildLocalRunner localRunner = getNativeImageBuildLocalRunner(nativeConfig); + NativeImageBuildLocalRunner localRunner = getNativeImageBuildLocalRunner(nativeConfig, outputDir.toFile()); if (localRunner != null) { return localRunner; } @@ -372,12 +366,12 @@ private void checkGraalVMVersion(GraalVM.Version version) { } } - private static NativeImageBuildLocalRunner getNativeImageBuildLocalRunner(NativeConfig nativeConfig) { + private static NativeImageBuildLocalRunner getNativeImageBuildLocalRunner(NativeConfig nativeConfig, File outputDir) { String executableName = getNativeImageExecutableName(); if (nativeConfig.graalvmHome.isPresent()) { File file = Paths.get(nativeConfig.graalvmHome.get(), "bin", executableName).toFile(); if (file.exists()) { - return new NativeImageBuildLocalRunner(file.getAbsolutePath()); + return new NativeImageBuildLocalRunner(file.getAbsolutePath(), outputDir); } } @@ -399,7 +393,7 @@ private static NativeImageBuildLocalRunner getNativeImageBuildLocalRunner(Native if (javaHome != null) { File file = new File(javaHome, "bin/" + executableName); if (file.exists()) { - return new NativeImageBuildLocalRunner(file.getAbsolutePath()); + return new NativeImageBuildLocalRunner(file.getAbsolutePath(), outputDir); } } @@ -412,7 +406,7 @@ private static NativeImageBuildLocalRunner getNativeImageBuildLocalRunner(Native if (dir.isDirectory()) { File file = new File(dir, executableName); if (file.exists()) { - return new NativeImageBuildLocalRunner(file.getAbsolutePath()); + return new NativeImageBuildLocalRunner(file.getAbsolutePath(), outputDir); } } } @@ -446,51 +440,6 @@ private static String testGCCArgument(String argument) { return ""; } - private boolean objcopyExists() { - // System path - String systemPath = System.getenv(PATH); - if (systemPath != null) { - String[] pathDirs = systemPath.split(File.pathSeparator); - for (String pathDir : pathDirs) { - File dir = new File(pathDir); - if (dir.isDirectory()) { - File file = new File(dir, "objcopy"); - if (file.exists()) { - return true; - } - } - } - } - - return false; - } - - private void splitDebugSymbols(Path executable) { - Path symbols = Paths.get(String.format("%s.debug", executable.toString())); - objcopy("--only-keep-debug", executable.toString(), symbols.toString()); - objcopy(String.format("--add-gnu-debuglink=%s", symbols.toString()), executable.toString()); - } - - private static void objcopy(String... args) { - final List command = new ArrayList<>(args.length + 1); - command.add("objcopy"); - command.addAll(Arrays.asList(args)); - if (log.isDebugEnabled()) { - log.debugf("Execute %s", String.join(" ", command)); - } - Process process = null; - try { - process = new ProcessBuilder(command).start(); - process.waitFor(); - } catch (IOException | InterruptedException e) { - throw new RuntimeException("Unable to invoke objcopy", e); - } finally { - if (process != null) { - process.destroy(); - } - } - } - private static class NativeImageInvokerInfo { private final List args; From 36ec89402a1a359b9a02337f05aa3c7077d51dea Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Thu, 1 Apr 2021 14:48:56 +0200 Subject: [PATCH 4/5] Fix confusion between native image name and executable name --- .../NativeImageBuildRemoteContainerRunner.java | 5 ++++- .../pkg/steps/NativeImageBuildRunner.java | 16 ++++++++-------- .../pkg/steps/NativeImageBuildStep.java | 12 +++++++----- 3 files changed, 19 insertions(+), 14 deletions(-) diff --git a/core/deployment/src/main/java/io/quarkus/deployment/pkg/steps/NativeImageBuildRemoteContainerRunner.java b/core/deployment/src/main/java/io/quarkus/deployment/pkg/steps/NativeImageBuildRemoteContainerRunner.java index 393c6a378ed06..94aa3dc1cc492 100644 --- a/core/deployment/src/main/java/io/quarkus/deployment/pkg/steps/NativeImageBuildRemoteContainerRunner.java +++ b/core/deployment/src/main/java/io/quarkus/deployment/pkg/steps/NativeImageBuildRemoteContainerRunner.java @@ -17,11 +17,14 @@ public class NativeImageBuildRemoteContainerRunner extends NativeImageBuildConta private static final Logger log = Logger.getLogger(NativeImageBuildRemoteContainerRunner.class); private static final String CONTAINER_BUILD_VOLUME_NAME = "quarkus-native-builder-image-project-volume"; + private final String nativeImageName; private final String resultingExecutableName; private String containerId; - public NativeImageBuildRemoteContainerRunner(NativeConfig nativeConfig, Path outputDir, String resultingExecutableName) { + public NativeImageBuildRemoteContainerRunner(NativeConfig nativeConfig, Path outputDir, + String nativeImageName, String resultingExecutableName) { super(nativeConfig, outputDir); + this.nativeImageName = nativeImageName; this.resultingExecutableName = resultingExecutableName; } diff --git a/core/deployment/src/main/java/io/quarkus/deployment/pkg/steps/NativeImageBuildRunner.java b/core/deployment/src/main/java/io/quarkus/deployment/pkg/steps/NativeImageBuildRunner.java index 07f08ac524cb7..6c06430803489 100644 --- a/core/deployment/src/main/java/io/quarkus/deployment/pkg/steps/NativeImageBuildRunner.java +++ b/core/deployment/src/main/java/io/quarkus/deployment/pkg/steps/NativeImageBuildRunner.java @@ -42,8 +42,8 @@ public GraalVM.Version getGraalVMVersion() { public void setup(boolean processInheritIODisabled) { } - public int build(List args, String nativeImageName, Path outputDir, boolean debugEnabled, - boolean processInheritIODisabled) + public int build(List args, String nativeImageName, String resultingExecutableName, Path outputDir, + boolean debugEnabled, boolean processInheritIODisabled) throws InterruptedException, IOException { preBuild(args); try { @@ -65,10 +65,10 @@ public int build(List args, String nativeImageName, Path outputDir, bool if (objcopyExists()) { if (debugEnabled) { - splitDebugSymbols(nativeImageName); + splitDebugSymbols(nativeImageName, resultingExecutableName); } else { // Strip debug symbols regardless, because the underlying JDK might contain them - objcopy("--strip-debug", nativeImageName); + objcopy("--strip-debug", resultingExecutableName); } } else { log.warn("objcopy executable not found in PATH. Debug symbols will not be separated from executable."); @@ -80,10 +80,10 @@ public int build(List args, String nativeImageName, Path outputDir, bool } } - private void splitDebugSymbols(String executable) { - String symbols = String.format("%s.debug", executable); - objcopy("--only-keep-debug", executable, symbols); - objcopy(String.format("--add-gnu-debuglink=%s", symbols), executable); + private void splitDebugSymbols(String nativeImageName, String resultingExecutableName) { + String symbols = String.format("%s.debug", nativeImageName); + objcopy("--only-keep-debug", resultingExecutableName, symbols); + objcopy(String.format("--add-gnu-debuglink=%s", symbols), resultingExecutableName); } protected abstract String[] getGraalVMVersionCommand(List args); diff --git a/core/deployment/src/main/java/io/quarkus/deployment/pkg/steps/NativeImageBuildStep.java b/core/deployment/src/main/java/io/quarkus/deployment/pkg/steps/NativeImageBuildStep.java index dddbb78fa01ca..7d430f638d3a4 100644 --- a/core/deployment/src/main/java/io/quarkus/deployment/pkg/steps/NativeImageBuildStep.java +++ b/core/deployment/src/main/java/io/quarkus/deployment/pkg/steps/NativeImageBuildStep.java @@ -150,7 +150,8 @@ public NativeImageBuildItem build(NativeConfig nativeConfig, NativeImageSourceJa String nativeImageName = getNativeImageName(outputTargetBuildItem, packageConfig); String resultingExecutableName = getResultingExecutableName(nativeImageName, isContainerBuild); - NativeImageBuildRunner buildRunner = getNativeImageBuildRunner(nativeConfig, outputDir, resultingExecutableName); + NativeImageBuildRunner buildRunner = getNativeImageBuildRunner(nativeConfig, outputDir, + nativeImageName, resultingExecutableName); buildRunner.setup(processInheritIODisabled.isPresent()); final GraalVM.Version graalVMVersion = buildRunner.getGraalVMVersion(); @@ -183,8 +184,8 @@ public NativeImageBuildItem build(NativeConfig nativeConfig, NativeImageSourceJa List nativeImageArgs = commandAndExecutable.args; - int exitCode = buildRunner.build(nativeImageArgs, nativeImageName, outputDir, nativeConfig.debug.enabled, - processInheritIODisabled.isPresent()); + int exitCode = buildRunner.build(nativeImageArgs, nativeImageName, resultingExecutableName, outputDir, + nativeConfig.debug.enabled, processInheritIODisabled.isPresent()); if (exitCode != 0) { throw imageGenerationFailed(exitCode, nativeImageArgs); } @@ -238,7 +239,7 @@ public static boolean isContainerBuild(NativeConfig nativeConfig) { } private static NativeImageBuildRunner getNativeImageBuildRunner(NativeConfig nativeConfig, Path outputDir, - String resultingExecutableName) { + String nativeImageName, String resultingExecutableName) { if (!isContainerBuild(nativeConfig)) { NativeImageBuildLocalRunner localRunner = getNativeImageBuildLocalRunner(nativeConfig, outputDir.toFile()); if (localRunner != null) { @@ -253,7 +254,8 @@ private static NativeImageBuildRunner getNativeImageBuildRunner(NativeConfig nat log.warn(errorMessage + " Attempting to fall back to container build."); } if (nativeConfig.remoteContainerBuild) { - return new NativeImageBuildRemoteContainerRunner(nativeConfig, outputDir, resultingExecutableName); + return new NativeImageBuildRemoteContainerRunner(nativeConfig, outputDir, + nativeImageName, resultingExecutableName); } return new NativeImageBuildLocalContainerRunner(nativeConfig, outputDir); } From 8008cebb7840dacc9ca95b767cf75ba435d07c3d Mon Sep 17 00:00:00 2001 From: Foivos Zakkak Date: Thu, 1 Apr 2021 18:05:12 +0300 Subject: [PATCH 5/5] Add comment to explain the usage of fixed volume name --- .../pkg/steps/NativeImageBuildRemoteContainerRunner.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/core/deployment/src/main/java/io/quarkus/deployment/pkg/steps/NativeImageBuildRemoteContainerRunner.java b/core/deployment/src/main/java/io/quarkus/deployment/pkg/steps/NativeImageBuildRemoteContainerRunner.java index 94aa3dc1cc492..f427ca4c5268b 100644 --- a/core/deployment/src/main/java/io/quarkus/deployment/pkg/steps/NativeImageBuildRemoteContainerRunner.java +++ b/core/deployment/src/main/java/io/quarkus/deployment/pkg/steps/NativeImageBuildRemoteContainerRunner.java @@ -15,6 +15,9 @@ public class NativeImageBuildRemoteContainerRunner extends NativeImageBuildContainerRunner { private static final Logger log = Logger.getLogger(NativeImageBuildRemoteContainerRunner.class); + // Use a predefined volume name and implicitly create the volume with `podman create`, instead of explicitly + // generating a unique volume with `podman volume create`, to work around Podman's 3.0.x + // issue https://github.com/containers/podman/issues/9608 private static final String CONTAINER_BUILD_VOLUME_NAME = "quarkus-native-builder-image-project-volume"; private final String nativeImageName;