Skip to content

Commit

Permalink
Merge pull request #16 from madisp/java-toolchain
Browse files Browse the repository at this point in the history
add support for Java toolchains
  • Loading branch information
martinbonnin committed Apr 3, 2023
2 parents ee331e2 + d07938f commit cb007cd
Show file tree
Hide file tree
Showing 6 changed files with 120 additions and 12 deletions.
25 changes: 25 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,31 @@ For plugins that generate source code and contain a lot of package names, this m

By using `R8` and [proguard rules](https://www.guardsquare.com/manual/configuration/usage), `Gr8` makes relocation more predictable and configurable.

**Can I override the system classes used by `R8`, like target JDK 11 with my plugin while building on Java 17?**

If you set your Java toolchain then R8 will also use the same toolchain to discover system classes:

```
java {
toolchain {
languageVersion.set(JavaLanguageVersion.of(11))
}
}
```

If for some reason you want to override this explicitly:

```
gr8 {
val shadowedJar = create("gr8") {
proguardFile("rules.pro")
configuration("shade")
systemClassesToolchain {
languageVersion.set(JavaLanguageVersion.of(11))
}
}
}
```

**Could I use the Gradle Worker API instead?**

Expand Down
2 changes: 1 addition & 1 deletion plugin-common/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ plugins {
}

dependencies {
api("dev.gradleplugins:gradle-api:6.0")
api("dev.gradleplugins:gradle-api:6.7")
implementation("net.mbonnin.r8:r8:3.4.0-dev.0")
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,20 +1,25 @@
package com.gradleup.gr8

import com.gradleup.gr8.StripGradleApiTask.Companion.isGradleApi
import org.gradle.api.Action
import org.gradle.api.Project
import org.gradle.api.Task
import org.gradle.api.file.RegularFile
import org.gradle.api.plugins.JavaPluginExtension
import org.gradle.api.provider.ListProperty
import org.gradle.api.provider.Property
import org.gradle.api.provider.Provider
import org.gradle.api.tasks.TaskProvider
import org.gradle.api.tasks.bundling.AbstractArchiveTask
import org.gradle.api.tasks.bundling.Jar
import org.gradle.jvm.toolchain.JavaCompiler
import org.gradle.jvm.toolchain.JavaToolchainService
import org.gradle.jvm.toolchain.JavaToolchainSpec
import java.io.File

open class Gr8Configurator(
private val name: String,
private val project: Project,
private val javaToolchainService: JavaToolchainService,
) {
private var programJar: Property<Any> = project.objects.property(Any::class.java)
private var configuration: Property<String> = project.objects.property(String::class.java)
Expand All @@ -23,9 +28,17 @@ open class Gr8Configurator(
private var proguardFiles = mutableListOf<Any>()
private var stripGradleApi: Property<Boolean> = project.objects.property(Boolean::class.java)
private var excludes: ListProperty<String> = project.objects.listProperty(String::class.java)
private val javaCompiler: Property<JavaCompiler> = project.objects.property(JavaCompiler::class.java)

private val buildDir = project.layout.buildDirectory.dir("gr8/$name").get().asFile

init {
val javaExtension = project.extensions.findByType(JavaPluginExtension::class.java)
if (javaExtension != null) {
javaCompiler.convention(javaToolchainService.compilerFor(javaExtension.toolchain))
}
}

/**
* The configuration to include in the resulting output jar.
*/
Expand Down Expand Up @@ -122,6 +135,43 @@ open class Gr8Configurator(
this.excludes.add(exclude)
}

/**
* The java compiler toolchain to use for discovering system classes when running R8
*
* The system classes from this Java toolchain will be passed to R8 when invoking it, enabling you
* to target any version of Java toolchain while building on newer JDKs. Defaults to the toolchain used to compile.
*
* Usage:
*
* ```
* systemClassesToolchain(javaToolchains.compilerFor {
* languageVersion.set(JavaLanguageVersion.of(11))
* })
* ```
*/
fun systemClassesToolchain(compiler: JavaCompiler) {
this.javaCompiler.set(compiler)
}

/**
* The java compiler toolchain to use for discovering system classes when running R8, defaults to the Java extension
* toolchain (also used for compiling your classes)
*
* The system classes from this Java toolchain will be passed to R8 when invoking it, enabling you
* to target any version of Java toolchain while building on newer JDKs. Defaults to the toolchain used to compile.
*
* Usage:
*
* ```
* systemClassesToolchain {
* languageVersion.set(JavaLanguageVersion.of(11))
* }
* ```
*/
fun systemClassesToolchain(spec: Action<JavaToolchainSpec>) {
this.javaCompiler.set(javaToolchainService.compilerFor(spec))
}

private fun defaultProgramJar(): Provider<File> {
return project.tasks.named("jar").flatMap {
(it as Jar).archiveFile
Expand Down Expand Up @@ -181,6 +231,8 @@ open class Gr8Configurator(
val archiveName = archiveName.getOrElse("${project.name}-${project.version}-shadowed.jar")
task.outputJar(File(buildDir, archiveName))
task.proguardConfigurationFiles.from(proguardFiles.toTypedArray())

task.javaCompiler.set(javaCompiler)
}

return r8TaskProvider
Expand Down
11 changes: 8 additions & 3 deletions plugin-common/src/main/kotlin/com/gradleup/gr8/Gr8Extension.kt
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,18 @@ import org.gradle.api.internal.artifacts.dependencies.DefaultSelfResolvingDepend
import org.gradle.api.provider.Provider
import org.gradle.api.publish.PublishingExtension
import org.gradle.api.publish.maven.MavenPublication
import org.gradle.jvm.toolchain.JavaToolchainService
import javax.inject.Inject

open class Gr8Extension(
abstract class Gr8Extension(
private val project: Project,
) {

private val configurators = mutableSetOf<String>()

@get:Inject
protected abstract val javaToolchainService: JavaToolchainService

/**
* @return a provider that returns the new fat-minimized jar
*/
Expand All @@ -27,7 +32,7 @@ open class Gr8Extension(
"Gr8: $name is already created"
}

val configurator = Gr8Configurator(name, project)
val configurator = Gr8Configurator(name, project, javaToolchainService)
configurators.add(name)

action.execute(configurator)
Expand Down Expand Up @@ -115,4 +120,4 @@ open class Gr8Extension(
apiDependencies.remove(gradleApi)
}
}
}
}
36 changes: 31 additions & 5 deletions plugin-common/src/main/kotlin/com/gradleup/gr8/Gr8Task.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,18 @@ import com.android.tools.r8.JdkClassFileProvider
import com.android.tools.r8.OutputMode
import com.android.tools.r8.R8
import com.android.tools.r8.R8Command
import org.gradle.api.Action
import org.gradle.api.DefaultTask
import org.gradle.api.file.*
import org.gradle.api.provider.Property
import org.gradle.api.provider.Provider
import org.gradle.api.tasks.*
import org.gradle.internal.jvm.Jvm
import org.gradle.jvm.toolchain.JavaCompiler
import org.gradle.jvm.toolchain.JavaToolchainService
import org.gradle.jvm.toolchain.JavaToolchainSpec
import java.io.File
import javax.inject.Inject

@CacheableTask
abstract class Gr8Task : DefaultTask() {
Expand All @@ -30,6 +36,13 @@ abstract class Gr8Task : DefaultTask() {
@get:OutputFile
internal abstract val mapping: RegularFileProperty

@get:Nested
@get:Optional
internal abstract val javaCompiler: Property<JavaCompiler>

@get:Inject
protected abstract val javaToolchainService: JavaToolchainService

fun programFiles(any: Any) {
programFiles.from(any)
programFiles.disallowChanges()
Expand All @@ -50,6 +63,16 @@ abstract class Gr8Task : DefaultTask() {
mapping.disallowChanges()
}

fun javaLauncher(launcher: JavaCompiler) {
javaCompiler.set(launcher)
javaCompiler.disallowChanges()
}

fun toolchain(spec: Action<JavaToolchainSpec>) {
javaCompiler.set(javaToolchainService.compilerFor(spec))
javaCompiler.disallowChanges()
}

fun outputJar(): Provider<RegularFile> = outputJar

fun proguardConfigurationFiles(any: Any) {
Expand Down Expand Up @@ -82,11 +105,14 @@ abstract class Gr8Task : DefaultTask() {
setProguardMapOutputPath(mapping.get().asFile.toPath())
}
}
/**
* We might need an option to override that as if you're running newer versions of Java to run the task
* R8/asm might fail reading this while the target classes might very well be readable
*/
.addLibraryResourceProvider(JdkClassFileProvider.fromJdkHome(Jvm.current().javaHome.toPath()))
.apply {
if (javaCompiler.isPresent) {
val javaHome = javaCompiler.get().metadata.installationPath.asFile.toPath()
addLibraryResourceProvider(JdkClassFileProvider.fromJdkHome(javaHome))
} else {
addLibraryResourceProvider(JdkClassFileProvider.fromJdkHome(Jvm.current().javaHome.toPath()))
}
}
.setOutput(outputJar.asFile.get().toPath(), OutputMode.ClassFile)
.addProguardConfigurationFiles(proguardConfigurationFiles.files.map { it.toPath() })
.build()
Expand Down
4 changes: 2 additions & 2 deletions plugin/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ dependencies {
// Because we only allow stripping the gradleApi from the classpath, we remove
exclude("dev.gradleplugins", "gradle-api")
}
compileOnly("dev.gradleplugins:gradle-api:6.0")
add("gr8Classpath", "dev.gradleplugins:gradle-api:6.0") {
compileOnly("dev.gradleplugins:gradle-api:6.7")
add("gr8Classpath", "dev.gradleplugins:gradle-api:6.7") {
exclude("org.apache.ant")
}
}
Expand Down

0 comments on commit cb007cd

Please sign in to comment.