From 55cc5e84fc809bd4de3e536cd191d1f4049baf4e Mon Sep 17 00:00:00 2001 From: Sergey Igushkin Date: Tue, 29 Jan 2019 18:32:40 +0300 Subject: [PATCH] Fix publishing dependencies of Android libraries (KT-29476) * Add the extendsFrom relation between the Kotlin MPP compilation's configurations (`*Api`, `*Implementation`, `*RuntimeOnly`) and the Android variant's `*Elements` configurations, as those dependencies currently are not added to the Android source sets and are thus missing from the published dependencies. * Fix a `this is KotlinCompilationToRunnableFiles` check that mistakenly referenced the Project receiver of `whenEvaluated { ... }` Issue #KT-29476 Fixed --- .../AbstractKotlinAndroidGradleTests.kt | 36 ++++++++++++-- .../plugin/android/Android25ProjectHandler.kt | 10 ++++ .../gradle/plugin/mpp/kotlinCompilations.kt | 48 +++++++++---------- 3 files changed, 66 insertions(+), 28 deletions(-) diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/AbstractKotlinAndroidGradleTests.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/AbstractKotlinAndroidGradleTests.kt index 3eb0df162d1..e89944f64f4 100644 --- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/AbstractKotlinAndroidGradleTests.kt +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/AbstractKotlinAndroidGradleTests.kt @@ -140,6 +140,8 @@ class KotlinAndroid32GradleIT : KotlinAndroid3GradleIT(androidGradlePluginVersio // Convert the 'app' project to a library, publish the two without metadata, // check that the dependencies in the POMs are correctly rewritten: + val appGroupDir = "app/build/repo/com/example/" + gradleSettingsScript().modify { it.replace("enableFeaturePreview", "//") } gradleBuildScript("app").modify { it.replace("com.android.application", "com.android.library") @@ -152,19 +154,47 @@ class KotlinAndroid32GradleIT : KotlinAndroid3GradleIT(androidGradlePluginVersio } build("publish") { assertSuccessful() - val appGroupDir = "app/build/repo/com/example/" listOf("foobar", "foobaz").forEach { flavor -> listOf("-debug", "").forEach { buildType -> assertFileExists(appGroupDir + "app-androidapp-$flavor$buildType/1.0/app-androidapp-$flavor$buildType-1.0.aar") assertFileExists(appGroupDir + "app-androidapp-$flavor$buildType/1.0/app-androidapp-$flavor$buildType-1.0-sources.jar") val pomText = projectDir.resolve( appGroupDir + "app-androidapp-$flavor$buildType/1.0/app-androidapp-$flavor$buildType-1.0.pom" - ).readText() - assertTrue { "lib-androidlib-$flavor$buildType" in pomText } + ).readText().replace("\\s+".toRegex(), "") + assertTrue { + "lib-androidlib-$flavor$buildType1.0runtime" in pomText + } } } projectDir.resolve(groupDir).deleteRecursively() } + + // Also check that api and runtimeOnly MPP dependencies get correctly published with the appropriate scope, KT-29476: + gradleBuildScript("app").modify { + it.replace("implementation project(':lib')", "api project(':lib')") + "\n" + """ + kotlin.sourceSets.commonMain.dependencies { + runtimeOnly(kotlin('reflect')) + } + """.trimIndent() + } + build("publish") { + assertSuccessful() + listOf("foobar", "foobaz").forEach { flavor -> + listOf("-debug", "").forEach { buildType -> + val pomText = projectDir.resolve( + appGroupDir + "app-androidapp-$flavor$buildType/1.0/app-androidapp-$flavor$buildType-1.0.pom" + ).readText().replace("\\s+".toRegex(), "") + assertTrue { + "lib-androidlib-$flavor$buildType1.0compile" in pomText + } + assertTrue { + val kotlinVersion = defaultBuildOptions().kotlinVersion + "kotlin-reflect$kotlinVersionruntime" in pomText + } + } + } + } + } @Test diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/android/Android25ProjectHandler.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/android/Android25ProjectHandler.kt index a2f891548fe..0e84e7dfe66 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/android/Android25ProjectHandler.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/android/Android25ProjectHandler.kt @@ -146,6 +146,16 @@ class Android25ProjectHandler( // We should request such API in the Android plugin val apiElementsConfigurationName = "${variant.name}ApiElements" val runtimeElementsConfigurationName = "${variant.name}RuntimeElements" + + // KT-29476, the Android *Elements configurations need Kotlin MPP dependencies: + if (project.configurations.findByName(apiElementsConfigurationName) != null) { + project.addExtendsFromRelation(apiElementsConfigurationName, compilation.apiConfigurationName) + } + if (project.configurations.findByName(runtimeElementsConfigurationName) != null) { + project.addExtendsFromRelation(runtimeElementsConfigurationName, compilation.implementationConfigurationName) + project.addExtendsFromRelation(runtimeElementsConfigurationName, compilation.runtimeOnlyConfigurationName) + } + listOf(apiElementsConfigurationName, runtimeElementsConfigurationName).forEach { outputConfigurationName -> project.configurations.findByName(outputConfigurationName)?.usesPlatformOf(compilation.target) } diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/kotlinCompilations.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/kotlinCompilations.kt index dfffe701b46..1284fe446f3 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/kotlinCompilations.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/kotlinCompilations.kt @@ -104,35 +104,33 @@ abstract class AbstractKotlinCompilation( override fun source(sourceSet: KotlinSourceSet) { if (kotlinSourceSets.add(sourceSet)) { - with(target.project) { - //TODO possibly issue with forced instantiation - whenEvaluated { - sourceSet.getSourceSetHierarchy().forEach { sourceSet -> - val isCommonSource = - CompilationSourceSetUtil.sourceSetsInMultipleCompilations(project)?.contains(sourceSet) ?: false + //TODO possibly issue with forced instantiation + target.project.whenEvaluated { + sourceSet.getSourceSetHierarchy().forEach { sourceSet -> + val isCommonSource = + CompilationSourceSetUtil.sourceSetsInMultipleCompilations(project)?.contains(sourceSet) ?: false - addSourcesToCompileTask(sourceSet, addAsCommonSources = isCommonSource) + addSourcesToCompileTask(sourceSet, addAsCommonSources = isCommonSource) - // Use `forced = false` since `api`, `implementation`, and `compileOnly` may be missing in some cases like - // old Java & Android projects: - addExtendsFromRelation(apiConfigurationName, sourceSet.apiConfigurationName, forced = false) - addExtendsFromRelation(implementationConfigurationName, sourceSet.implementationConfigurationName, forced = false) - addExtendsFromRelation(compileOnlyConfigurationName, sourceSet.compileOnlyConfigurationName, forced = false) + // Use `forced = false` since `api`, `implementation`, and `compileOnly` may be missing in some cases like + // old Java & Android projects: + addExtendsFromRelation(apiConfigurationName, sourceSet.apiConfigurationName, forced = false) + addExtendsFromRelation(implementationConfigurationName, sourceSet.implementationConfigurationName, forced = false) + addExtendsFromRelation(compileOnlyConfigurationName, sourceSet.compileOnlyConfigurationName, forced = false) - if (this is KotlinCompilationToRunnableFiles<*>) { - addExtendsFromRelation(runtimeOnlyConfigurationName, sourceSet.runtimeOnlyConfigurationName, forced = false) - } + if (this@AbstractKotlinCompilation is KotlinCompilationToRunnableFiles<*>) { + addExtendsFromRelation(runtimeOnlyConfigurationName, sourceSet.runtimeOnlyConfigurationName, forced = false) + } - if (sourceSet.name != defaultSourceSetName) { - kotlinExtension.sourceSets.findByName(defaultSourceSetName)?.let { defaultSourceSet -> - // Temporary solution for checking consistency across source sets participating in a compilation that may - // not be interconnected with the dependsOn relation: check the settings as if the default source set of - // the compilation depends on the one added to the compilation: - defaultSourceSetLanguageSettingsChecker.runAllChecks( - defaultSourceSet, - sourceSet - ) - } + if (sourceSet.name != defaultSourceSetName) { + kotlinExtension.sourceSets.findByName(defaultSourceSetName)?.let { defaultSourceSet -> + // Temporary solution for checking consistency across source sets participating in a compilation that may + // not be interconnected with the dependsOn relation: check the settings as if the default source set of + // the compilation depends on the one added to the compilation: + defaultSourceSetLanguageSettingsChecker.runAllChecks( + defaultSourceSet, + sourceSet + ) } } }