Skip to content

Commit

Permalink
Support for Gradle 8 (#149)
Browse files Browse the repository at this point in the history
See line/armeria#4854 for the detailed
motivation and changes.
  • Loading branch information
ikhoon authored May 12, 2023
1 parent c20bc5b commit dad1db8
Show file tree
Hide file tree
Showing 9 changed files with 159 additions and 82 deletions.
15 changes: 1 addition & 14 deletions lib/common-dependencies.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,6 @@ buildscript {
}
}

def managedDependencyOverrides = [] as Set

allprojects { p ->
ext {
// Add managedVersions() for backward compatibility with dependencies.yml
Expand Down Expand Up @@ -178,19 +176,8 @@ configure(projectsWithFlags('java')) {
dependencies {
configurations.configureEach { configuration ->
// Add to resolvable configurations
if (configuration.canBeResolved && !configuration.canBeConsumed) {
add(configuration.name, platform(dependencyManagementProject))
}

// Find version overrides in dependency declaration configurations
if (!configuration.canBeResolved && !configuration.canBeConsumed) {
configuration.dependencies.configureEach { dep ->
if (dep instanceof org.gradle.api.artifacts.ExternalDependency) {
if (dep.version != null) {
managedDependencyOverrides.add(String.valueOf("${dep.module}:${dep.version}"))
}
}
}
add(configuration.name, platform(dependencyManagementProject))
}
}
}
Expand Down
5 changes: 5 additions & 0 deletions lib/java-alpn.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,11 @@ configure(projectsWithFlags('java')) {
fileName.replaceFirst("-[0-9]+\\.[0-9]+\\.[0-9]+(?:\\.[^.]+)?\\.jar", ".jar")
}
}
tasks.compileJava.dependsOn(tasks.copyAlpnAgent)
tasks.processResources.dependsOn(tasks.copyAlpnAgent)
tasks.sourcesJar.dependsOn(tasks.copyAlpnAgent)
tasks.javadoc.dependsOn(tasks.copyAlpnAgent)
project.ext.getLintTask().dependsOn(tasks.copyAlpnAgent)

tasks.withType(JavaForkOptions) {
dependsOn tasks.copyAlpnAgent
Expand Down
10 changes: 5 additions & 5 deletions lib/java-coverage.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -49,11 +49,11 @@ configure(rootProject) {
task jacocoTestReport(type: JacocoReport) {
def reportTask = delegate
reports {
csv.enabled = false
xml.enabled = true
xml.destination = file("${rootProject.buildDir}/report/jacoco/jacocoTestReport.xml")
html.enabled = true
html.destination = file("${rootProject.buildDir}/report/jacoco/html")
csv.required = false
xml.required = true
xml.outputLocation.set(file("${rootProject.buildDir}/report/jacoco/jacocoTestReport.xml"))
html.required = true
html.outputLocation.set(file("${rootProject.buildDir}/report/jacoco/html"))
}

jacocoClasspath = configurations.jacocoAnt
Expand Down
8 changes: 8 additions & 0 deletions lib/java-rpc-proto.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,14 @@ configure(projectsWithFlags('java')) {
// declaring an explicit or implicit dependency.
sourcesJarTask.dependsOn(task)
}

def copyAlpnAgentTask= tasks.findByName('copyAlpnAgent')
if (copyAlpnAgentTask) {
// A workaround for ':generateProto' uses this output of task ':copyAlpnAgent' without
// declaring an explicit or implicit dependency.
task.dependsOn(copyAlpnAgentTask)
}

project.ext.getGenerateSourcesTask().dependsOn(task)
}
}
Expand Down
7 changes: 7 additions & 0 deletions lib/java-rpc-thrift.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,13 @@ configure(projectsWithFlags('java')) {
compileTask.dependsOn(task)
}

def copyAlpnAgentTask= tasks.findByName('copyAlpnAgent')
if (copyAlpnAgentTask) {
// A workaround for ':generateProto' uses this output of task ':copyAlpnAgent' without
// declaring an explicit or implicit dependency.
task.dependsOn(copyAlpnAgentTask)
}

project.ext.getGenerateSourcesTask().dependsOn(task)
}
}
Expand Down
35 changes: 24 additions & 11 deletions lib/java-shade.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,7 @@ configure(relocatedProjects) {
printconfiguration file("${project.buildDir}/proguard.cfg")
}

tasks.shadedClasses.dependsOn tasks.trimShadedJar
tasks.assemble.dependsOn tasks.trimShadedJar

// Add the trimmed JAR to archives.
Expand Down Expand Up @@ -198,17 +199,29 @@ configure(relocatedProjects) {
tasks.check.dependsOn tasks.shadedTest

// Configurations shouldn't be created in afterEvaluate so create it eagerly here before configuring it.
it.configurations.create("shadedTestRuntime") {

// In Gradle 8, dependencies can't be declared in a resolvable (canBeResolved=true) configuration. As a
// workaround two configurations are created to separate the declaration and resolving roles.
// - Directly declares dependencies to `shadedTestImplementation`.
// - Indirectly resolves the dependencies of `shadedTestImplementation` by creating a new configuration
// and extends `shadedTestImplementation`.
// https://discuss.gradle.org/t/problem-with-compileclasspath-after-gradle-8-update/44940
project.configurations.create("shadedTestImplementation") {
canBeResolved = false
canBeConsumed = false
}
project.configurations.create("shadedTestRuntime") {
canBeResolved = true
canBeConsumed = false
extendsFrom(project.configurations.shadedTestImplementation)
}

// Update the classpath of the 'shadedTest' task after all shaded projects are evaluated
// so that we get the complete dependency list.
project.afterEvaluate {
if (numConfiguredRelocatedProjects.incrementAndGet() == relocatedProjects.size()) {
relocatedProjects.each { p ->
configureShadedTestRuntimeConfiguration(p)
configureShadedTestImplementConfiguration(p)
}
relocatedProjects.each { p ->
def testTask = p.tasks.shadedTest
Expand Down Expand Up @@ -271,25 +284,25 @@ private void configureShadowTask(Project project, ShadowJar task, boolean isMain

/**
* Finds the dependencies of {@code project} recursively and adds the found dependencies to
* the configuration named as {@code 'shadedTestRuntime'}.
* the configuration named as {@code 'shadedTestImplementation'}.
*/
private Configuration configureShadedTestRuntimeConfiguration(
private Configuration configureShadedTestImplementConfiguration(
Project project, Project recursedProject = project,
Set<ExcludeRule> excludeRules = new HashSet<>(),
Set<Project> visitedProjects = new HashSet<>()) {

def shadedTestRuntime = project.configurations.getByName('shadedTestRuntime')
def shadedTestImplementation = project.configurations.getByName('shadedTestImplementation')

if (visitedProjects.contains(recursedProject)) {
return shadedTestRuntime
return shadedTestImplementation
} else {
visitedProjects.add(recursedProject);
}

if (recursedProject.tasks.findByName('trimShadedJar')) {
project.dependencies.add(shadedTestRuntime.name, files(recursedProject.tasks.trimShadedJar.outJarFiles))
project.dependencies.add(shadedTestImplementation.name, files(recursedProject.tasks.trimShadedJar.outJarFiles))
} else if (recursedProject.tasks.findByName('shadedJar')) {
project.dependencies.add(shadedTestRuntime.name, files(recursedProject.tasks.shadedJar.archivePath))
project.dependencies.add(shadedTestImplementation.name, files(recursedProject.tasks.shadedJar.archivePath))
}

def shadedDependencyNames = project.ext.relocations.collect { it['name'] }
Expand Down Expand Up @@ -323,17 +336,17 @@ private Configuration configureShadedTestRuntimeConfiguration(
}
// Do not use `project.dependencies.add(name, dep)` that discards the classifier of
// a dependency. See https://github.com/gradle/gradle/issues/23096
project.configurations.getByName(shadedTestRuntime.name).dependencies.add(dep)
project.configurations.getByName(shadedTestImplementation.name).dependencies.add(dep)
}
}
}

// Recurse into the project dependencies.
projectDependencies.each { ProjectDependency dep ->
configureShadedTestRuntimeConfiguration(
configureShadedTestImplementConfiguration(
project, dep.dependencyProject,
excludeRules + dep.excludeRules, visitedProjects)
}

return shadedTestRuntime
return shadedTestImplementation
}
101 changes: 60 additions & 41 deletions lib/java.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ configure(projectsWithFlags('java')) {
apply plugin: 'java-library'
apply plugin: 'eclipse'
apply plugin: 'idea'
apply plugin: 'jvm-test-suite'

archivesBaseName = project.ext.artifactId

Expand All @@ -65,6 +66,17 @@ configure(projectsWithFlags('java')) {
"for '${project.path}' cannot be smaller than 8")
}

def targetJavaVersionStr = null
if (targetJavaVersion != null) {
targetJavaVersionStr = JavaVersion.toVersion(targetJavaVersion).toString()
}
def javaSourceCompatibility = targetJavaVersionStr ?: project.findProperty('javaSourceCompatibility') ?: '1.8'
def javaTargetCompatibility = targetJavaVersionStr ?: project.findProperty('javaTargetCompatibility') ?: '1.8'

// The default targetJavaVersion is 'javaTargetCompatibility'
targetJavaVersion = Integer.valueOf(JavaVersion.toVersion(javaTargetCompatibility).majorVersion)
project.ext.set('targetJavaVersion', targetJavaVersion)

def testJavaVersion = targetJavaVersion
if (project.hasProperty('testJavaVersion')) {
def testVersion = Integer.parseInt(String.valueOf(project.findProperty('testJavaVersion')))
Expand All @@ -74,6 +86,10 @@ configure(projectsWithFlags('java')) {
}
}

if (targetJavaVersion != null) {
targetJavaVersionStr = JavaVersion.toVersion(targetJavaVersion).toString()
}

logger.info("Using JRE ${testJavaVersion} to test ${project.path}")
project.ext.set("testJavaVersion", testJavaVersion)

Expand Down Expand Up @@ -118,56 +134,59 @@ configure(projectsWithFlags('java')) {

// Set the sensible compiler options.
tasks.withType(JavaCompile) {
def targetJavaVersionStr = null
if (targetJavaVersion != null) {
targetJavaVersionStr = JavaVersion.toVersion(targetJavaVersion).toString()
}
sourceCompatibility = targetJavaVersionStr ?: project.findProperty('javaSourceCompatibility') ?: '1.8'
// the default targetJavaVersion is 'javaTargetCompatibility'
targetCompatibility = targetJavaVersionStr ?: project.findProperty('javaTargetCompatibility') ?: '1.8'
sourceCompatibility = javaSourceCompatibility
targetCompatibility = javaTargetCompatibility
if (rootProject.ext.buildJdkVersion >= 9) {
// Supported since java 9 https://openjdk.org/jeps/247
options.release.set(Integer.valueOf(JavaVersion.toVersion(targetCompatibility).majorVersion))
options.release.set(targetJavaVersion)
}
options.encoding = 'UTF-8'
options.warnings = false
options.compilerArgs += '-parameters'
}

// Enable full exception logging for test failures.
tasks.withType(Test).configureEach {
testLogging.exceptionFormat = 'full'

// Use JUnit platform.
def flakyTests = rootProject.findProperty('flakyTests')
if (flakyTests == 'true') {
useJUnitPlatform {
includeTags 'FLAKY_TESTS'
testing {
suites {
test {
// Use JUnit platform.
useJUnitJupiter()

targets {
all {
testTask.configure {
testLogging.exceptionFormat = 'full'

def flakyTests = rootProject.findProperty('flakyTests')
if (flakyTests == 'true') {
useJUnitPlatform {
includeTags 'FLAKY_TESTS'
}
} else if (flakyTests == 'false') {
useJUnitPlatform {
excludeTags 'FLAKY_TESTS'
}
} else if (flakyTests != null) {
throw new IllegalArgumentException("flakyTests: $flakyTests (expected: true, false or null)")
}

// Use a different JRE for testing if necessary.
if (rootProject.ext.buildJdkVersion != project.ext.testJavaVersion) {
javaLauncher = javaToolchains.launcherFor {
languageVersion = JavaLanguageVersion.of(project.ext.testJavaVersion)
}
}

// disable tests for projects which target a higher java version
if (project.ext.testJavaVersion < project.ext.targetJavaVersion) {
project.logger.lifecycle("Skipping tests for ${project.path} since the " +
"testJavaVersion(${project.ext.testJavaVersion}) is smaller than the " +
"targetJavaVersion(${project.ext.targetJavaVersion})")
enabled = false
}
}
}
}
}
} else if (flakyTests == 'false') {
useJUnitPlatform {
excludeTags 'FLAKY_TESTS'
}
} else {
if (flakyTests != null) {
throw new IllegalArgumentException("flakyTests: $flakyTests (expected: true, false or null)")
}
useJUnitPlatform()
}

// Use a different JRE for testing if necessary.
if (rootProject.ext.buildJdkVersion != project.ext.testJavaVersion) {
javaLauncher = javaToolchains.launcherFor {
languageVersion = JavaLanguageVersion.of(project.ext.testJavaVersion)
}
}

// disable tests for projects which target a higher java version
if (project.ext.testJavaVersion < targetJavaVersion) {
project.logger.lifecycle("Skipping tests for ${project.path} since the " +
"testJavaVersion(${testJavaVersion}) is smaller than the " +
"targetJavaVersion(${targetJavaVersion})")
it.enabled = false
}
}

Expand Down
35 changes: 32 additions & 3 deletions lib/kotlin.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,11 @@ configure(projectsWithFlags('kotlin')) {
}.each { task ->
task.kotlinOptions.jvmTarget = target
task.kotlinOptions.freeCompilerArgs = compilerArgs

def copyAlpnAgentTask = tasks.findByName("copyAlpnAgent")
if (copyAlpnAgentTask != null) {
task.dependsOn(copyAlpnAgentTask)
}
}
}

Expand All @@ -36,9 +41,33 @@ configure(projectsWithFlags('kotlin')) {
}

afterEvaluate {
// A workaround for 'runKtlintCheckOverMainSourceSet' uses this output of task ':generateProto' without
// declaring an explicit or implicit dependency.
tasks.runKtlintCheckOverMainSourceSet.dependsOn(project.ext.getGenerateSourcesTask())

// `tasks.withType(KtLintCheckTask)` does not work here.
['Main', 'Test', 'Jmh'].each { name ->
// A workaround for 'runKtlintCheckOverMainSourceSet' uses this output of task ':generateProto'
// without declaring an explicit or implicit dependency.
def copyAlpnAgentTask = tasks.findByName("copyAlpnAgent")
def ktlintTask = tasks.findByName("runKtlintCheckOver${name}SourceSet")
if (ktlintTask != null) {
ktlintTask.dependsOn(project.ext.getGenerateSourcesTask())
if (copyAlpnAgentTask != null) {
ktlintTask.dependsOn(copyAlpnAgentTask)
}
}
def ktlintScriptTask = tasks.findByName("runKtlintCheckOverKotlinScripts")
if (ktlintScriptTask != null) {
if (copyAlpnAgentTask != null) {
ktlintScriptTask.dependsOn(copyAlpnAgentTask)
}
}

// A workaround for 'compileJmhKotlin' uses this output of task 'compileJmhThrift' without
// declaring an explicit or implicit dependency.
def compileTask = tasks.findByName("compile${name}Kotlin")
if (compileTask != null) {
compileTask.dependsOn(project.ext.getGenerateSourcesTask())
}
}
project.ext.getLintTask().dependsOn(tasks.ktlintCheck)
}
}
Expand Down
Loading

0 comments on commit dad1db8

Please sign in to comment.