Skip to content

Commit

Permalink
Refactor: Extract getBuildCommand method
Browse files Browse the repository at this point in the history
  • Loading branch information
zakkak committed Jan 22, 2021
1 parent e711395 commit abbc448
Showing 1 changed file with 145 additions and 141 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -120,148 +120,11 @@ public NativeImageBuildItem build(NativeConfig nativeConfig, NativeImageSourceJa
}

try {
List<String> command = new ArrayList<>(nativeImage);
if (nativeConfig.cleanupServer && !graalVMVersion.isMandrel()) {
List<String> cleanup = new ArrayList<>(nativeImage);
cleanup.add("--server-shutdown");
final ProcessBuilder pb = new ProcessBuilder(cleanup.toArray(new String[0]));
pb.directory(outputDir.toFile());
final Process process = ProcessUtil.launchProcess(pb, processInheritIODisabled.isPresent());
process.waitFor();
}
boolean enableSslNative = false;
for (NativeImageSystemPropertyBuildItem prop : nativeImageProperties) {
//todo: this should be specific build items
if (prop.getKey().equals("quarkus.ssl.native") && prop.getValue() != null) {
enableSslNative = Boolean.parseBoolean(prop.getValue());
} else if (prop.getKey().equals("quarkus.jni.enable") && prop.getValue().equals("false")) {
log.warn("Your application is setting the deprecated 'quarkus.jni.enable' configuration key to false."
+ " Please consider removing this configuration key as it is ignored (JNI is always enabled) and it"
+ " will be removed in a future Quarkus version.");
} else if (prop.getKey().equals("quarkus.native.enable-all-security-services") && prop.getValue() != null) {
nativeConfig.enableAllSecurityServices |= Boolean.parseBoolean(prop.getValue());
} else if (prop.getKey().equals("quarkus.native.enable-all-charsets") && prop.getValue() != null) {
nativeConfig.addAllCharsets |= Boolean.parseBoolean(prop.getValue());
} else {
// todo maybe just -D is better than -J-D in this case
if (prop.getValue() == null) {
command.add("-J-D" + prop.getKey());
} else {
command.add("-J-D" + prop.getKey() + "=" + prop.getValue());
}
}
}
command.add("-J-Duser.language=" + System.getProperty("user.language"));
// Native image runtime uses the host's (i.e. build time) value of file.encoding
// system property. We intentionally default this to UTF-8 to avoid platform specific
// defaults to be picked up which can then result in inconsistent behaviour in the
// generated native application
command.add("-J-Dfile.encoding=UTF-8");

if (enableSslNative) {
nativeConfig.enableHttpsUrlHandler = true;
nativeConfig.enableAllSecurityServices = true;
}

handleAdditionalProperties(nativeConfig, command, isContainerBuild, outputDir);
command.add("--initialize-at-build-time=");
command.add(
"-H:InitialCollectionPolicy=com.oracle.svm.core.genscavenge.CollectionPolicy$BySpaceAndTime"); //the default collection policy results in full GC's 50% of the time
command.add("-H:+JNI");
command.add("-H:+AllowFoldMethods");
command.add("-jar");
command.add(runnerJarName);

if (nativeConfig.enableFallbackImages) {
command.add("-H:FallbackThreshold=5");
} else {
//Default: be strict as those fallback images aren't very useful
//and tend to cover up real problems.
command.add("-H:FallbackThreshold=0");
}

if (nativeConfig.reportErrorsAtRuntime) {
command.add("-H:+ReportUnsupportedElementsAtRuntime");
}
if (nativeConfig.reportExceptionStackTraces) {
command.add("-H:+ReportExceptionStackTraces");
}
if (nativeConfig.debug.enabled) {
if (graalVMVersion.isMandrel() || graalVMVersion.isNewerThan(GraalVM.Version.VERSION_20_1)) {
command.add("-g");
command.add("-H:DebugInfoSourceSearchPath=" + APP_SOURCES);
}
}
if (nativeConfig.debugBuildProcess) {
command.add("-J-Xrunjdwp:transport=dt_socket,address=" + DEBUG_BUILD_PROCESS_PORT + ",server=y,suspend=y");
}
if (nativeConfig.enableReports) {
command.add("-H:+PrintAnalysisCallTree");
}
if (nativeConfig.dumpProxies) {
command.add("-Dsun.misc.ProxyGenerator.saveGeneratedFiles=true");
if (nativeConfig.enableServer) {
log.warn(
"Options dumpProxies and enableServer are both enabled: this will get the proxies dumped in an unknown external working directory");
}
}
if (nativeConfig.nativeImageXmx.isPresent()) {
command.add("-J-Xmx" + nativeConfig.nativeImageXmx.get());
}
List<String> protocols = new ArrayList<>(2);
if (nativeConfig.enableHttpUrlHandler) {
protocols.add("http");
}
if (nativeConfig.enableHttpsUrlHandler) {
protocols.add("https");
}
if (nativeConfig.addAllCharsets) {
command.add("-H:+AddAllCharsets");
} else {
command.add("-H:-AddAllCharsets");
}
if (!protocols.isEmpty()) {
command.add("-H:EnableURLProtocols=" + String.join(",", protocols));
}
if (nativeConfig.enableAllSecurityServices) {
command.add("--enable-all-security-services");
}
if (!noPIE.isEmpty()) {
command.add("-H:NativeLinkerOption=" + noPIE);
}

if (!nativeConfig.enableIsolates) {
command.add("-H:-SpawnIsolates");
}
if (!nativeConfig.enableJni) {
log.warn("Your application is setting the deprecated 'quarkus.native.enable-jni' configuration key to false."
+ " Please consider removing this configuration key as it is ignored (JNI is always enabled) and it"
+ " will be removed in a future Quarkus version.");
}
if (!nativeConfig.enableServer && !SystemUtils.IS_OS_WINDOWS && !graalVMVersion.isMandrel()) {
command.add("--no-server");
}
if (nativeConfig.enableVmInspection) {
command.add("-H:+AllowVMInspection");
}
if (nativeConfig.autoServiceLoaderRegistration) {
command.add("-H:+UseServiceLoaderFeature");
//When enabling, at least print what exactly is being added:
command.add("-H:+TraceServiceLoaderFeature");
} else {
command.add("-H:-UseServiceLoaderFeature");
}
if (nativeConfig.fullStackTraces) {
command.add("-H:+StackTrace");
} else {
command.add("-H:-StackTrace");
}
String executableName = outputTargetBuildItem.getBaseName() + packageConfig.runnerSuffix;
command.add(executableName);

log.info(String.join(" ", command).replace("$", "\\$"));
List<String> buildCommand = getBuildCommand(nativeConfig, nativeImageProperties, processInheritIODisabled, outputDir, runnerJarName, nativeImage, noPIE, isContainerBuild, graalVMVersion, executableName);
log.info(String.join(" ", buildCommand).replace("$", "\\$"));
CountDownLatch errorReportLatch = new CountDownLatch(1);
final ProcessBuilder processBuilder = new ProcessBuilder(command).directory(outputDir.toFile());
final ProcessBuilder processBuilder = new ProcessBuilder(buildCommand).directory(outputDir.toFile());
final Process process = ProcessUtil.launchProcessStreamStdOut(processBuilder, processInheritIODisabled.isPresent());
ExecutorService executor = Executors.newSingleThreadExecutor();
executor.submit(new ErrorReplacingProcessReader(process.getErrorStream(), outputDir.resolve("reports").toFile(),
Expand All @@ -270,7 +133,7 @@ public NativeImageBuildItem build(NativeConfig nativeConfig, NativeImageSourceJa
errorReportLatch.await();
int exitCode = process.waitFor();
if (exitCode != 0) {
throw imageGenerationFailed(exitCode, command);
throw imageGenerationFailed(exitCode, buildCommand);
}
if (SystemUtils.IS_OS_WINDOWS && !(isContainerBuild)) {
//once image is generated it gets added .exe on Windows
Expand Down Expand Up @@ -313,6 +176,147 @@ public NativeImageBuildItem build(NativeConfig nativeConfig, NativeImageSourceJa
}
}

private List<String> getBuildCommand(NativeConfig nativeConfig, List<NativeImageSystemPropertyBuildItem> nativeImageProperties, Optional<ProcessInheritIODisabled> processInheritIODisabled, Path outputDir, String runnerJarName, List<String> nativeImage, String noPIE, boolean isContainerBuild, GraalVM.Version graalVMVersion, String executableName) throws IOException, InterruptedException {
List<String> command = new ArrayList<>(nativeImage);
if (nativeConfig.cleanupServer && !graalVMVersion.isMandrel()) {
List<String> cleanup = new ArrayList<>(nativeImage);
cleanup.add("--server-shutdown");
final ProcessBuilder pb = new ProcessBuilder(cleanup.toArray(new String[0]));
pb.directory(outputDir.toFile());
final Process process = ProcessUtil.launchProcess(pb, processInheritIODisabled.isPresent());
process.waitFor();
}
boolean enableSslNative = false;
for (NativeImageSystemPropertyBuildItem prop : nativeImageProperties) {
//todo: this should be specific build items
if (prop.getKey().equals("quarkus.ssl.native") && prop.getValue() != null) {
enableSslNative = Boolean.parseBoolean(prop.getValue());
} else if (prop.getKey().equals("quarkus.jni.enable") && prop.getValue().equals("false")) {
log.warn("Your application is setting the deprecated 'quarkus.jni.enable' configuration key to false."
+ " Please consider removing this configuration key as it is ignored (JNI is always enabled) and it"
+ " will be removed in a future Quarkus version.");
} else if (prop.getKey().equals("quarkus.native.enable-all-security-services") && prop.getValue() != null) {
nativeConfig.enableAllSecurityServices |= Boolean.parseBoolean(prop.getValue());
} else if (prop.getKey().equals("quarkus.native.enable-all-charsets") && prop.getValue() != null) {
nativeConfig.addAllCharsets |= Boolean.parseBoolean(prop.getValue());
} else {
// todo maybe just -D is better than -J-D in this case
if (prop.getValue() == null) {
command.add("-J-D" + prop.getKey());
} else {
command.add("-J-D" + prop.getKey() + "=" + prop.getValue());
}
}
}
command.add("-J-Duser.language=" + System.getProperty("user.language"));
// Native image runtime uses the host's (i.e. build time) value of file.encoding
// system property. We intentionally default this to UTF-8 to avoid platform specific
// defaults to be picked up which can then result in inconsistent behaviour in the
// generated native application
command.add("-J-Dfile.encoding=UTF-8");

if (enableSslNative) {
nativeConfig.enableHttpsUrlHandler = true;
nativeConfig.enableAllSecurityServices = true;
}

handleAdditionalProperties(nativeConfig, command, isContainerBuild, outputDir);
command.add("--initialize-at-build-time=");
command.add(
"-H:InitialCollectionPolicy=com.oracle.svm.core.genscavenge.CollectionPolicy$BySpaceAndTime"); //the default collection policy results in full GC's 50% of the time
command.add("-H:+JNI");
command.add("-H:+AllowFoldMethods");
command.add("-jar");
command.add(runnerJarName);

if (nativeConfig.enableFallbackImages) {
command.add("-H:FallbackThreshold=5");
} else {
//Default: be strict as those fallback images aren't very useful
//and tend to cover up real problems.
command.add("-H:FallbackThreshold=0");
}

if (nativeConfig.reportErrorsAtRuntime) {
command.add("-H:+ReportUnsupportedElementsAtRuntime");
}
if (nativeConfig.reportExceptionStackTraces) {
command.add("-H:+ReportExceptionStackTraces");
}
if (nativeConfig.debug.enabled) {
if (graalVMVersion.isMandrel() || graalVMVersion.isNewerThan(GraalVM.Version.VERSION_20_1)) {
command.add("-g");
command.add("-H:DebugInfoSourceSearchPath=" + APP_SOURCES);
}
}
if (nativeConfig.debugBuildProcess) {
command.add("-J-Xrunjdwp:transport=dt_socket,address=" + DEBUG_BUILD_PROCESS_PORT + ",server=y,suspend=y");
}
if (nativeConfig.enableReports) {
command.add("-H:+PrintAnalysisCallTree");
}
if (nativeConfig.dumpProxies) {
command.add("-Dsun.misc.ProxyGenerator.saveGeneratedFiles=true");
if (nativeConfig.enableServer) {
log.warn(
"Options dumpProxies and enableServer are both enabled: this will get the proxies dumped in an unknown external working directory");
}
}
if (nativeConfig.nativeImageXmx.isPresent()) {
command.add("-J-Xmx" + nativeConfig.nativeImageXmx.get());
}
List<String> protocols = new ArrayList<>(2);
if (nativeConfig.enableHttpUrlHandler) {
protocols.add("http");
}
if (nativeConfig.enableHttpsUrlHandler) {
protocols.add("https");
}
if (nativeConfig.addAllCharsets) {
command.add("-H:+AddAllCharsets");
} else {
command.add("-H:-AddAllCharsets");
}
if (!protocols.isEmpty()) {
command.add("-H:EnableURLProtocols=" + String.join(",", protocols));
}
if (nativeConfig.enableAllSecurityServices) {
command.add("--enable-all-security-services");
}
if (!noPIE.isEmpty()) {
command.add("-H:NativeLinkerOption=" + noPIE);
}

if (!nativeConfig.enableIsolates) {
command.add("-H:-SpawnIsolates");
}
if (!nativeConfig.enableJni) {
log.warn("Your application is setting the deprecated 'quarkus.native.enable-jni' configuration key to false."
+ " Please consider removing this configuration key as it is ignored (JNI is always enabled) and it"
+ " will be removed in a future Quarkus version.");
}
if (!nativeConfig.enableServer && !SystemUtils.IS_OS_WINDOWS && !graalVMVersion.isMandrel()) {
command.add("--no-server");
}
if (nativeConfig.enableVmInspection) {
command.add("-H:+AllowVMInspection");
}
if (nativeConfig.autoServiceLoaderRegistration) {
command.add("-H:+UseServiceLoaderFeature");
//When enabling, at least print what exactly is being added:
command.add("-H:+TraceServiceLoaderFeature");
} else {
command.add("-H:-UseServiceLoaderFeature");
}
if (nativeConfig.fullStackTraces) {
command.add("-H:+StackTrace");
} else {
command.add("-H:-StackTrace");
}
command.add(executableName);
return command;
}

private static List<String> getNativeImage(NativeConfig nativeConfig, boolean shouldRedirectIO, Path outputDir,
Map<String, String> env) {
boolean isContainerBuild = nativeConfig.containerRuntime.isPresent() || nativeConfig.containerBuild;
Expand Down

0 comments on commit abbc448

Please sign in to comment.