Skip to content

Commit

Permalink
Refactor: Separate container command from native image
Browse files Browse the repository at this point in the history
  • Loading branch information
zakkak committed Jan 22, 2021
1 parent abbc448 commit 7edd5b4
Showing 1 changed file with 82 additions and 56 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -101,16 +101,25 @@ public NativeImageBuildItem build(NativeConfig nativeConfig, NativeImageSourceJa
final String runnerJarName = runnerJar.getFileName().toString();

HashMap<String, String> env = new HashMap<>(System.getenv());
List<String> nativeImage;

String noPIE = "";
List<String> containerCommand = null;
List<String> nativeImage = null;

boolean isContainerBuild = nativeConfig.containerRuntime.isPresent() || nativeConfig.containerBuild;
if (!isContainerBuild && SystemUtils.IS_OS_LINUX) {
noPIE = detectNoPIE();
if (!isContainerBuild) {
nativeImage = getNativeImage(nativeConfig, processInheritIODisabled.isPresent(), outputDir, env);
if (nativeImage == null) {
assert SystemUtils.IS_OS_LINUX;
// If we are on linux we can fallback to the builder image and expect the resulting binary to be able to
// run on the host. Unfortunately the same is not true for other platforms.
log.warn("Cannot find `native-image` in the GRAALVM_HOME, JAVA_HOME and System PATH." +
"Install it using `gu install native-image`. Attempting to fall back to builder image.");
isContainerBuild = true;
}
}
if (isContainerBuild) {
nativeImage = setupContainerBuild(nativeConfig, processInheritIODisabled.isPresent(), outputDir);
}

nativeImage = getNativeImage(nativeConfig, processInheritIODisabled.isPresent(), outputDir, env);
final GraalVM.Version graalVMVersion = GraalVM.Version.ofBinary(nativeImage);

if (graalVMVersion.isDetected()) {
Expand All @@ -119,9 +128,14 @@ public NativeImageBuildItem build(NativeConfig nativeConfig, NativeImageSourceJa
log.error("Unable to get GraalVM version from the native-image binary.");
}

String executableName = outputTargetBuildItem.getBaseName() + packageConfig.runnerSuffix;
String noPIE = "";
if (!isContainerBuild && SystemUtils.IS_OS_LINUX) {
noPIE = detectNoPIE();
}
try {
String executableName = outputTargetBuildItem.getBaseName() + packageConfig.runnerSuffix;
List<String> buildCommand = getBuildCommand(nativeConfig, nativeImageProperties, processInheritIODisabled, outputDir, runnerJarName, nativeImage, noPIE, isContainerBuild, graalVMVersion, executableName);
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(buildCommand).directory(outputDir.toFile());
Expand Down Expand Up @@ -176,7 +190,11 @@ 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 {
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);
Expand Down Expand Up @@ -319,62 +337,55 @@ private List<String> getBuildCommand(NativeConfig nativeConfig, List<NativeImage

private static List<String> getNativeImage(NativeConfig nativeConfig, boolean shouldRedirectIO, Path outputDir,
Map<String, String> env) {
boolean isContainerBuild = nativeConfig.containerRuntime.isPresent() || nativeConfig.containerBuild;
if (!isContainerBuild) {
String imageName = SystemUtils.IS_OS_WINDOWS ? "native-image.cmd" : "native-image";
if (nativeConfig.graalvmHome.isPresent()) {
env.put(GRAALVM_HOME, nativeConfig.graalvmHome.get());
File file = Paths.get(nativeConfig.graalvmHome.get(), "bin", imageName).toFile();
if (file.exists()) {
return Collections.singletonList(file.getAbsolutePath());
}
String imageName = SystemUtils.IS_OS_WINDOWS ? "native-image.cmd" : "native-image";
if (nativeConfig.graalvmHome.isPresent()) {
env.put(GRAALVM_HOME, nativeConfig.graalvmHome.get());
File file = Paths.get(nativeConfig.graalvmHome.get(), "bin", imageName).toFile();
if (file.exists()) {
return Collections.singletonList(file.getAbsolutePath());
}
}
File java = nativeConfig.javaHome;
if (java == null) {
// try system property first - it will be the JAVA_HOME used by the current JVM
String home = System.getProperty(JAVA_HOME_SYS);
if (home == null) {
// No luck, somewhat a odd JVM not enforcing this property
// try with the JAVA_HOME environment variable
home = env.get(JAVA_HOME_ENV);
}
File java = nativeConfig.javaHome;
if (java == null) {
// try system property first - it will be the JAVA_HOME used by the current JVM
String home = System.getProperty(JAVA_HOME_SYS);
if (home == null) {
// No luck, somewhat a odd JVM not enforcing this property
// try with the JAVA_HOME environment variable
home = env.get(JAVA_HOME_ENV);
}

if (home != null) {
java = new File(home);
}
if (home != null) {
java = new File(home);
}
if (java != null) {
File file = new File(java, "bin/" + imageName);
if (file.exists()) {
return Collections.singletonList(file.getAbsolutePath());
}
}
if (java != null) {
File file = new File(java, "bin/" + imageName);
if (file.exists()) {
return Collections.singletonList(file.getAbsolutePath());
}
}

// System path
String systemPath = env.get(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, imageName);
if (file.exists()) {
return Collections.singletonList(file.getAbsolutePath());
}
// System path
String systemPath = env.get(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, imageName);
if (file.exists()) {
return Collections.singletonList(file.getAbsolutePath());
}
}
}
}

if (!SystemUtils.IS_OS_LINUX) {
throw new RuntimeException("Cannot find the `" + imageName + "` in the GRAALVM_HOME, JAVA_HOME and System " +
"PATH. Install it using `gu install native-image`");
}
// If we are on linux we can fallback to the builder image and expect the resulting binary to be able to
// run on the host. Unfortunately the same is not true for other platforms.
log.warn("Cannot find the `" + imageName + "` in the GRAALVM_HOME, JAVA_HOME and System " +
"PATH. Install it using `gu install native-image`. Attempting to fall back to builder image.");
if (!SystemUtils.IS_OS_LINUX) {
throw new RuntimeException("Cannot find the `" + imageName + "` in the GRAALVM_HOME, JAVA_HOME and System " +
"PATH. Install it using `gu install native-image`");
}
return setupContainerBuild(nativeConfig, shouldRedirectIO, outputDir);
return null;
}

public static List<String> setupContainerBuild(NativeConfig nativeConfig,
Expand Down Expand Up @@ -742,7 +753,22 @@ List<RuntimeReinitializedClassBuildItem> graalVmWorkaround(NativeConfig nativeCo
Optional<ProcessInheritIODisabled> processInheritIODisabled) {
Path outputDir = Paths.get("."); // The path is not important for getting the version
HashMap<String, String> env = new HashMap<>(System.getenv());
List<String> nativeImage = getNativeImage(nativeConfig, processInheritIODisabled.isPresent(), outputDir, env);
boolean isContainerBuild = nativeConfig.containerRuntime.isPresent() || nativeConfig.containerBuild;
List<String> nativeImage = null;
if (!isContainerBuild) {
nativeImage = getNativeImage(nativeConfig, processInheritIODisabled.isPresent(), outputDir, env);
if (nativeImage == null) {
assert SystemUtils.IS_OS_LINUX;
// If we are on linux we can fallback to the builder image and expect the resulting binary to be able to
// run on the host. Unfortunately the same is not true for other platforms.
log.warn("Cannot find `native-image` in the GRAALVM_HOME, JAVA_HOME and System PATH." +
"Install it using `gu install native-image`. Attempting to fall back to builder image.");
isContainerBuild = true;
}
}
if (isContainerBuild) {
nativeImage = setupContainerBuild(nativeConfig, processInheritIODisabled.isPresent(), outputDir);
}
GraalVM.Version version = GraalVM.Version.ofBinary(nativeImage);
if (version.isNewerThan(GraalVM.Version.VERSION_20_2)) {
// https://github.com/oracle/graal/issues/2841
Expand Down

0 comments on commit 7edd5b4

Please sign in to comment.