Skip to content

Commit

Permalink
Improve toolchain selection diagnostics
Browse files Browse the repository at this point in the history
  • Loading branch information
melix committed Oct 13, 2022
1 parent a3b5f3f commit 6c7f92a
Show file tree
Hide file tree
Showing 5 changed files with 107 additions and 16 deletions.
4 changes: 4 additions & 0 deletions docs/src/docs/asciidoc/index.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@ If you are using alternative build systems, see <<alternative-build-systems.adoc
* Ship the metadata repository as an artifact alongside the plugin
* Add ability to collect GraalVM metadata of dependencies to a custom location

==== Gradle plugin

* Improved diagnostics to help users figure out what GraalVM toolchain was selected

=== Release 0.9.14

==== Gradle plugin
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,9 @@
*/
@SuppressWarnings("unused")
public class GradleUtils {
private static final GradleVersion GRADLE_68 = GradleVersion.version("6.8");
private static final GradleVersion GRADLE_7 = GradleVersion.version("7.0");
private static final GradleVersion GRADLE_71 = GradleVersion.version("7.1");

public static SourceSet findSourceSet(Project project, String sourceSetName) {
SourceSetContainer sourceSetContainer = getJavaPluginConvention(project).getSourceSets();
Expand All @@ -72,6 +74,14 @@ public static boolean isAtLeastGradle7() {
return GradleVersion.current().compareTo(GRADLE_7) >= 0;
}

public static boolean isAtLeastGradle6dot8() {
return GradleVersion.current().compareTo(GRADLE_68) >= 0;
}

public static boolean isAtLeastGradle7dot1() {
return GradleVersion.current().compareTo(GRADLE_71) >= 0;
}

public static Configuration findConfiguration(Project project, String name) {
return project.getConfigurations().getByName(name);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,38 +50,45 @@
import org.gradle.process.ExecResult;

import java.io.File;
import java.io.IOException;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import static org.graalvm.buildtools.utils.SharedConstants.GU_EXE;
import static org.graalvm.buildtools.utils.SharedConstants.NATIVE_IMAGE_EXE;

public class NativeImageExecutableLocator {

public static Provider<String> graalvmHomeProvider(ProviderFactory providers) {
return providers.environmentVariable("GRAALVM_HOME")
.forUseAtConfigurationTime()
.orElse(providers.environmentVariable("JAVA_HOME").forUseAtConfigurationTime());
return graalvmHomeProvider(providers, new Diagnostics());
}

public static Provider<String> graalvmHomeProvider(ProviderFactory providers, Diagnostics diagnostics) {
return diagnostics.fromEnvVar("GRAALVM_HOME", providers)
.orElse(diagnostics.fromEnvVar("JAVA_HOME", providers));
}

public static File findNativeImageExecutable(Property<JavaLauncher> javaLauncher,
Provider<Boolean> disableToolchainDetection,
Provider<String> graalvmHomeProvider,
ExecOperations execOperations,
GraalVMLogger logger) {
GraalVMLogger logger,
Diagnostics diagnostics) {
File executablePath = null;
if (disableToolchainDetection.get() || !javaLauncher.isPresent()) {
boolean toolchainDetectionIsDisabled = Boolean.TRUE.equals(disableToolchainDetection.get());
if (toolchainDetectionIsDisabled || !javaLauncher.isPresent()) {
if (graalvmHomeProvider.isPresent()) {
diagnostics.disableToolchainDetection();
String graalvmHome = graalvmHomeProvider.get();
logger.lifecycle("Toolchain detection is disabled, will use GraalVM from {}.", graalvmHome);
executablePath = Paths.get(graalvmHome).resolve("bin/" + NATIVE_IMAGE_EXE).toFile();
}
}
if (executablePath == null) {
JavaInstallationMetadata metadata = javaLauncher.get().getMetadata();
diagnostics.withToolchain(metadata);
executablePath = metadata.getInstallationPath().file("bin/" + NATIVE_IMAGE_EXE).getAsFile();
if (!executablePath.exists() && graalvmHomeProvider.isPresent()) {
executablePath = Paths.get(graalvmHomeProvider.get()).resolve("bin").resolve(NATIVE_IMAGE_EXE).toFile();
}
}

try {
Expand All @@ -99,12 +106,77 @@ public static File findNativeImageExecutable(Property<JavaLauncher> javaLauncher
if (res.getExitValue() != 0) {
throw new GradleException("Native Image executable wasn't found, and '" + GU_EXE + "' tool failed to install it.");
}
diagnostics.withGuInstall();
}
} catch (GradleException e) {
throw new GradleException("Determining GraalVM installation failed with message: " + e.getMessage() + "\n\n"
+ "Make sure to declare the GRAALVM_HOME environment variable or install GraalVM with " +
"native-image in a standard location recognized by Gradle Java toolchain support");
+ "Make sure to declare the GRAALVM_HOME environment variable or install GraalVM with " +
"native-image in a standard location recognized by Gradle Java toolchain support");
}
diagnostics.withExecutablePath(executablePath);
return executablePath;
}

public static final class Diagnostics {
private boolean toolchainDetectionDisabled;
private String envVar;
private boolean guInstall;
private File executablePath;
private JavaInstallationMetadata toolchain;

public Provider<String> fromEnvVar(String envVar, ProviderFactory factory) {
return factory.environmentVariable(envVar)
// required for older Gradle versions support
.forUseAtConfigurationTime()
.map(ConfigurationCacheSupport.serializableTransformerOf(value -> {
this.envVar = envVar;
return value;
}));
}

public void withToolchain(JavaInstallationMetadata toolchain) {
this.toolchain = toolchain;
this.envVar = null;
}

public void disableToolchainDetection() {
toolchainDetectionDisabled = true;
}

public void withGuInstall() {
guInstall = true;
}

public void withExecutablePath(File path) {
executablePath = path;
}
public List<String> getDiagnostics() {
List<String> diags = new ArrayList<>();
diags.add("GraalVM Toolchain detection is " + (toolchainDetectionDisabled ? "disabled" : "enabled"));
if (envVar != null) {
diags.add("GraalVM location read from environment variable: " + envVar);
}
if (guInstall) {
diags.add("Native Image executable was installed using 'gu' tool");
}
if (toolchain != null) {
diags.add("GraalVM uses toolchain detection. Selected:");
diags.add(" - language version: " + toolchain.getLanguageVersion());
if (GradleUtils.isAtLeastGradle6dot8()) {
diags.add(" - vendor: " + toolchain.getVendor());
if (GradleUtils.isAtLeastGradle7dot1()) {
diags.add(" - runtime version: " + toolchain.getJavaRuntimeVersion());
}
}
}
if (executablePath != null) {
try {
diags.add("Native Image executable path: " + executablePath.getCanonicalPath());
} catch (IOException e) {
diags.add("Native Image executable path: " + executablePath.getAbsolutePath());
}
}
return Collections.unmodifiableList(diags);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@
*/
public abstract class BuildNativeImageTask extends DefaultTask {
private final Provider<String> graalvmHomeProvider;
private final NativeImageExecutableLocator.Diagnostics diagnostics;

@Nested
public abstract Property<NativeImageOptions> getOptions();
Expand Down Expand Up @@ -154,7 +155,8 @@ public BuildNativeImageTask() {
setGroup(JavaBasePlugin.VERIFICATION_GROUP);
getOutputDirectory().convention(outputDir);
ProviderFactory providers = getProject().getProviders();
this.graalvmHomeProvider = graalvmHomeProvider(providers);
this.diagnostics = new NativeImageExecutableLocator.Diagnostics();
this.graalvmHomeProvider = graalvmHomeProvider(providers, diagnostics);
getDisableToolchainDetection().convention(false);
}

Expand Down Expand Up @@ -191,9 +193,11 @@ public void exec() {
getDisableToolchainDetection(),
getGraalVMHome(),
getExecOperations(),
logger);

logger.lifecycle("Using executable path: " + executablePath);
logger,
diagnostics);
for (String diagnostic : diagnostics.getDiagnostics()) {
logger.lifecycle(diagnostic);
}
String executable = executablePath.getAbsolutePath();
File outputDir = getOutputDirectory().getAsFile().get();
if (outputDir.isDirectory() || outputDir.mkdirs()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@

import org.graalvm.buildtools.agent.AgentMode;
import org.graalvm.buildtools.gradle.internal.GraalVMLogger;
import org.graalvm.buildtools.gradle.internal.NativeImageExecutableLocator;
import org.graalvm.buildtools.utils.NativeImageUtils;
import org.gradle.api.Action;
import org.gradle.api.Task;
Expand Down Expand Up @@ -100,7 +101,7 @@ private static boolean isConfigDir(String dir) {
@Override
public void execute(Task task) {
if (isMergingEnabled.get()) {
File nativeImage = findNativeImageExecutable(noLauncherProperty, disableToolchainDetection, graalvmHomeProvider, execOperations, GraalVMLogger.of(task.getLogger()));
File nativeImage = findNativeImageExecutable(noLauncherProperty, disableToolchainDetection, graalvmHomeProvider, execOperations, GraalVMLogger.of(task.getLogger()), new NativeImageExecutableLocator.Diagnostics());
File workingDir = nativeImage.getParentFile();
File launcher = new File(workingDir, nativeImageConfigureFileName());
if (!launcher.exists()) {
Expand Down

0 comments on commit 6c7f92a

Please sign in to comment.