Skip to content

Commit

Permalink
Move applying binary-compatibility-validator to JB plugin (#1262)
Browse files Browse the repository at this point in the history
## Proposed Changes

- Split `JetbrainsAndroidXPlugin` and `JetBrainsAndroidXImplPlugin` (for
referring `AndroidXExtension`)
- Move applying `binary-compatibility-validator` to
`JetBrainsAndroidXImplPlugin`
- Fix check to `shouldPublish()`
- Generate API dumps for new modules
  • Loading branch information
MatkovIvan committed Apr 11, 2024
1 parent 3e434d2 commit 79d893b
Show file tree
Hide file tree
Showing 15 changed files with 1,906 additions and 168 deletions.
9 changes: 9 additions & 0 deletions buildSrc/apply/applyJetBrainsAndroidXImplPlugin.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import androidx.build.jetbrains.JetBrainsAndroidXImplPlugin

buildscript {
dependencies {
classpath(project.files("${project.rootProject.ext["buildSrcOut"]}/private/build/libs/private.jar"))
}
}

apply plugin: JetBrainsAndroidXImplPlugin
Original file line number Diff line number Diff line change
Expand Up @@ -18,125 +18,18 @@

package androidx.build

import androidx.build.jetbrains.artifactRedirecting
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.kotlin.dsl.create
import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension
import org.jetbrains.kotlin.gradle.plugin.KotlinMultiplatformPluginWrapper
import org.jetbrains.kotlin.gradle.plugin.mpp.AbstractKotlinTarget
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinAndroidTarget
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinSoftwareComponentWithCoordinatesAndPublication
import org.jetbrains.kotlin.konan.target.KonanTarget

open class JetbrainsExtensions(
val project: Project,
val multiplatformExtension: KotlinMultiplatformExtension
) {

// check for example here: https://maven.google.com/web/index.html?q=lifecyc#androidx.lifecycle
val defaultKonanTargetsPublishedByAndroidx = setOf(
KonanTarget.LINUX_X64,
KonanTarget.IOS_X64,
KonanTarget.IOS_ARM64,
KonanTarget.IOS_SIMULATOR_ARM64,
KonanTarget.MACOS_X64,
KonanTarget.MACOS_ARM64,
)

@JvmOverloads
fun configureKNativeRedirectingDependenciesInKlibManifest(
konanTargets: Set<KonanTarget> = defaultKonanTargetsPublishedByAndroidx
) {
multiplatformExtension.targets.all {
if (it is KotlinNativeTarget && it.konanTarget in konanTargets) {
it.substituteForRedirectedPublishedDependencies()
}
}
}

/**
* When https://youtrack.jetbrains.com/issue/KT-61096 is implemented,
* this workaround won't be needed anymore:
*
* K/Native stores the dependencies in klib manifest and tries to resolve them during compilation.
* Since we use project dependency - implementation(project(...)), the klib manifest will reference
* our groupId (for example org.jetbrains.compose.collection-internal instead of androidx.collection).
* Therefore, the dependency can't be resolved since we don't publish libs for some k/native targets.
*
* To workaround that, we need to make sure
* that the project dependency is substituted by a module dependency (from androidx).
* We do this here. It should be called only for those k/native targets which require
* redirection to androidx artefacts.
*
* For available androidx targets see:
* https://maven.google.com/web/index.html#androidx.annotation
* https://maven.google.com/web/index.html#androidx.collection
* https://maven.google.com/web/index.html#androidx.lifecycle
*/
fun KotlinNativeTarget.substituteForRedirectedPublishedDependencies() {
val comp = compilations.getByName("main")
val androidAnnotationVersion =
project.findProperty("artifactRedirecting.androidx.annotation.version")!!
val androidCollectionVersion =
project.findProperty("artifactRedirecting.androidx.collection.version")!!
val androidLifecycleVersion =
project.findProperty("artifactRedirecting.androidx.lifecycle.version")!!
listOf(
comp.configurations.compileDependencyConfiguration,
comp.configurations.runtimeDependencyConfiguration,
comp.configurations.apiConfiguration,
comp.configurations.implementationConfiguration,
comp.configurations.runtimeOnlyConfiguration,
comp.configurations.compileOnlyConfiguration,
).forEach { c ->
c?.resolutionStrategy {

// TODO: It should be based on config
it.dependencySubstitution {
it.substitute(it.project(":annotation:annotation"))
.using(it.module("androidx.annotation:annotation:$androidAnnotationVersion"))
it.substitute(it.project(":collection:collection"))
.using(it.module("androidx.collection:collection:$androidCollectionVersion"))
it.substitute(it.project(":lifecycle:lifecycle-common"))
.using(it.module("androidx.lifecycle:lifecycle-common:$androidLifecycleVersion"))
it.substitute(it.project(":lifecycle:lifecycle-runtime"))
.using(it.module("androidx.lifecycle:lifecycle-runtime:$androidLifecycleVersion"))
it.substitute(it.project(":lifecycle:lifecycle-viewmodel"))
.using(it.module("androidx.lifecycle:lifecycle-viewmodel:$androidLifecycleVersion"))
}
}
}
}

}
// TODO: Rename to JetBrainsAndroidXPlugin
class JetbrainsAndroidXPlugin : Plugin<Project> {

@Suppress("UNREACHABLE_CODE", "UNUSED_VARIABLE")
override fun apply(project: Project) {
project.plugins.all { plugin ->
if (plugin is KotlinMultiplatformPluginWrapper) {
onKotlinMultiplatformPluginApplied(project)
}
}
}

private fun onKotlinMultiplatformPluginApplied(project: Project) {
enableArtifactRedirectingPublishing(project)
val multiplatformExtension =
project.extensions.getByType(KotlinMultiplatformExtension::class.java)

val extension = project.extensions.create<JetbrainsExtensions>(
"jetbrainsExtension",
project,
multiplatformExtension
val supportRoot = project.getSupportRootFolder()
project.apply(
mapOf<String, String>(
"from" to "$supportRoot/buildSrc/apply/applyJetBrainsAndroidXImplPlugin.gradle"
)
)

// Note: Currently we call it unconditionally since Androidx provides the same set of
// Konan targets for all multiplatform libs they publish.
// In the future we might need to call it with non-default konan targets set in some modules
extension.configureKNativeRedirectingDependenciesInKlibManifest()
}

companion object {
Expand All @@ -148,50 +41,3 @@ class JetbrainsAndroidXPlugin : Plugin<Project> {
) {}
}
}

private val Project.multiplatformExtension
get() = extensions.findByType(KotlinMultiplatformExtension::class.java)

fun Project.experimentalArtifactRedirectingPublication() : Boolean = findProperty("artifactRedirecting.publication") == "true"
fun Project.artifactRedirectingAndroidxVersion() : String? = findProperty("artifactRedirecting.androidx.compose.version") as String?
fun Project.artifactRedirectingAndroidxFoundationVersion() : String? = findProperty("artifactRedirecting.androidx.compose.foundation.version") as String?
fun Project.artifactRedirectingAndroidxMaterial3Version() : String? = findProperty("artifactRedirecting.androidx.compose.material3.version") as String?
fun Project.artifactRedirectingAndroidxMaterialVersion() : String? = findProperty("artifactRedirecting.androidx.compose.material.version") as String?

fun enableArtifactRedirectingPublishing(project: Project) {
if (!project.experimentalArtifactRedirectingPublication()) return

if (project.experimentalArtifactRedirectingPublication() && (project.artifactRedirectingAndroidxVersion() == null)) {
error("androidx version should be specified for OEL publications")
}

val ext = project.multiplatformExtension ?: error("expected a multiplatform project")

val redirecting = project.artifactRedirecting()
val newRootComponent: CustomRootComponent = run {
val rootComponent = project
.components
.withType(KotlinSoftwareComponentWithCoordinatesAndPublication::class.java)
.getByName("kotlin")

CustomRootComponent(rootComponent) { configuration ->
val targetName = redirecting.targetVersions.keys.firstOrNull {
// we rely on the fact that configuration name starts with target name
configuration.name.startsWith(it)
}
val targetVersion = redirecting.versionForTargetOrDefault(targetName ?: "")
project.dependencies.create(
redirecting.groupId, project.name, targetVersion
)
}
}

val oelTargetNames = (project.findProperty("artifactRedirecting.publication.targetNames") as? String ?: "")
.split(",").toSet()

ext.targets.all { target ->
if (target.name in oelTargetNames || target is KotlinAndroidTarget) {
project.publishAndroidxReference(target as AbstractKotlinTarget, newRootComponent)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -310,9 +310,6 @@ class AndroidXComposeImplPlugin : Plugin<Project> {
"multiplatformExtension is null (multiplatform plugin not enabled?)"
}

val androidXExtension = project.extensions.findByType(AndroidXExtension::class.java)
?: throw Exception("You have applied AndroidXComposePlugin without AndroidXPlugin")

/*
The following configures source sets - note:
Expand Down Expand Up @@ -344,10 +341,6 @@ class AndroidXComposeImplPlugin : Plugin<Project> {
if (multiplatformExtension.targets.findByName("desktop") != null) {
tasks.named("desktopTestClasses").also(::addToBuildOnServer)
}

if (androidXExtension.type == LibraryType.PUBLISHED_LIBRARY) {
project.apply(plugin = "org.jetbrains.kotlinx.binary-compatibility-validator")
}
}
}
}
Expand Down
Loading

0 comments on commit 79d893b

Please sign in to comment.