Rewrite MPP dependencies in POMs of single-platform projects (KT-27059)

This is needed to ensure that POMs of single-platform Kotlin projects
depending on MPP libraries contain dependencies (Maven coordinates)
of the platform-specific modules of the libraries.

The mechanism and rationale are the same as in KT-28482

Issue #KT-27059 Fixed
This commit is contained in:
Sergey Igushkin
2019-02-14 18:39:18 +03:00
parent 51279a8195
commit 4aaa1a8067
10 changed files with 320 additions and 3 deletions
@@ -15,8 +15,6 @@ import org.jetbrains.kotlin.konan.target.CompilerOutputKind
import org.jetbrains.kotlin.konan.target.HostManager
import org.junit.Assert
import org.junit.Test
import java.io.File
import java.lang.StringBuilder
import java.util.jar.JarFile
import java.util.zip.ZipFile
import kotlin.test.assertEquals
@@ -1618,4 +1616,81 @@ class NewMultiplatformIT : BaseGradleIT() {
assertCompiledKotlinSources(project.relativize(libJsPlatformUtilKt, useLibJsPlatformUtilKt))
}
}
@Test
fun testPomRewritingInSinglePlatformProject() = with(Project("kt-27059-pom-rewriting", GradleVersionRequired.AtLeast("4.10.2"))) {
setupWorkingDir()
gradleBuildScript().modify(::transformBuildScriptWithPluginsDsl)
val groupDir = "build/repo/com/example/"
build(":mpp-lib:publish") {
assertSuccessful()
assertFileExists(groupDir + "mpp-lib")
assertFileExists(groupDir + "mpp-lib-myjvm")
}
fun doTestPomRewriting(mppProjectDependency: Boolean, legacyPublishing: Boolean, keepPomIntact: Boolean? = null) {
val params = mutableListOf("clean", ":jvm-app:publish", ":js-app:publish").apply {
if (mppProjectDependency)
add("-PmppProjectDependency=true")
if (legacyPublishing)
add("-PlegacyPublishing=true")
if (keepPomIntact == true)
add("-Pkotlin.mpp.keepMppDependenciesIntactInPoms=true")
}.toTypedArray()
build(*params) {
assertSuccessful()
if (legacyPublishing) {
assertTasksExecuted(":jvm-app:uploadArchives")
assertTasksExecuted(":js-app:uploadArchives")
} else {
assertTasksExecuted(":jvm-app:publishMainPublicationToMavenRepository")
assertTasksExecuted(":js-app:publishMainPublicationToMavenRepository")
}
val jvmModuleDir = groupDir + "jvm-app/1.0/"
val jsModuleDir = groupDir + "js-app/1.0/"
val jvmPom = fileInWorkingDir(jvmModuleDir + "jvm-app-1.0.pom").readText().replace("\\s+".toRegex(), "")
val jsPom = fileInWorkingDir(jsModuleDir + "js-app-1.0.pom").readText().replace("\\s+".toRegex(), "")
if (keepPomIntact != true) {
assertTrue("The JVM POM should contain the dependency on 'mpp-lib' rewritten as 'mpp-lib-myjvm'") {
jvmPom.contains(
"<groupId>com.example</groupId><artifactId>mpp-lib-myjvm</artifactId><version>1.0</version><scope>compile</scope>"
)
}
assertTrue("The JS POM should contain the dependency on 'mpp-lib' rewritten as 'mpp-lib-js'") {
jsPom.contains(
"<groupId>com.example</groupId><artifactId>mpp-lib-js</artifactId><version>1.0</version><scope>compile</scope>"
)
}
} else {
assertTrue("The JVM POM should contain the original dependency on 'mpp-lib'") {
jvmPom.contains(
"<groupId>com.example</groupId><artifactId>mpp-lib</artifactId><version>1.0</version><scope>compile</scope>"
)
}
assertTrue("The JS POM should contain the original dependency on 'mpp-lib'") {
jsPom.contains(
"<groupId>com.example</groupId><artifactId>mpp-lib</artifactId><version>1.0</version><scope>compile</scope>"
)
}
}
}
}
doTestPomRewriting(mppProjectDependency = false, legacyPublishing = false)
doTestPomRewriting(mppProjectDependency = false, legacyPublishing = true)
doTestPomRewriting(mppProjectDependency = true, legacyPublishing = false)
// This case doesn't work and never did; TODO investigate KT-29975
// doTestPomRewriting(mppProjectDependency = true, legacyPublishing = true)
// Also check that the flag for keeping POMs intact works:
doTestPomRewriting(mppProjectDependency = false, legacyPublishing = false, keepPomIntact = true)
doTestPomRewriting(mppProjectDependency = false, legacyPublishing = true, keepPomIntact = true)
}
}
@@ -0,0 +1,10 @@
plugins {
id "org.jetbrains.kotlin.multiplatform" version "<pluginMarkerVersion>" apply false
}
allprojects {
repositories {
mavenLocal()
jcenter()
}
}
@@ -0,0 +1,62 @@
plugins {
id "kotlin2js"
}
group = "com.example"
version = "1.0"
dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib-js"
}
if (project.findProperty("mppProjectDependency") == "true") {
dependencies {
api project(":mpp-lib")
}
} else {
repositories {
maven { setUrl "${rootProject.buildDir}/repo" }
}
dependencies {
api "com.example:mpp-lib:1.0"
}
}
if (project.findProperty("legacyPublishing") == "true") {
apply plugin: 'maven'
uploadArchives {
repositories {
mavenDeployer {
repository(url: "file://${rootProject.buildDir}/repo")
}
}
}
tasks.create("publish") {
dependsOn uploadArchives
}
} else {
apply plugin: 'maven-publish'
publishing {
publications {
main(MavenPublication) {
from components.java
}
}
repositories {
maven { setUrl("${rootProject.buildDir}/repo") }
}
}
}
@@ -0,0 +1,5 @@
import com.example.mpp.lib.*
fun main() {
println(hello())
}
@@ -0,0 +1,62 @@
plugins {
id "org.jetbrains.kotlin.jvm"
}
group = "com.example"
version = "1.0"
dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib"
}
if (project.findProperty("mppProjectDependency") == "true") {
dependencies {
api project(":mpp-lib")
}
} else {
repositories {
maven { setUrl "${rootProject.buildDir}/repo" }
}
dependencies {
api "com.example:mpp-lib:1.0"
}
}
if (project.findProperty("legacyPublishing") == "true") {
apply plugin: 'maven'
uploadArchives {
repositories {
mavenDeployer {
repository(url: "file://${rootProject.buildDir}/repo")
}
}
}
tasks.create("publish") {
dependsOn uploadArchives
}
} else {
apply plugin: 'maven-publish'
publishing {
publications {
main(MavenPublication) {
from components.java
}
}
repositories {
maven { setUrl("${rootProject.buildDir}/repo") }
}
}
}
@@ -0,0 +1,5 @@
import com.example.mpp.lib.*
fun main() {
println(hello())
}
@@ -0,0 +1,42 @@
plugins {
id "org.jetbrains.kotlin.multiplatform"
id "maven-publish"
}
group = "com.example"
version = "1.0"
kotlin {
jvm()
js()
sourceSets {
commonMain {
dependencies {
implementation 'org.jetbrains.kotlin:kotlin-stdlib-common'
}
}
jvmMain {
dependencies {
implementation 'org.jetbrains.kotlin:kotlin-stdlib'
}
}
jsMain {
dependencies {
implementation 'org.jetbrains.kotlin:kotlin-stdlib-js'
}
}
}
}
publishing {
publications {
jvm {
artifactId = "mpp-lib-myjvm"
}
}
repositories {
maven { setUrl("${rootProject.buildDir}/repo") }
}
}
@@ -0,0 +1,3 @@
package com.example.mpp.lib
fun hello(): String = "hello"
@@ -0,0 +1,18 @@
pluginManagement {
resolutionStrategy {
eachPlugin {
if (requested.id.id == "kotlin2js") {
useModule("org.jetbrains.kotlin:kotlin-gradle-plugin:${requested.version}")
}
}
}
repositories {
mavenLocal()
jcenter()
gradlePluginPortal()
}
}
enableFeaturePreview('GRADLE_METADATA')
include(":mpp-lib", ":jvm-app", ":js-app")
@@ -7,6 +7,7 @@ import groovy.lang.Closure
import org.gradle.api.*
import org.gradle.api.artifacts.ExternalDependency
import org.gradle.api.artifacts.MutableVersionConstraint
import org.gradle.api.artifacts.maven.MavenResolver
import org.gradle.api.attributes.Usage
import org.gradle.api.file.FileCollection
import org.gradle.api.file.SourceDirectorySet
@@ -15,9 +16,12 @@ import org.gradle.api.logging.Logging
import org.gradle.api.plugins.InvalidPluginException
import org.gradle.api.plugins.JavaPlugin
import org.gradle.api.plugins.JavaPluginConvention
import org.gradle.api.publish.PublishingExtension
import org.gradle.api.publish.maven.MavenPublication
import org.gradle.api.tasks.CompileClasspathNormalizer
import org.gradle.api.tasks.Delete
import org.gradle.api.tasks.SourceSet
import org.gradle.api.tasks.Upload
import org.gradle.api.tasks.bundling.AbstractArchiveTask
import org.gradle.api.tasks.compile.AbstractCompile
import org.gradle.api.tasks.compile.JavaCompile
@@ -27,7 +31,6 @@ import org.jetbrains.kotlin.gradle.dsl.KotlinCommonOptions
import org.jetbrains.kotlin.gradle.dsl.KotlinJvmOptionsImpl
import org.jetbrains.kotlin.gradle.dsl.KotlinSingleJavaTargetExtension
import org.jetbrains.kotlin.gradle.dsl.kotlinExtension
import org.jetbrains.kotlin.gradle.internal.Kapt3GradleSubplugin.Companion.getKaptGeneratedClassesDir
import org.jetbrains.kotlin.gradle.internal.Kapt3KotlinGradleSubplugin
import org.jetbrains.kotlin.gradle.internal.KaptVariantData
import org.jetbrains.kotlin.gradle.internal.checkAndroidAnnotationProcessorDependencyUsage
@@ -348,10 +351,41 @@ internal abstract class AbstractKotlinPlugin(
{ compilation -> buildSourceSetProcessor(project, compilation, kotlinPluginVersion) }
)
rewriteMppDependenciesInPom(target)
configureProjectGlobalSettings(project, kotlinPluginVersion)
registry.register(KotlinModelBuilder(kotlinPluginVersion, null))
}
private fun rewriteMppDependenciesInPom(target: KotlinTarget) {
val project = target.project
fun shouldRewritePoms(): Boolean =
PropertiesProvider(project).keepMppDependenciesIntactInPoms != true
project.pluginManager.withPlugin("maven-publish") {
project.extensions.configure(PublishingExtension::class.java) { publishing ->
publishing.publications.withType(MavenPublication::class.java).all { publication ->
publication.pom.withXml { xml ->
if (shouldRewritePoms())
project.rewritePomMppDependenciesToActualTargetModules(xml, target.components.single())
}
}
}
}
project.pluginManager.withPlugin("maven") {
project.tasks.withType(Upload::class.java).all { uploadTask ->
uploadTask.repositories.withType(MavenResolver::class.java).all { mavenResolver ->
mavenResolver.pom.withXml { xml ->
if (shouldRewritePoms())
project.rewritePomMppDependenciesToActualTargetModules(xml, target.components.single())
}
}
}
}
}
companion object {
fun configureProjectGlobalSettings(project: Project, kotlinPluginVersion: String) {
configureDefaultVersionsResolutionStrategy(project, kotlinPluginVersion)
@@ -527,6 +561,7 @@ internal open class KotlinPlugin(
(project.kotlinExtension as KotlinSingleJavaTargetExtension).target = target
project.pluginManager.apply(ScriptingGradleSubplugin::class.java)
super.apply(project)
}
}