Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add release Android target by default for KMP #736

Merged
merged 3 commits into from
Mar 10, 2024
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

## 0.28.0 **UNRELEASED**

- For Kotlin Multiplatform the main plugin will now automatically publish the
`release` variant if the project has an Android target.
- Support specifying the Android variants to publish in `KotlinMultiplatform(...)`.
- Updated minimum supported Gradle, Android Gradle Plugin and Kotlin versions.
- Removed support for the deprecated Kotlin/JS plugin.
- Removed the deprecated `closeAndReleaseRepository` task. Use `releaseRepository`, which
Expand Down
11 changes: 9 additions & 2 deletions docs/what.md
Original file line number Diff line number Diff line change
Expand Up @@ -196,8 +196,10 @@ For projects using the `org.jetbrains.kotlin.multiplatform` plugin.
// - `JavadocJar.None()` don't publish this artifact
// - `JavadocJar.Empty()` publish an emprt jar
// - `JavadocJar.Dokka("dokkaHtml")` when using Kotlin with Dokka, where `dokkaHtml` is the name of the Dokka task that should be used as input
// sources publishing is always enabled by the Kotlin Multiplatform plugin
configure(new KotlinMultiplatform(new JavadocJar.Dokka("dokkaHtml")))
// the second whether to publish a sources jar
// the third parameters configures which Android library variants to publish if this project has an Android target
// defaults to "release" when using the main plugin and nothing for the base plugin
configure(new KotlinMultiplatform(new JavadocJar.Dokka("dokkaHtml"), true, ["debug", "release"]))
}
```

Expand All @@ -215,6 +217,11 @@ For projects using the `org.jetbrains.kotlin.multiplatform` plugin.
// - `JavadocJar.Empty()` publish an emprt jar
// - `JavadocJar.Dokka("dokkaHtml")` when using Kotlin with Dokka, where `dokkaHtml` is the name of the Dokka task that should be used as input
javadocJar = JavadocJar.Dokka("dokkaHtml"),
// whether to publish a sources jar
sourcesJar = true,
// configure which Android library variants to publish if this project has an Android target
// defaults to "release" when using the main plugin and nothing for the base plugin
androidVariantsToPublish = listOf("debug", release"),
))
}
```
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -462,6 +462,112 @@ class MavenPublishPluginPlatformTest {
assertThat(androidReleaseResult).javadocJar().exists()
assertThat(androidReleaseResult).javadocJar().isSigned()

val androidDebugResult = result.withArtifactIdSuffix("android-debug")
assertThat(androidDebugResult).outcome().succeeded()
assertThat(androidDebugResult).artifact("aar").doesNotExist()
assertThat(androidDebugResult).pom().doesNotExist()
assertThat(androidDebugResult).module().doesNotExist()
assertThat(androidDebugResult).sourcesJar().doesNotExist()
assertThat(androidDebugResult).javadocJar().doesNotExist()
}

