Skip to content

Commit cf0a242

Browse files
qwwdfsadSpace Team
authored andcommitted
[ABI Validation] BCV Gradle rework
* Annotate file paths with `@Language("file-reference")` * Update to Gradle 8 * bump Gradle Plugin Publish Plugin version * build script updates & improvements * use Java Toolchains to set the Java version * use jvm-test-fixtures plugin for functionalTest sources * update build config, remove redundant Maven publication * Initial Gradle convention plugins * Apply BCV, commit API dump * The ABI shape will be reduced in the future, this is a technical change * java-diff-utils * Update Gradle to 8.5 --------- Co-authored-by: aSemy <[email protected]> Pull request Kotlin/binary-compatibility-validator#134 Moved from Kotlin/binary-compatibility-validator@60098a3
1 parent 4f15c0f commit cf0a242

25 files changed

+694
-279
lines changed

libraries/tools/abi-validation/api/binary-compatibility-validator.api

Lines changed: 286 additions & 0 deletions
Large diffs are not rendered by default.
Lines changed: 111 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,24 @@
1-
import com.gradle.publish.*
2-
import kotlinx.validation.build.*
3-
import org.jetbrains.kotlin.gradle.tasks.*
1+
import kotlinx.validation.build.mavenCentralMetadata
2+
import kotlinx.validation.build.mavenRepositoryPublishing
3+
import kotlinx.validation.build.signPublicationIfKeyPresent
4+
import org.gradle.api.attributes.TestSuiteType.FUNCTIONAL_TEST
5+
import org.jetbrains.kotlin.gradle.dsl.JvmTarget
6+
import org.jetbrains.kotlin.gradle.dsl.KotlinVersion
47

58
plugins {
69
kotlin("jvm")
710
`java-gradle-plugin`
8-
id("com.gradle.plugin-publish") apply false
11+
id("com.gradle.plugin-publish")
12+
kotlinx.validation.build.conventions.`java-base`
913
signing
1014
`maven-publish`
15+
`jvm-test-suite`
16+
id("org.jetbrains.kotlinx.binary-compatibility-validator")
1117
}
1218

