The Toolchains for JVM projects (gradle.org) documentation is clear on how to make a task Java-toolchain-aware for JavaLauncher by using launcherFor. Looking at the documentation of JavaToolchainService I can also see you can get a JavaCompiler via compilerFor and a JavadocTool via javadocToolFor. That’s great if I want to directly use the java, javac, or javadoc executables.
But say I want to execute a different tool, such as jlink, jpackage, or jmod. One way I can think to implement this is like so:
import org.gradle.api.DefaultTask
import org.gradle.api.plugins.JavaPluginExtension
import org.gradle.api.provider.Property
import org.gradle.api.tasks.Nested
import org.gradle.api.tasks.TaskAction
import org.gradle.jvm.toolchain.JavaLauncher
import org.gradle.jvm.toolchain.JavaToolchainService
import org.gradle.kotlin.dsl.getByType
import org.gradle.process.ExecOperations
import javax.inject.Inject
@Suppress("LeakingThis")
abstract class JLinkTask : DefaultTask() {
@get:Inject
protected abstract val execOps: ExecOperations
@get:Inject
protected abstract val javaToolchainService: JavaToolchainService
@get:Nested
abstract val launcher: Property<JavaLauncher>
init {
val toolchain = project.extensions.getByType(JavaPluginExtension::class).toolchain
val defaultLauncher = javaToolchainService.launcherFor(toolchain)
launcher.convention(defaultLauncher)
}
@TaskAction
fun execute() {
val result = execOps.exec {
// Is this a good idea?
executable(launcher.get().metadata.installationPath.file("bin/jlink"))
// ... other configuration ...
}
result.rethrowFailure()
result.assertNormalExitValue()
}
}
But is this part:
executable(launcher.get().metadata.installationPath.file("bin/jlink"))
A good idea? Is there a better implementation? Should I not use toolchains for this?
Additionally, will toolchains be extended to support any Java tool, or perhaps simply provide a way (if there isn’t one already?) to get the installation path without going through, e.g., JavaLauncher (which implies the java tool will be used)?