@TestParameterInjectorTest
fun kotlinMultiplatformWithAndroidLibraryAndSpecifiedVariantsProject(
@TestParameter(valuesProvider = AgpVersionProvider::class) agpVersion: AgpVersion,
@TestParameter(valuesProvider = KotlinVersionProvider::class) kotlinVersion: KotlinVersion,
) {
agpVersion.assumeSupportedJdkAndGradleVersion(gradleVersion)
kotlinVersion.assumeSupportedJdkAndGradleVersion(gradleVersion)

val project = kotlinMultiplatformWithAndroidLibraryAndSpecifiedVariantsProjectSpec(agpVersion, kotlinVersion)
val result = project.run(fixtures, testProjectDir, testOptions)

assertThat(result).outcome().succeeded()
assertThat(result).artifact("jar").exists()
assertThat(result).artifact("jar").isSigned()
assertThat(result).pom().exists()
assertThat(result).pom().isSigned()
assertThat(result).pom().matchesExpectedPom(
kotlinStdlibCommon(kotlinVersion).copy(scope = "runtime"),
)
assertThat(result).module().exists()
assertThat(result).module().isSigned()
assertThat(result).sourcesJar().exists()
assertThat(result).sourcesJar().isSigned()
assertThat(result).sourcesJar().containsSourceSetFiles("commonMain")
assertThat(result).javadocJar().exists()
assertThat(result).javadocJar().isSigned()

val jvmResult = result.withArtifactIdSuffix("jvm")
assertThat(jvmResult).outcome().succeeded()
assertThat(jvmResult).artifact("jar").exists()
assertThat(jvmResult).artifact("jar").isSigned()
assertThat(jvmResult).pom().exists()
assertThat(jvmResult).pom().isSigned()
assertThat(jvmResult).pom().matchesExpectedPom(
kotlinStdlibJdk(kotlinVersion),
kotlinStdlibCommon(kotlinVersion),
)
assertThat(jvmResult).module().exists()
assertThat(jvmResult).module().isSigned()
assertThat(jvmResult).sourcesJar().exists()
assertThat(jvmResult).sourcesJar().isSigned()
assertThat(jvmResult).sourcesJar().containsSourceSetFiles("commonMain", "jvmMain")
assertThat(jvmResult).javadocJar().exists()
assertThat(jvmResult).javadocJar().isSigned()

val linuxResult = result.withArtifactIdSuffix("linux")
assertThat(linuxResult).outcome().succeeded()
assertThat(linuxResult).artifact("klib").exists()
assertThat(linuxResult).artifact("klib").isSigned()
assertThat(linuxResult).pom().exists()
assertThat(linuxResult).pom().isSigned()
assertThat(linuxResult).pom().matchesExpectedPom(
"klib",
kotlinStdlibCommon(kotlinVersion),
)
assertThat(linuxResult).module().exists()
assertThat(linuxResult).module().isSigned()
assertThat(linuxResult).sourcesJar().exists()
assertThat(linuxResult).sourcesJar().isSigned()
assertThat(linuxResult).sourcesJar().containsSourceSetFiles("commonMain", "linuxMain")
assertThat(linuxResult).javadocJar().exists()
assertThat(linuxResult).javadocJar().isSigned()

val nodejsResult = result.withArtifactIdSuffix("nodejs")
assertThat(nodejsResult).outcome().succeeded()
assertThat(nodejsResult).artifact("klib").exists()
assertThat(nodejsResult).artifact("klib").isSigned()
assertThat(nodejsResult).pom().exists()
assertThat(nodejsResult).pom().isSigned()
assertThat(nodejsResult).pom().matchesExpectedPom("klib", kotlinStdlibJs(kotlinVersion), kotlinDomApi(kotlinVersion))
assertThat(nodejsResult).module().exists()
assertThat(nodejsResult).module().isSigned()
assertThat(nodejsResult).sourcesJar().exists()
assertThat(nodejsResult).sourcesJar().isSigned()
assertThat(nodejsResult).sourcesJar().containsSourceSetFiles("commonMain", "nodeJsMain")
assertThat(nodejsResult).javadocJar().exists()
assertThat(nodejsResult).javadocJar().isSigned()

val androidReleaseResult = result.withArtifactIdSuffix("android")
assertThat(androidReleaseResult).outcome().succeeded()
assertThat(androidReleaseResult).artifact("aar").exists()
assertThat(androidReleaseResult).artifact("aar").isSigned()
assertThat(androidReleaseResult).pom().exists()
assertThat(androidReleaseResult).pom().isSigned()
assertThat(androidReleaseResult).pom().matchesExpectedPom(
"aar",
kotlinStdlibJdk(kotlinVersion),
kotlinStdlibCommon(kotlinVersion),
)
assertThat(androidReleaseResult).module().exists()
assertThat(androidReleaseResult).module().isSigned()
assertThat(androidReleaseResult).sourcesJar().exists()
assertThat(androidReleaseResult).sourcesJar().isSigned()
assertThat(androidReleaseResult).sourcesJar().containsSourceSetFiles("commonMain", "androidMain", "androidRelease")
assertThat(androidReleaseResult).javadocJar().exists()
assertThat(androidReleaseResult).javadocJar().isSigned()

val androidDebugResult = result.withArtifactIdSuffix("android-debug")
assertThat(androidDebugResult).outcome().succeeded()
assertThat(androidDebugResult).artifact("aar").exists()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,8 @@ fun kotlinMultiplatformWithAndroidLibraryProjectSpec(agpVersion: AgpVersion, kot
SourceFile("androidDebug", "kotlin", "com/vanniktech/maven/publish/test/ExpectedTestClass.kt"),
SourceFile("androidRelease", "kotlin", "com/vanniktech/maven/publish/test/ExpectedTestClass.kt"),
),
// needs to explicitly specify release to match the main plugin default behavior
basePluginConfig = "configure(new KotlinMultiplatform(new JavadocJar.Empty(), true, [\"release\"]))",
buildFileExtra = baseProject.buildFileExtra + """

android {
Expand All @@ -187,9 +189,7 @@ fun kotlinMultiplatformWithAndroidLibraryProjectSpec(agpVersion: AgpVersion, kot
}

kotlin {
android {
publishLibraryVariants("release", "debug")
}
androidTarget {}

jvmToolchain {
languageVersion.set(JavaLanguageVersion.of("8"))
Expand All @@ -199,6 +199,24 @@ fun kotlinMultiplatformWithAndroidLibraryProjectSpec(agpVersion: AgpVersion, kot
)
}

fun kotlinMultiplatformWithAndroidLibraryAndSpecifiedVariantsProjectSpec(
agpVersion: AgpVersion,
kotlinVersion: KotlinVersion,
): ProjectSpec {
val baseProject = kotlinMultiplatformWithAndroidLibraryProjectSpec(agpVersion, kotlinVersion)
return baseProject.copy(
basePluginConfig = "configure(new KotlinMultiplatform(new JavadocJar.Empty()))",
buildFileExtra = baseProject.buildFileExtra + """

kotlin {
androidTarget {
publishLibraryVariants("release", "debug")
}
}
""".trimIndent(),
)
}

fun androidLibraryProjectSpec(version: AgpVersion) = ProjectSpec(
plugins = listOf(
androidLibraryPlugin.copy(version = version.value),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,13 @@ open class ArtifactSubject internal constructor(
}
}

fun doesNotExist() {
if (artifact.exists()) {
val files = result.repo.toFile().walkTopDown().filter { it.isFile }.toList()
failWithActual(fact("expected not to exist", artifact), fact("but repo contained", files))
}
}

fun isSigned() {
val signedArtifact = artifact.resolveSibling("${artifact.name}.asc")
if (!signedArtifact.exists()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -364,8 +364,17 @@ abstract class MavenPublishBaseExtension(
}

when {
project.plugins.hasPlugin("org.jetbrains.kotlin.multiplatform") ->
configure(KotlinMultiplatform(defaultJavaDocOption(plainJavadocSupported = false)))
project.plugins.hasPlugin("org.jetbrains.kotlin.multiplatform") -> {
val variant = project.findOptionalProperty("ANDROID_VARIANT_TO_PUBLISH") ?: "release"
configure(
KotlinMultiplatform(
javadocJar = defaultJavaDocOption(plainJavadocSupported = false),
sourcesJar = true,
androidVariantsToPublish = listOf(variant),
forceAndroidVariantsIfNotEmpty = false,
),
)
}
project.plugins.hasPlugin("com.android.library") -> {
val variant = project.findOptionalProperty("ANDROID_VARIANT_TO_PUBLISH") ?: "release"
configure(AndroidSingleVariantLibrary(variant))
Expand Down
25 changes: 22 additions & 3 deletions plugin/src/main/kotlin/com/vanniktech/maven/publish/Platform.kt
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import org.gradle.jvm.component.internal.DefaultJvmSoftwareComponent
import org.gradle.jvm.tasks.Jar
import org.gradle.util.GradleVersion
import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinAndroidTarget

/**
* Represents a platform that the plugin supports to publish. For example [JavaLibrary], [AndroidMultiVariantLibrary] or
Expand Down Expand Up @@ -269,10 +270,18 @@ data class AndroidMultiVariantLibrary @JvmOverloads constructor(
*
* This does not include javadoc jars because there are no APIs for that available.
*/
data class KotlinMultiplatform @JvmOverloads constructor(
override val javadocJar: JavadocJar = JavadocJar.Empty(),
override val sourcesJar: Boolean = true,
data class KotlinMultiplatform internal constructor(
override val javadocJar: JavadocJar,
override val sourcesJar: Boolean,
val androidVariantsToPublish: List<String>,
val forceAndroidVariantsIfNotEmpty: Boolean,
) : Platform() {
@JvmOverloads constructor(
javadocJar: JavadocJar = JavadocJar.Empty(),
sourcesJar: Boolean = true,
androidVariantsToPublish: List<String> = emptyList(),
) : this(javadocJar, sourcesJar, androidVariantsToPublish, forceAndroidVariantsIfNotEmpty = true)

override fun configure(project: Project) {
check(project.plugins.hasPlugin("org.jetbrains.kotlin.multiplatform")) {
"Calling configure(KotlinMultiplatform(...)) requires the org.jetbrains.kotlin.multiplatform plugin to be applied"
Expand All @@ -286,6 +295,16 @@ data class KotlinMultiplatform @JvmOverloads constructor(

project.extensions.configure(KotlinMultiplatformExtension::class.java) {
it.withSourcesJar(sourcesJar)

if (androidVariantsToPublish.isNotEmpty()) {
it.targets.configureEach { target ->
if (target is KotlinAndroidTarget) {
if (forceAndroidVariantsIfNotEmpty || target.publishLibraryVariants.isNullOrEmpty()) {
target.publishLibraryVariants = androidVariantsToPublish
}
}
}
}
}
}
}
Expand Down