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 e966f9a1aca3b..977cb104e0461 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 @@ -198,6 +198,15 @@ public interface NativeConfig { */ Optional containerBuild(); + /** + * Explicit configuration option to generate a native Position Independent Executable (PIE) for Linux. + * If the system supports PIE generation, the default behaviour is to disable it for + * performance reasons. + * However, some systems can only run position-independent executables, + * so this option enables the generation of such native executables. + */ + Optional pie(); + /** * If this build is done using a remote docker daemon. */ 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 25f2ee179e2da..9734fa89d4de3 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 @@ -194,11 +194,15 @@ public NativeImageBuildItem build(NativeConfig nativeConfig, LocalesBuildTimeCon Path outputDir = nativeImageSourceJarBuildItem.getPath().getParent(); final String runnerJarName = runnerJar.getFileName().toString(); - String noPIE = ""; + String pie = ""; boolean isContainerBuild = nativeImageRunner.isContainerBuild(); if (!isContainerBuild && SystemUtils.IS_OS_LINUX) { - noPIE = detectNoPIE(); + if (nativeConfig.pie().isPresent() && nativeConfig.pie().get()) { + pie = detectPIE(); + } else { + pie = detectNoPIE(); + } } String nativeImageName = getNativeImageName(outputTargetBuildItem, packageConfig); @@ -242,7 +246,7 @@ public NativeImageBuildItem build(NativeConfig nativeConfig, LocalesBuildTimeCon .setOutputDir(outputDir) .setRunnerJarName(runnerJarName) .setNativeImageName(nativeImageName) - .setNoPIE(noPIE) + .setPIE(pie) .setGraalVMVersion(graalVMVersion) .setNativeImageFeatures(nativeImageFeatures) .setContainerBuild(isContainerBuild) @@ -522,6 +526,10 @@ private static String detectNoPIE() { return argument.length() == 0 ? testGCCArgument("-nopie") : argument; } + private static String detectPIE() { + return testGCCArgument("-pie"); + } + private static String testGCCArgument(String argument) { try { Process gcc = new ProcessBuilder("cc", "-v", "-E", argument, "-").start(); @@ -562,7 +570,7 @@ static class Builder { private List nativeImageFeatures; private Path outputDir; private String runnerJarName; - private String noPIE = ""; + private String pie = ""; private GraalVM.Version graalVMVersion = null; private String nativeImageName; private boolean classpathIsBroken; @@ -646,8 +654,8 @@ public Builder setRunnerJarName(String runnerJarName) { return this; } - public Builder setNoPIE(String noPIE) { - this.noPIE = noPIE; + public Builder setPIE(String pie) { + this.pie = pie; return this; } @@ -857,8 +865,8 @@ public NativeImageInvokerInfo build() { if (!inlineBeforeAnalysis) { nativeImageArgs.add("-H:-InlineBeforeAnalysis"); } - if (!noPIE.isEmpty()) { - nativeImageArgs.add("-H:NativeLinkerOption=" + noPIE); + if (!pie.isEmpty()) { + nativeImageArgs.add("-H:NativeLinkerOption=" + pie); } if (!nativeConfig.enableIsolates()) { diff --git a/core/deployment/src/test/java/io/quarkus/deployment/pkg/TestNativeConfig.java b/core/deployment/src/test/java/io/quarkus/deployment/pkg/TestNativeConfig.java index e7890ec83c3f6..900acdcef123c 100644 --- a/core/deployment/src/test/java/io/quarkus/deployment/pkg/TestNativeConfig.java +++ b/core/deployment/src/test/java/io/quarkus/deployment/pkg/TestNativeConfig.java @@ -137,6 +137,11 @@ public Optional containerBuild() { return Optional.empty(); } + @Override + public Optional pie() { + return Optional.empty(); + } + @Override public boolean remoteContainerBuild() { return false;