Skip to content

Commit

Permalink
Disable toolchain detection by default (#420)
Browse files Browse the repository at this point in the history
* Disable toolchain detection by default

With the changes coming in GraalVM regarding versioning, in particular
the fact that the GraalVM version becomes internal and that the
vendor string is changing, toolchain detection will clearly be broken
for all users.

This commit therefore disables toolchain detection by default, and
makes sure to document properly the new behavior.

* Apply suggestions from code review

Co-authored-by: Fabio Niephaus <[email protected]>

---------

Co-authored-by: Fabio Niephaus <[email protected]>
  • Loading branch information
melix and fniephaus committed Apr 4, 2023
1 parent 0ead262 commit 9d4fb49
Show file tree
Hide file tree
Showing 7 changed files with 47 additions and 56 deletions.
72 changes: 30 additions & 42 deletions docs/src/docs/asciidoc/gradle-plugin.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -91,30 +91,13 @@ include::../snippets/gradle/kotlin/settings.gradle.kts[tags=pre-release, indent=

=== Installing GraalVM Native Image tool

The plugin relies on Gradle's https://docs.gradle.org/7.1.1/userguide/toolchains.html[JVM toolchain support], allowing to decorrelate the tool used to run Gradle, the compiler used to build your application, and eventually the SDK used to generate a native image.

In practice, it means that this plugin will try to locate a suitable installation of GraalVM for you, even if you don't run Gradle itself with GraalVM.
For this, it will look into conventional places on your machine, including from installations done by popular tools like https://sdkman.io/[SDKMAN!] or https://github.com/shyiko/jabba[Jabba].

WARNING: Even if you have a GraalVM SDK installed, Gradle will _not_ automatically detect if `native-image` is also installed.
Therefore, you will need to make sure that you have executed `gu install native-image` as indicated in the <<graalvm-setup.adoc#,setup instructions>>.

If Gradle cannot find a GraalVM installation on the machine, it will fail with an error like this:

----
> No compatible toolchains found for request filter: {languageVersion=11, vendor=matching('GraalVM'), implementation=vendor-specific} (auto-detect true, auto-download true)
----

This happens because there's no automatic provisioning of the GraalVM toolchain available yet, so you will have to install it first.
Follow the <<graalvm-setup.adoc#,following instructions>> to install it properly.
By default, the plugin will try to use the `native-image` tool that is bundled with the JDK that is used to run Gradle.
This means you must make sure that you run Gradle with a GraalVM JDK.

Alternatively, you may choose to:

1. <<configuration-toolchains-disabling, Disable toolchain support>>
2. Run Gradle itself with a GraalVM SDK
3. Set up a `GRAALVM_HOME` environment variable pointing to your GraalVM installation

Note that none of the above options is recommended as they are more fragile.
1. Set up a `GRAALVM_HOME` environment variable pointing to your GraalVM installation, in which case the JDK pointed at this location will be used for Native Image builds instead
2. <<configuration-toolchains-enabling, Enable toolchain support to automatically>>

[[configuration]]
== Configuration
Expand All @@ -139,44 +122,49 @@ The main executable is configured by the image named `main`, while the test exec
The link:javadocs/native-gradle-plugin/org/graalvm/buildtools/gradle/dsl/NativeImageOptions.html[NativeImageOptions] allows you to tweak how the native image is going to be built.

[[configuration-toolchains]]
==== Selecting the GraalVM toolchain
=== Using Gradle toolchains

By default, the plugin will select a Java 11 GraalVM toolchain.
If you want to use a different toolchain, for example a GraalVM Community Edition for Java 8, you can configure the toolchain like this:
[[configuration-toolchains-enabling]]
==== Enabling toolchain detection

.Selecting the GraalVM toolchain
[source, groovy, role="multi-language-sample"]
Instead of relying on the JDK which is used to run Gradle, you can use the https://docs.gradle.org/current/userguide/toolchains.html[Gradle toolchain support] to select a specific GraalVM installation.

However, because of limitations in Gradle, the plugin may not be able to properly detect the toolchain.
In particular, this will only work properly if you _only_ have GraalVM JDKs installed on the machine: **Otherwise, Gradle will not be able to reliably detect GraalVM JDKs**, nor detect GraalVM distributions from different vendors.

Should you still want to enable toolchain support, you do it via the `graalvmNative` extension:

.Enabling toolchain detection
[source,groovy,role="multi-language-sample"]
----
include::../snippets/gradle/groovy/build.gradle[tags=select-toolchain]
include::../snippets/gradle/groovy/build.gradle[tags=enabling-toolchain, indent=0]
----

[source,kotlin,role="multi-language-sample"]
[source, kotlin, role="multi-language-sample"]
----
include::../snippets/gradle/kotlin/build.gradle.kts[tags=select-toolchain]
include::../snippets/gradle/kotlin/build.gradle.kts[tags=enabling-toolchain, indent=0]
----

[[configuration-toolchains-disabling]]
===== Disabling toolchain detection
==== Selecting the GraalVM toolchain

Because of limitations in Gradle, the plugin may not be able to properly detect the toolchain.
This is the case if, for example, you want to use GraalVM Enterprise or you want to be able to select a particular version of GraalVM.
By default, the plugin will select a Java 11 GraalVM toolchain using the vendor string `GraalVM`,
which works properly for GraalVM up to version 22.3 included.
More recent versions of GraalVM do not have a specific version and are aligned with the language version they support.

To work around this problem, you can disable toolchain detection:
If you want to use a different toolchain, for example a distribution compatible with Java 20 from Oracle, you can configure the toolchain like this:

.Disabling toolchain detection
[source,groovy,role="multi-language-sample"]
.Selecting the GraalVM toolchain
[source, groovy, role="multi-language-sample"]
----
include::../snippets/gradle/groovy/build.gradle[tags=disabling-toolchain, indent=0]
include::../snippets/gradle/groovy/build.gradle[tags=select-toolchain]
----

[source, kotlin, role="multi-language-sample"]
[source,kotlin,role="multi-language-sample"]
----
include::../snippets/gradle/kotlin/build.gradle.kts[tags=disabling-toolchain, indent=0]
include::../snippets/gradle/kotlin/build.gradle.kts[tags=select-toolchain]
----

If you do this, the plugin will search for 2 environment variables: `GRAALVM_HOME` and `JAVA_HOME` _in that order_.
If one of them is set, it will assume that it points to a valid GraalVM installation and completely bypass toolchain selection.
Therefore, it becomes your responsibility to make sure that the environment variable points to a JDK that is compatible with your build script requirements (in particular, the language version).
Again, be aware that the toolchain detection _cannot_ distinguish between GraalVM JDKs and standard JDKs without Native Image support: if you have both installed on the machine, Gradle may randomly pick one or the other.

[[configuration-options]]
==== Configuration options
Expand Down
1 change: 1 addition & 0 deletions docs/src/docs/asciidoc/index.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ If you are using alternative build systems, see <<alternative-build-systems.adoc
- Bump minimal version of Gradle to 7.4
- Fix compatibility with Gradle's https://docs.gradle.org/8.0.2/userguide/configuration_cache.html#header[configuration cache] (requires Gradle 7.5+)
- Remove use of deprecated Gradle APIs
- [Behavior change] Toolchain detection is now disabled by default

==== Maven plugin

Expand Down
12 changes: 6 additions & 6 deletions docs/src/docs/snippets/gradle/groovy/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -49,20 +49,20 @@ graalvmNative {
binaries {
main {
javaLauncher = javaToolchains.launcherFor {
languageVersion = JavaLanguageVersion.of(8)
vendor = JvmVendorSpec.matching("GraalVM Community")
languageVersion = JavaLanguageVersion.of(20)
vendor = JvmVendorSpec.matching("Oracle Corporation")
}
}
}
}
// end::select-toolchain[]

if (providers.environmentVariable("DISABLE_TOOLCHAIN").isPresent()) {
// tag::disabling-toolchain[]
if (providers.environmentVariable("ENABLE_TOOLCHAIN").isPresent()) {
// tag::enabling-toolchain[]
graalvmNative {
toolchainDetection = false
toolchainDetection = true
}
// end::disabling-toolchain[]
// end::enabling-toolchain[]
}

// tag::all-config-options[]
Expand Down
12 changes: 6 additions & 6 deletions docs/src/docs/snippets/gradle/kotlin/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -50,20 +50,20 @@ graalvmNative {
binaries {
named("main") {
javaLauncher.set(javaToolchains.launcherFor {
languageVersion.set(JavaLanguageVersion.of(8))
vendor.set(JvmVendorSpec.matching("GraalVM Community"))
languageVersion.set(JavaLanguageVersion.of(20))
vendor.set(JvmVendorSpec.matching("Oracle Corporation"))
})
}
}
}
// end::select-toolchain[]

if (providers.environmentVariable("DISABLE_TOOLCHAIN").isPresent()) {
// tag::disabling-toolchain[]
if (providers.environmentVariable("ENABLE_TOOLCHAIN").isPresent()) {
// tag::enabling-toolchain[]
graalvmNative {
toolchainDetection.set(false)
toolchainDetection.set(true)
}
// end::disabling-toolchain[]
// end::enabling-toolchain[]
}

// tag::all-config-options[]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ class NativeImageOptionsTest extends Specification {
id 'org.graalvm.buildtools.native'
}
graalvmNative.toolchainDetection = true
assert graalvmNative.binaries.main.javaLauncher
.get()
.metadata
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ public interface GraalVMExtension {

/**
* Property driving the detection of toolchains which support building native images.
* The default is true.
* The default is false.
*
* @return is toolchain detection on
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ public DefaultGraalVmExtension(NamedDomainObjectContainer<NativeImageOptions> na
this.plugin = plugin;
this.project = project;
this.defaultJavaLauncher = project.getObjects().property(JavaLauncher.class);
getToolchainDetection().convention(true);
getToolchainDetection().convention(false);
nativeImages.configureEach(options -> options.getJavaLauncher().convention(defaultJavaLauncher));
getTestSupport().convention(true);
AgentOptions agentOpts = getAgent();
Expand Down

0 comments on commit 9d4fb49

Please sign in to comment.