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 7717fd5d137e1..d7faf57b3842f 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 @@ -229,6 +229,17 @@ public class NativeConfig { @ConfigItem public boolean reportErrorsAtRuntime; + /** + * Don't build a native image if it already exists. + * + * This is useful if you have already built an image and you want to use Quarkus to deploy it somewhere. + * + * Note that this is not able to detect if the existing image is outdated, if you have modified source + * or config and want a new image you must not use this flag. + */ + @ConfigItem(defaultValue = "false") + public boolean reuseExisting; + /** * Build time configuration options for resources inclusion in the native executable. */ 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 2a60fbdc8d2bd..f2d0401a785a2 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 @@ -149,6 +149,8 @@ public NativeImageBuildItem build(NativeConfig nativeConfig, NativeImageSourceJa String nativeImageName = getNativeImageName(outputTargetBuildItem, packageConfig); String resultingExecutableName = getResultingExecutableName(nativeImageName, isContainerBuild); + Path generatedExecutablePath = outputDir.resolve(resultingExecutableName); + Path finalExecutablePath = outputTargetBuildItem.getOutputDirectory().resolve(resultingExecutableName); NativeImageBuildRunner buildRunner = getNativeImageBuildRunner(nativeConfig, outputDir, nativeImageName, resultingExecutableName); @@ -160,6 +162,14 @@ public NativeImageBuildItem build(NativeConfig nativeConfig, NativeImageSourceJa } else { log.error("Unable to get GraalVM version from the native-image binary."); } + if (nativeConfig.reuseExisting) { + if (Files.exists(finalExecutablePath)) { + return new NativeImageBuildItem(finalExecutablePath, + new NativeImageBuildItem.GraalVMVersion(graalVMVersion.fullVersion, graalVMVersion.major, + graalVMVersion.minor, + graalVMVersion.distribution.name())); + } + } try { if (nativeConfig.cleanupServer) { @@ -189,8 +199,6 @@ public NativeImageBuildItem build(NativeConfig nativeConfig, NativeImageSourceJa if (exitCode != 0) { throw imageGenerationFailed(exitCode, nativeImageArgs); } - Path generatedExecutablePath = outputDir.resolve(resultingExecutableName); - Path finalExecutablePath = outputTargetBuildItem.getOutputDirectory().resolve(resultingExecutableName); IoUtils.copy(generatedExecutablePath, finalExecutablePath); Files.delete(generatedExecutablePath); if (nativeConfig.debug.enabled) { diff --git a/docs/src/main/asciidoc/container-image.adoc b/docs/src/main/asciidoc/container-image.adoc index 6691068a46159..0cfc429603571 100644 --- a/docs/src/main/asciidoc/container-image.adoc +++ b/docs/src/main/asciidoc/container-image.adoc @@ -106,6 +106,8 @@ To build a container image for your project, `quarkus.container-image.build=true ./mvnw clean package -Dquarkus.container-image.build=true ---- +NOTE: If you ever want to build a native container image and already have an existing native image you can set `-Dquarkus.native.reuse-existing=true` and the native image build will not be re-run. + == Pushing To push a container image for your project, `quarkus.container-image.push=true` needs to be set using any of the ways that Quarkus supports.