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
This commit is contained in:
+33
-3
@@ -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 { "<artifactId>lib-androidlib-$flavor$buildType</artifactId>" in pomText }
|
||||
).readText().replace("\\s+".toRegex(), "")
|
||||
assertTrue {
|
||||
"<artifactId>lib-androidlib-$flavor$buildType</artifactId><version>1.0</version><scope>runtime</scope>" 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 {
|
||||
"<artifactId>lib-androidlib-$flavor$buildType</artifactId><version>1.0</version><scope>compile</scope>" in pomText
|
||||
}
|
||||
assertTrue {
|
||||
val kotlinVersion = defaultBuildOptions().kotlinVersion
|
||||
"<artifactId>kotlin-reflect</artifactId><version>$kotlinVersion</version><scope>runtime</scope>" in pomText
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
+10
@@ -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)
|
||||
}
|
||||
|
||||
+23
-25
@@ -104,35 +104,33 @@ abstract class AbstractKotlinCompilation<T : KotlinCommonOptions>(
|
||||
|
||||
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
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user