13-
repositories {
14-
mavenCentral()
15-
gradlePluginPortal()
16-
google()
19+
group = "org.jetbrains.kotlinx"
20+
providers.gradleProperty("DeployVersion").orNull?.let {
21+
version = it
1722
}
1823

1924
sourceSets {
@@ -22,29 +27,18 @@ sourceSets {
2227
}
2328
}
2429

25-
sourceSets {
26-
create("functionalTest") {
27-
withConvention(org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet::class) {
28-
}
29-
compileClasspath += sourceSets.main.get().output + configurations.testRuntimeClasspath
30-
runtimeClasspath += output + compileClasspath
31-
}
32-
}
33-
34-
tasks.register<Test>("functionalTest") {
35-
testClassesDirs = sourceSets["functionalTest"].output.classesDirs
36-
classpath = sourceSets["functionalTest"].runtimeClasspath
37-
}
38-
tasks.check { dependsOn(tasks["functionalTest"]) }
39-
4030
// While gradle testkit supports injection of the plugin classpath it doesn't allow using dependency notation
4131
// to determine the actual runtime classpath for the plugin. It uses isolation, so plugins applied by the build
4232
// script are not visible in the plugin classloader. This means optional dependencies (dependent on applied plugins -
4333
// for example kotlin multiplatform) are not visible even if they are in regular gradle use. This hack will allow
4434
// extending the classpath. It is based upon: https://docs.gradle.org/6.0/userguide/test_kit.html#sub:test-kit-classpath-injection
4535

4636
// Create a configuration to register the dependencies against
47-
val testPluginRuntimeConfiguration = configurations.register("testPluginRuntime")
37+
val testPluginRuntimeConfiguration = configurations.create("testPluginRuntime") {
38+
isCanBeConsumed = false
39+
isCanBeResolved = true
40+
isVisible = false
41+
}
4842

4943
// The task that will create a file that stores the classpath needed for the plugin to have additional runtime dependencies
5044
// This file is then used in to tell TestKit which classpath to use.
@@ -58,106 +52,144 @@ val createClasspathManifest = tasks.register("createClasspathManifest") {
5852
.withPropertyName("outputDir")
5953

6054
doLast {
61-
outputDir.mkdirs()
62-
file(outputDir.resolve("plugin-classpath.txt")).writeText(testPluginRuntimeConfiguration.get().joinToString("\n"))
55+
file(outputDir.resolve("plugin-classpath.txt"))
56+
.writeText(testPluginRuntimeConfiguration.joinToString("\n"))
6357
}
6458
}
6559

66-
val kotlinVersion: String by project
67-
val androidGradlePluginVersion: String = "7.2.2"
68-
6960
dependencies {
7061
implementation(gradleApi())
71-
implementation("org.jetbrains.kotlinx:kotlinx-metadata-jvm:0.6.2")
72-
implementation("org.ow2.asm:asm:9.2")
73-
implementation("org.ow2.asm:asm-tree:9.2")
74-
implementation("com.googlecode.java-diff-utils:diffutils:1.3.0")
75-
compileOnly("org.jetbrains.kotlin.multiplatform:org.jetbrains.kotlin.multiplatform.gradle.plugin:1.8.10")
76-
// compileOnly("com.android.tools.build:gradle:${androidGradlePluginVersion}")
62+
implementation(libs.kotlinx.metadata)
63+
implementation(libs.ow2.asm)
64+
implementation(libs.ow2.asmTree)
65+
implementation(libs.javaDiffUtils)
66+
compileOnly(libs.gradlePlugin.kotlin)
67+
68+
// Android support is not yet implemented https://github.com/Kotlin/binary-compatibility-validator/issues/94
69+
//compileOnly(libs.gradlePlugin.android)
7770

7871
// The test needs the full kotlin multiplatform plugin loaded as it has no visibility of previously loaded plugins,
7972
// unlike the regular way gradle loads plugins.
80-
add(testPluginRuntimeConfiguration.name, "org.jetbrains.kotlin.multiplatform:org.jetbrains.kotlin.multiplatform.gradle.plugin:$kotlinVersion")
81-
add(testPluginRuntimeConfiguration.name, "com.android.tools.build:gradle:${androidGradlePluginVersion}")
82-
83-
testImplementation(kotlin("test-junit"))
84-
"functionalTestImplementation"(files(createClasspathManifest))
85-
86-
"functionalTestImplementation"("org.assertj:assertj-core:3.18.1")
87-
"functionalTestImplementation"(gradleTestKit())
88-
"functionalTestImplementation"(kotlin("test-junit"))
73+
testPluginRuntimeConfiguration(libs.gradlePlugin.android)
74+
testPluginRuntimeConfiguration(libs.gradlePlugin.kotlin)
8975
}
9076

9177
tasks.compileKotlin {
92-
kotlinOptions.apply {
93-
allWarningsAsErrors = true
94-
95-
languageVersion = "1.4"
96-
apiVersion = "1.4"
97-
jvmTarget = "1.8"
98-
78+
compilerOptions {
79+
allWarningsAsErrors.set(true)
80+
@Suppress("DEPRECATION") // Compatibility with Gradle 7 requires Kotlin 1.4
81+
languageVersion.set(KotlinVersion.KOTLIN_1_4)
82+
apiVersion.set(languageVersion)
83+
jvmTarget.set(JvmTarget.JVM_1_8)
9984
// Suppressing "w: Language version 1.4 is deprecated and its support will be removed" message
10085
// because LV=1.4 in practice is mandatory as it is a default language version in Gradle 7.0+ for users' kts scripts.
101-
freeCompilerArgs += "-Xsuppress-version-warnings"
86+
freeCompilerArgs.addAll(
87+
"-Xsuppress-version-warnings"
88+
)
10289
}
10390
}
10491

10592
java {
106-
sourceCompatibility = JavaVersion.VERSION_1_8
107-
targetCompatibility = JavaVersion.VERSION_1_8
93+
withJavadocJar()
94+
withSourcesJar()
95+
toolchain {
96+
languageVersion.set(JavaLanguageVersion.of(8))
97+
}
10898
}
10999

110-
tasks {
111-
compileTestKotlin {
112-
kotlinOptions {
113-
languageVersion = "1.9"
114-
freeCompilerArgs += "-Xsuppress-version-warnings"
115-
}
116-
}
117-
test {
118-
systemProperty("overwrite.output", System.getProperty("overwrite.output", "false"))
119-
systemProperty("testCasesClassesDirs", sourceSets.test.get().output.classesDirs.asPath)
120-
jvmArgs("-ea")
100+
tasks.compileTestKotlin {
101+
compilerOptions {
102+
languageVersion.set(KotlinVersion.KOTLIN_1_9)
121103
}
122104
}
123105

124-
properties["DeployVersion"]?.let { version = it }
106+
tasks.withType<Test>().configureEach {
107+
systemProperty("overwrite.output", System.getProperty("overwrite.output", "false"))
108+
systemProperty("testCasesClassesDirs", sourceSets.test.get().output.classesDirs.asPath)
109+
jvmArgs("-ea")
110+
}
125111

126112
publishing {
127113
publications {
128114
create<MavenPublication>("maven") {
129115
from(components["java"])
130-
mavenCentralMetadata()
131-
mavenCentralArtifacts(project, project.sourceSets.main.get().allSource)
116+
artifact(tasks.javadocJar)
117+
artifact(tasks.sourcesJar)
132118
}
133119

134120
mavenRepositoryPublishing(project)
135121
mavenCentralMetadata()
136122
}
137123

138-
publications.withType(MavenPublication::class).all {
124+
publications.withType<MavenPublication>().all {
139125
signPublicationIfKeyPresent(this)
140126
}
141-
}
142127

143-
apply(plugin = "org.gradle.java-gradle-plugin")
144-
apply(plugin = "com.gradle.plugin-publish")
145-
146-
extensions.getByType(PluginBundleExtension::class).apply {
147-
website = "https://github.com/Kotlin/binary-compatibility-validator"
148-
vcsUrl = "https://github.com/Kotlin/binary-compatibility-validator"
149-
tags = listOf("kotlin", "api-management", "binary-compatibility")
128+
// a publication will be created automatically by com.gradle.plugin-publish
150129
}
151130

131+
@Suppress("UnstableApiUsage")
152132
gradlePlugin {
153-
testSourceSets(sourceSets["functionalTest"])
133+
website.set("https://github.com/Kotlin/binary-compatibility-validator")
134+
vcsUrl.set("https://github.com/Kotlin/binary-compatibility-validator")
135+
136+
plugins.configureEach {
137+
tags.addAll("kotlin", "api-management", "binary-compatibility")
138+
}
154139

155140
plugins {
156141
create("binary-compatibility-validator") {
157142
id = "org.jetbrains.kotlinx.binary-compatibility-validator"
158143
implementationClass = "kotlinx.validation.BinaryCompatibilityValidatorPlugin"
159144
displayName = "Binary compatibility validator"
160-
description = "Produces binary API dumps and compares them in order to verify that binary API is preserved"
145+
description =
146+
"Produces binary API dumps and compares them in order to verify that binary API is preserved"
161147
}
162148
}
163149
}
150+
151+
@Suppress("UnstableApiUsage")
152+
testing {
153+
suites {
154+
withType<JvmTestSuite>().configureEach {
155+
useJUnit()
156+
dependencies {
157+
implementation(project())
158+
implementation(libs.assertJ.core)
159+
implementation(libs.kotlin.test)
160+
}
161+
}
162+
163+
val test by getting(JvmTestSuite::class) {
164+
description = "Regular unit tests"
165+
}
166+
167+
val functionalTest by creating(JvmTestSuite::class) {
168+
testType.set(FUNCTIONAL_TEST)
169+
description = "Functional Plugin tests using Gradle TestKit"
170+
171+
dependencies {
172+
implementation(files(createClasspathManifest))
173+
174+
implementation(gradleApi())
175+
implementation(gradleTestKit())
176+
}
177+
178+
targets.configureEach {
179+
testTask.configure {
180+
shouldRunAfter(test)
181+
}
182+
}
183+
}
184+
185+
gradlePlugin.testSourceSets(functionalTest.sources)
186+
187+
tasks.check {
188+
dependsOn(functionalTest)
189+
}
190+
}
191+
}
192+
193+
tasks.withType<Sign>().configureEach {
194+
onlyIf("only sign if signatory is present") { signatory?.keyId != null }
195+
}

libraries/tools/abi-validation/buildSrc/build.gradle.kts

Lines changed: 5 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -3,45 +3,21 @@
33
* Use of this source code is governed by the Apache 2.0 License that can be found in the LICENSE.txt file.
44
*/
55

6-
import org.jetbrains.kotlin.gradle.plugin.*
6+
import java.util.Properties
77
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
8-
import java.util.*
98

109
plugins {
1110
`kotlin-dsl`
1211
}
1312

14-
repositories {
15-
jcenter()
16-
}
17-
18-
val props = Properties().apply {
19-
project.file("../gradle.properties").inputStream().use { load(it) }
20-
}
21-
22-
val kotlinVersion: String = props.getProperty("kotlinVersion")
23-
2413
dependencies {
25-
implementation(kotlin("gradle-plugin-api", kotlinVersion))
26-
}
27-
28-
sourceSets["main"].withConvention(KotlinSourceSet::class) { kotlin.srcDirs("src") }
29-
30-
kotlinDslPluginOptions {
31-
experimentalWarning.set(false)
14+
implementation(libs.gradlePlugin.kotlin)
15+
implementation(libs.gradlePlugin.pluginPublishing)
16+
implementation(libs.gradlePlugin.bcv)
3217
}
3318

3419
tasks.withType<KotlinCompile>().configureEach {
35-
kotlinOptions.apply {
20+
kotlinOptions {
3621
allWarningsAsErrors = true
37-
apiVersion = "1.3"
38-
freeCompilerArgs += "-Xskip-runtime-version-check"
3922
}
4023
}
41-
42-
// Silence the following warning:
43-
// 'compileJava' task (current target is 17) and 'compileKotlin' task (current target is 1.8) jvm target compatibility should be set to the same Java version.
44-
java {
45-
sourceCompatibility = JavaVersion.VERSION_1_8
46-
targetCompatibility = JavaVersion.VERSION_1_8
47-
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
/*
2+
* Copyright 2016-2023 JetBrains s.r.o.
3+
* Use of this source code is governed by the Apache 2.0 License that can be found in the LICENSE.txt file.
4+
*/
5+
import org.gradle.api.initialization.resolve.RepositoriesMode.PREFER_SETTINGS
6+
7+
rootProject.name = "buildSrc"
8+
9+
pluginManagement {
10+
repositories {
11+
gradlePluginPortal()
12+
mavenCentral()
13+
}
14+
}
15+
16+
@Suppress("UnstableApiUsage")
17+
dependencyResolutionManagement {
18+
19+
repositoriesMode.set(PREFER_SETTINGS)
20+
21+
repositories {
22+
mavenCentral()
23+
gradlePluginPortal()
24+
}
25+
26+
versionCatalogs {
27+
create("libs") {
28+
from(files("../gradle/libs.versions.toml"))
29+
}
30+
}
31+
}

libraries/tools/abi-validation/buildSrc/src/MavenCentralMetadata.kt renamed to libraries/tools/abi-validation/buildSrc/src/main/kotlin/MavenCentralMetadata.kt

Lines changed: 4 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,12 @@
11
/*
2-
* Copyright 2016-2020 JetBrains s.r.o.
2+
* Copyright 2016-2023 JetBrains s.r.o.
33
* Use of this source code is governed by the Apache 2.0 License that can be found in the LICENSE.txt file.
44
*/
5-
65
package kotlinx.validation.build
76

8-
import org.gradle.api.*
9-
import org.gradle.api.file.*
10-
import org.gradle.api.publish.*
11-
import org.gradle.api.publish.maven.*
12-
import org.gradle.jvm.tasks.*
13-
import org.gradle.kotlin.dsl.*
7+
import org.gradle.api.publish.PublishingExtension
8+
import org.gradle.api.publish.maven.MavenPublication
9+
import org.gradle.kotlin.dsl.withType
1410

1511
fun PublishingExtension.mavenCentralMetadata() {
1612
publications.withType(MavenPublication::class) {
@@ -41,16 +37,3 @@ fun PublishingExtension.mavenCentralMetadata() {
4137
}
4238
}
4339
}
44-
45-
fun MavenPublication.mavenCentralArtifacts(project: Project, sources: SourceDirectorySet) {
46-
val sourcesJar by project.tasks.creating(Jar::class) {
47-
archiveClassifier.set("sources")
48-
from(sources)
49-
}
50-
val javadocJar by project.tasks.creating(Jar::class) {
51-
archiveClassifier.set("javadoc")
52-
// contents are deliberately left empty
53-
}
54-
artifact(sourcesJar)
55-
artifact(javadocJar)
56-
}

0 commit comments

Comments
 (0)