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.jetbrains.kotlin.konan.target.HostManager
import org.junit.Assert import org.junit.Assert
import org.junit.Test import org.junit.Test
import java.io.File
import java.lang.StringBuilder
import java.util.jar.JarFile import java.util.jar.JarFile
import java.util.zip.ZipFile import java.util.zip.ZipFile
import kotlin.test.assertEquals import kotlin.test.assertEquals
@@ -1618,4 +1616,81 @@ class NewMultiplatformIT : BaseGradleIT() {
assertCompiledKotlinSources(project.relativize(libJsPlatformUtilKt, useLibJsPlatformUtilKt)) 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.*
import org.gradle.api.artifacts.ExternalDependency import org.gradle.api.artifacts.ExternalDependency
import org.gradle.api.artifacts.MutableVersionConstraint import org.gradle.api.artifacts.MutableVersionConstraint
import org.gradle.api.artifacts.maven.MavenResolver
import org.gradle.api.attributes.Usage import org.gradle.api.attributes.Usage
import org.gradle.api.file.FileCollection import org.gradle.api.file.FileCollection
import org.gradle.api.file.SourceDirectorySet 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.InvalidPluginException
import org.gradle.api.plugins.JavaPlugin import org.gradle.api.plugins.JavaPlugin
import org.gradle.api.plugins.JavaPluginConvention 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.CompileClasspathNormalizer
import org.gradle.api.tasks.Delete import org.gradle.api.tasks.Delete
import org.gradle.api.tasks.SourceSet import org.gradle.api.tasks.SourceSet
import org.gradle.api.tasks.Upload
import org.gradle.api.tasks.bundling.AbstractArchiveTask import org.gradle.api.tasks.bundling.AbstractArchiveTask
import org.gradle.api.tasks.compile.AbstractCompile import org.gradle.api.tasks.compile.AbstractCompile
import org.gradle.api.tasks.compile.JavaCompile 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.KotlinJvmOptionsImpl
import org.jetbrains.kotlin.gradle.dsl.KotlinSingleJavaTargetExtension import org.jetbrains.kotlin.gradle.dsl.KotlinSingleJavaTargetExtension
import org.jetbrains.kotlin.gradle.dsl.kotlinExtension 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.Kapt3KotlinGradleSubplugin
import org.jetbrains.kotlin.gradle.internal.KaptVariantData import org.jetbrains.kotlin.gradle.internal.KaptVariantData
import org.jetbrains.kotlin.gradle.internal.checkAndroidAnnotationProcessorDependencyUsage import org.jetbrains.kotlin.gradle.internal.checkAndroidAnnotationProcessorDependencyUsage
@@ -348,10 +351,41 @@ internal abstract class AbstractKotlinPlugin(
{ compilation -> buildSourceSetProcessor(project, compilation, kotlinPluginVersion) } { compilation -> buildSourceSetProcessor(project, compilation, kotlinPluginVersion) }
) )
rewriteMppDependenciesInPom(target)
configureProjectGlobalSettings(project, kotlinPluginVersion) configureProjectGlobalSettings(project, kotlinPluginVersion)
registry.register(KotlinModelBuilder(kotlinPluginVersion, null)) 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 { companion object {
fun configureProjectGlobalSettings(project: Project, kotlinPluginVersion: String) { fun configureProjectGlobalSettings(project: Project, kotlinPluginVersion: String) {
configureDefaultVersionsResolutionStrategy(project, kotlinPluginVersion) configureDefaultVersionsResolutionStrategy(project, kotlinPluginVersion)
@@ -527,6 +561,7 @@ internal open class KotlinPlugin(
(project.kotlinExtension as KotlinSingleJavaTargetExtension).target = target (project.kotlinExtension as KotlinSingleJavaTargetExtension).target = target
project.pluginManager.apply(ScriptingGradleSubplugin::class.java) project.pluginManager.apply(ScriptingGradleSubplugin::class.java)
super.apply(project) super.apply(project)
} }
} }