From 389ea32f48ca46c3e1f5ad0fd9e0d46cea7b631f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergej=20Ko=C5=A1=C4=8Dejev?= Date: Fri, 28 Jun 2024 21:23:23 +0200 Subject: [PATCH] 1.27.0: Add `javaLauncher` and `toolchainSpec` to `DownloadJbrForPlatform` task --- CHANGELOG.md | 8 ++++ api/mps-gradle-plugin.api | 4 +- build.gradle.kts | 2 +- docs/plugins/download-jbr.md | 23 +++++---- .../de/itemis/mps/gradle/downloadJBR/Tasks.kt | 30 ++++++++++-- .../kotlin/test/others/JBRDownloadTest.kt | 48 +++++++++++++++++++ 6 files changed, 98 insertions(+), 17 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fee3614f..a6ec8cb7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,14 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## 1.27.0 + +### Added + +- `DownloadJbrForPlatform#toolchainSpec`: a `Provider` that can be used with `JavaToolchainService` + to look up tools such as the Java launcher, compiler or Javadoc generator. +- `DownloadJbrForPlatform#javaLauncher`: a `Provider` that can be used with `JavaExec` tasks. + ## 1.26.0 ### Changed diff --git a/api/mps-gradle-plugin.api b/api/mps-gradle-plugin.api index 389c720c..a434e066 100644 --- a/api/mps-gradle-plugin.api +++ b/api/mps-gradle-plugin.api @@ -209,9 +209,11 @@ public class de/itemis/mps/gradle/downloadJBR/DownloadJbrConfiguration { } public class de/itemis/mps/gradle/downloadJBR/DownloadJbrForPlatform : org/gradle/api/DefaultTask { - public fun ()V + public fun (Lorg/gradle/api/model/ObjectFactory;Lorg/gradle/jvm/toolchain/JavaToolchainService;)V public final fun getJavaExecutable ()Ljava/io/File; + public final fun getJavaLauncher ()Lorg/gradle/api/provider/Provider; public final fun getJbrDir ()Ljava/io/File; + public final fun getToolchainSpec ()Lorg/gradle/api/provider/Provider; public final fun setJavaExecutable (Ljava/io/File;)V public final fun setJbrDir (Ljava/io/File;)V } diff --git a/build.gradle.kts b/build.gradle.kts index 7d43cbb3..36c5745f 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -24,7 +24,7 @@ plugins { id("org.jetbrains.kotlinx.binary-compatibility-validator") version "0.13.2" } -val baseVersion = "1.26.0" +val baseVersion = "1.27.0" group = "de.itemis.mps" diff --git a/docs/plugins/download-jbr.md b/docs/plugins/download-jbr.md index 2178833a..ea295d73 100644 --- a/docs/plugins/download-jbr.md +++ b/docs/plugins/download-jbr.md @@ -1,17 +1,17 @@ ## Download JetBrains Runtime -When building MPS projects with the JetBrains Runtime, the JDK/JRE used by MPS and other intellij based IDEs, it's -required to download the correct version of the runtime. Since the runtime is platform dependent it's required to -download a platform dependent binary. While it's possible to add the logic to your own build script we provide a convenient -way of doing this with a Gradle plugin. +When building MPS projects with the JetBrains Runtime, the JDK/JRE used by MPS and other JetBrains IDEs, it's +required to download the correct version of the runtime. Since the runtime is platform-dependent it is required to +download a platform-dependent binary. While it's possible to add the logic to your own build script, we provide +a convenient way of doing this with a Gradle plugin. -The download-jbr plugin will add new dependencies and a task to your build. It will add a dependency to `com.jetbrains.jdk:jbr` -to your build, you need to make sure that it is available in your dependency repositories. The itemis Maven repository at -https://artifacts.itemis.cloud/repository/maven-mps provides this dependency, but you can create your own with -the scripts located in [mbeddr/build.publish.jdk](https://github.com/mbeddr/build.publish.jdk). +The `download-jbr` plugin will add new dependencies and a task to your build. It will add a dependency to +`com.jetbrains.jdk:jbr` to your build, you need to make sure that it is available in your dependency repositories. The +[itemis Maven repository](https://artifacts.itemis.cloud/repository/maven-mps) provides this dependency, but you can +create your own with the scripts located in [mbeddr/build.publish.jdk](https://github.com/mbeddr/build.publish.jdk). For easy consumption and incremental build support the plugin creates a task `downloadJbr` which exposes the location of -the java executable via the `javaExecutable` property. See +the java executable via the `javaExecutable` and `javaLauncher` properties. See [the tests](../../src/test/kotlin/test/others/JBRDownloadTest.kt) for an example of how to use it. ### Usage @@ -25,9 +25,7 @@ plugins { repositories { mavenCentral() - maven { - url = URI("https://artifacts.itemis.cloud/repository/maven-mps") - } + maven("https://artifacts.itemis.cloud/repository/maven-mps") } downloadJbr { @@ -51,6 +49,7 @@ downloadJbr { ``` ### Parameters + * `jbrVersion` - version of the JBR to download. While this supports maven version selectors we highly recommend not using wildcards like `*` or `+` in there for reproducible builds. * `distributionType` - optional distribution type for the JBR to use. Will default to `jbr_jcef` if omitted. diff --git a/src/main/kotlin/de/itemis/mps/gradle/downloadJBR/Tasks.kt b/src/main/kotlin/de/itemis/mps/gradle/downloadJBR/Tasks.kt index 7599b331..efa379bd 100644 --- a/src/main/kotlin/de/itemis/mps/gradle/downloadJBR/Tasks.kt +++ b/src/main/kotlin/de/itemis/mps/gradle/downloadJBR/Tasks.kt @@ -3,13 +3,23 @@ package de.itemis.mps.gradle.downloadJBR import org.gradle.api.DefaultTask import org.gradle.api.file.DirectoryProperty import org.gradle.api.file.RegularFileProperty +import org.gradle.api.model.ObjectFactory +import org.gradle.api.provider.Provider import org.gradle.api.tasks.* +import org.gradle.jvm.toolchain.JavaLauncher +import org.gradle.jvm.toolchain.JavaToolchainService +import org.gradle.jvm.toolchain.JavaToolchainSpec +import org.gradle.jvm.toolchain.internal.SpecificInstallationToolchainSpec import java.io.File +import javax.inject.Inject -open class DownloadJbrForPlatform : DefaultTask() { +open class DownloadJbrForPlatform @Inject constructor( + private val objects: ObjectFactory, + private val javaToolchainService: JavaToolchainService +) : DefaultTask() { @get:Internal - internal val jbrDirProperty: DirectoryProperty = project.objects.directoryProperty() + internal val jbrDirProperty: DirectoryProperty = objects.directoryProperty() @get:Internal var jbrDir : File @@ -19,7 +29,7 @@ open class DownloadJbrForPlatform : DefaultTask() { } @get:Internal - internal val javaExecutableProperty: RegularFileProperty = project.objects.fileProperty() + internal val javaExecutableProperty: RegularFileProperty = objects.fileProperty() @get:Internal var javaExecutable: File @@ -27,4 +37,18 @@ open class DownloadJbrForPlatform : DefaultTask() { set(value) { javaExecutableProperty.set(value) } + + /** + * A [JavaToolchainSpec] that can be passed to [JavaToolchainService] to obtain various tools (Java compiler, + * launcher, javadoc). + */ + @get:Internal + val toolchainSpec: Provider = + javaExecutableProperty.map { SpecificInstallationToolchainSpec.fromJavaExecutable(objects, it.asFile.path) } + + /** + * A [JavaLauncher] for the downloaded JBR that can be used with [JavaExec] task. + */ + @get:Internal + val javaLauncher: Provider = toolchainSpec.flatMap(javaToolchainService::launcherFor) } diff --git a/src/test/kotlin/test/others/JBRDownloadTest.kt b/src/test/kotlin/test/others/JBRDownloadTest.kt index 50d043ab..7ace0216 100644 --- a/src/test/kotlin/test/others/JBRDownloadTest.kt +++ b/src/test/kotlin/test/others/JBRDownloadTest.kt @@ -2,6 +2,8 @@ package test.others import org.gradle.testkit.runner.GradleRunner import org.gradle.testkit.runner.TaskOutcome +import org.hamcrest.CoreMatchers.containsString +import org.hamcrest.MatcherAssert.assertThat import org.junit.Assert import org.junit.Before import org.junit.Rule @@ -199,4 +201,50 @@ class JBRDownloadTest { .build() Assert.assertEquals(TaskOutcome.SUCCESS, result.task(":exec")?.outcome) } + + @Test + fun `executed downloaded java using JavaLauncher`() { + settingsFile.writeText(""" + rootProject.name = "hello-world" + """.trimIndent()) + + buildFile.writeText(""" + import java.net.URI + import de.itemis.mps.gradle.downloadJBR.DownloadJbrForPlatform + + plugins { + id("download-jbr") + } + + repositories { + mavenCentral() + maven { + url = URI("https://artifacts.itemis.cloud/repository/maven-mps") + } + } + + downloadJbr { + jbrVersion = "$JBR_VERSION" + } + + val downloadJbrTask = tasks.named("downloadJbr", DownloadJbrForPlatform::class) + + tasks.register("exec") { + dependsOn(downloadJbrTask) + javaLauncher.set(downloadJbrTask.flatMap { it.javaLauncher }) + jvmArgs("--version") + + // Main class will be ignored due to --version but has to be provided + mainClass.set("ignored") + } + """.trimIndent()) + + val result = GradleRunner.create() + .withProjectDir(testProjectDir.root) + .withArguments("exec") + .withPluginClasspath() + .build() + Assert.assertEquals(TaskOutcome.SUCCESS, result.task(":exec")?.outcome) + assertThat(result.output, containsString("OpenJDK Runtime Environment JBR")) + } }