mirror of
https://github.com/jlengrand/kotlin.git
synced 2026-03-10 08:31:29 +00:00
Add (and disable) metadata compilation for single backend source sets
KotlinProjectStructureMetadata is created by inspecting source sets with metadata compilation. Single backend common source sets are currently not supported for metadata compilation and therefore did not register one. Foreseeing to support this case with KT-42468, metadata compilation is now created and registered, but just disabled. This change will include android variants in KotlinProjectStructureMetadata even when not officially published. With those variants, the IDE can infer visibility from some module's "jvmAndAndroidMain" source set to another modules "jvmAndAndroidMain" KotlinMetadataTargetConfigurator: rename getPublishedCommonSourceSets to getCommonSourceSetsForMetadataCompilation KotlinMetadataTargetConfigurator: isMetadataCompilationSupported and add comment to getPublishedCommonSourceSets Re-use androidPluginIds in KotlinPlugin KotlinAndroidTarget: Create KotlinComponents for non-published variants and mark them with publishable=false JvmAndAndroidIntermediateSourceSetTest: add KotlinProjectStructureMetadata jvmAndAndroidMain exists in jvm variants test AbstractAndroidProjectHandler: Add java sources only in post processing KotlinAndroidTarget: Inline creation of usageContexts KotlinAndroidTarget.doCreateComponents: filter non-publishable variants when publishLibraryVariantsGroupedByFlavor is enabled #KT-42383 fixed
This commit is contained in:
committed by
Sebastian Sellmair
parent
03e63f1103
commit
96352b9c8c
2
.idea/codeStyles/Project.xml
generated
2
.idea/codeStyles/Project.xml
generated
@@ -101,4 +101,4 @@
|
||||
<option name="ALIGN_MULTILINE_PARAMETERS_IN_CALLS" value="true" />
|
||||
</codeStyleSettings>
|
||||
</code_scheme>
|
||||
</component>
|
||||
</component>
|
||||
|
||||
2
.idea/inspectionProfiles/idea_default.xml
generated
2
.idea/inspectionProfiles/idea_default.xml
generated
@@ -453,4 +453,4 @@
|
||||
<option name="ignoreNonEmtpyLoops" value="false" />
|
||||
</inspection_tool>
|
||||
</profile>
|
||||
</component>
|
||||
</component>
|
||||
|
||||
@@ -0,0 +1,128 @@
|
||||
/*
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
@file:Suppress("invisible_reference", "invisible_member", "FunctionName", "DuplicatedCode")
|
||||
|
||||
package org.jetbrains.kotlin.gradle
|
||||
|
||||
import com.android.build.gradle.LibraryExtension
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.api.internal.project.ProjectInternal
|
||||
import org.gradle.api.plugins.ExtraPropertiesExtension
|
||||
import org.gradle.testfixtures.ProjectBuilder
|
||||
import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension
|
||||
import org.jetbrains.kotlin.gradle.dsl.multiplatformExtension
|
||||
import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet
|
||||
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinAndroidTarget
|
||||
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinMetadataCompilation
|
||||
import org.jetbrains.kotlin.gradle.plugin.mpp.buildKotlinProjectStructureMetadata
|
||||
import kotlin.test.*
|
||||
|
||||
class JvmAndAndroidIntermediateSourceSetTest {
|
||||
|
||||
private lateinit var project: ProjectInternal
|
||||
private lateinit var kotlin: KotlinMultiplatformExtension
|
||||
private lateinit var jvmAndAndroidMain: KotlinSourceSet
|
||||
|
||||
@BeforeTest
|
||||
fun setup() {
|
||||
project = ProjectBuilder.builder().build() as ProjectInternal
|
||||
project.extensions.getByType(ExtraPropertiesExtension::class.java).set("kotlin.mpp.enableGranularSourceSetsMetadata", "true")
|
||||
|
||||
project.plugins.apply("kotlin-multiplatform")
|
||||
project.plugins.apply("android-library")
|
||||
|
||||
/* Arbitrary minimal Android setup */
|
||||
val android = project.extensions.getByName("android") as LibraryExtension
|
||||
android.compileSdkVersion(30)
|
||||
|
||||
/* Kotlin Setup */
|
||||
kotlin = project.multiplatformExtension
|
||||
kotlin.jvm()
|
||||
kotlin.android()
|
||||
jvmAndAndroidMain = kotlin.sourceSets.create("jvmAndAndroidMain")
|
||||
kotlin.sourceSets.run {
|
||||
jvmAndAndroidMain.dependsOn(getByName("commonMain"))
|
||||
|
||||
getByName("jvmMain") {
|
||||
it.dependsOn(jvmAndAndroidMain)
|
||||
}
|
||||
getByName("androidMain") {
|
||||
it.dependsOn(jvmAndAndroidMain)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `metadata compilation is created and disabled`() {
|
||||
/* evaluate */
|
||||
project.evaluate()
|
||||
|
||||
/* Check if compilation is created correctly */
|
||||
val jvmAndAndroidMainMetadataCompilations = kotlin.targets.flatMap { it.compilations }
|
||||
.filterIsInstance<KotlinMetadataCompilation<*>>()
|
||||
.filter { it.name == jvmAndAndroidMain.name }
|
||||
|
||||
assertEquals(
|
||||
1, jvmAndAndroidMainMetadataCompilations.size,
|
||||
"Expected exactly one metadata compilation created for jvmAndAndroidMain source set"
|
||||
)
|
||||
|
||||
val compilation = jvmAndAndroidMainMetadataCompilations.single()
|
||||
assertFalse(
|
||||
compilation.compileKotlinTaskProvider.get().enabled,
|
||||
"Expected compilation task to be disabled, because not supported yet"
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `KotlinProjectStructureMetadata jvmAndAndroidMain exists in jvm variants`() {
|
||||
project.evaluate()
|
||||
val metadata = assertNotNull(buildKotlinProjectStructureMetadata(project))
|
||||
assertTrue("jvmAndAndroidMain" in metadata.sourceSetNamesByVariantName["jvmApiElements"].orEmpty())
|
||||
assertTrue("jvmAndAndroidMain" in metadata.sourceSetNamesByVariantName["jvmRuntimeElements"].orEmpty())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `KotlinProjectStructureMetadata jvmAndAndroidMain exists in android variants`() {
|
||||
project.evaluate()
|
||||
val metadata = assertNotNull(buildKotlinProjectStructureMetadata(project))
|
||||
assertTrue("jvmAndAndroidMain" in metadata.sourceSetNamesByVariantName["debugApiElements"].orEmpty())
|
||||
assertTrue("jvmAndAndroidMain" in metadata.sourceSetNamesByVariantName["debugRuntimeElements"].orEmpty())
|
||||
assertTrue("jvmAndAndroidMain" in metadata.sourceSetNamesByVariantName["releaseApiElements"].orEmpty())
|
||||
assertTrue("jvmAndAndroidMain" in metadata.sourceSetNamesByVariantName["releaseRuntimeElements"].orEmpty())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `Android Kotlin Components are marked as not publishable when variant is not published`() {
|
||||
val target = kotlin.targets.getByName("android") as KotlinAndroidTarget
|
||||
target.publishLibraryVariants = emptyList()
|
||||
project.evaluate()
|
||||
val kotlinComponents = target.kotlinComponents
|
||||
assertTrue(kotlinComponents.isNotEmpty(), "Expected at least one KotlinComponent to be present")
|
||||
|
||||
kotlinComponents.forEach { component ->
|
||||
assertFalse(component.publishable, "Expected component to not publishable, because no publication is configured")
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `Android Kotlin Components are marked as publishable when variant is published`() {
|
||||
val target = kotlin.targets.getByName("android") as KotlinAndroidTarget
|
||||
target.publishLibraryVariants = listOf("release")
|
||||
project.evaluate()
|
||||
val kotlinComponents = target.kotlinComponents
|
||||
assertTrue(kotlinComponents.isNotEmpty(), "Expected at least one KotlinComponent to be present")
|
||||
|
||||
kotlinComponents.forEach { component ->
|
||||
val isReleaseComponent = "release" in component.name.toLowerCase()
|
||||
if (isReleaseComponent) {
|
||||
assertTrue(component.publishable, "Expected release component to be marked as publishable")
|
||||
} else {
|
||||
assertFalse(component.publishable, "Expected non-release component to be marked as not publishable")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,7 @@
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
// TODO KT-34102
|
||||
@file:Suppress("invisible_reference", "invisible_member")
|
||||
@file:Suppress("invisible_reference", "invisible_member", "FunctionName")
|
||||
package org.jetbrains.kotlin.gradle
|
||||
|
||||
import com.android.build.gradle.LibraryExtension
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
|
||||
/*
|
||||
* Copyright 2010-2016 JetBrains s.r.o.
|
||||
*
|
||||
@@ -28,6 +27,8 @@ import org.jetbrains.kotlin.gradle.dsl.kotlinExtension
|
||||
import org.jetbrains.kotlin.gradle.logging.kotlinWarn
|
||||
import org.jetbrains.kotlin.gradle.tasks.AbstractKotlinCompile
|
||||
import org.jetbrains.kotlin.gradle.utils.SingleWarningPerBuild
|
||||
import org.jetbrains.kotlin.gradle.utils.androidPluginIds
|
||||
import java.util.concurrent.atomic.AtomicBoolean
|
||||
|
||||
abstract class KotlinPlatformPluginBase(protected val platformName: String) : Plugin<Project> {
|
||||
companion object {
|
||||
@@ -182,6 +183,7 @@ open class KotlinPlatformImplementationPluginBase(platformName: String) : Kotlin
|
||||
private fun getKotlinSourceSetsSafe(project: Project): NamedDomainObjectCollection<out Named> {
|
||||
// Access through reflection, because another project's KotlinProjectExtension might be loaded by a different class loader:
|
||||
val kotlinExt = project.extensions.getByName("kotlin")
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
val sourceSets = kotlinExt.javaClass.getMethod("getSourceSets").invoke(kotlinExt) as NamedDomainObjectCollection<out Named>
|
||||
return sourceSets
|
||||
@@ -210,8 +212,24 @@ open class KotlinPlatformImplementationPluginBase(platformName: String) : Kotlin
|
||||
internal fun <T> Project.whenEvaluated(fn: Project.() -> T) {
|
||||
if (state.executed) {
|
||||
fn()
|
||||
} else {
|
||||
afterEvaluate { it.fn() }
|
||||
return
|
||||
}
|
||||
|
||||
/* Make sure that all afterEvaluate blocks from the AndroidPlugin get scheduled first */
|
||||
val isDispatched = AtomicBoolean(false)
|
||||
androidPluginIds.forEach { androidPluginId ->
|
||||
pluginManager.withPlugin(androidPluginId) {
|
||||
if (!isDispatched.getAndSet(true)) {
|
||||
afterEvaluate { fn() }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
afterEvaluate {
|
||||
/* If no Android plugin was loaded, then the action was not dispatched and we can freely execute it now */
|
||||
if (!isDispatched.getAndSet(true)) {
|
||||
fn()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -263,4 +281,4 @@ private fun warnAboutKotlin12xMppDeprecation(project: Project) {
|
||||
if (project.findProperty(KOTLIN_12X_MPP_DEPRECATION_SUPPRESS_FLAG) != "true") {
|
||||
SingleWarningPerBuild.show(project, KOTLIN_12X_MPP_DEPRECATION_WARNING)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -796,11 +796,6 @@ abstract class AbstractAndroidProjectHandler(private val kotlinConfigurationTool
|
||||
kotlinOptions.noJdk = true
|
||||
ext.addExtension(KOTLIN_OPTIONS_DSL_NAME, kotlinOptions)
|
||||
|
||||
val androidPluginIds = listOf(
|
||||
"android", "com.android.application", "android-library", "com.android.library",
|
||||
"com.android.test", "com.android.feature", "com.android.dynamic-feature", "com.android.instantapp"
|
||||
)
|
||||
|
||||
val plugin by lazy {
|
||||
androidPluginIds.asSequence()
|
||||
.mapNotNull { project.plugins.findPlugin(it) as? BasePlugin }
|
||||
@@ -904,6 +899,7 @@ abstract class AbstractAndroidProjectHandler(private val kotlinConfigurationTool
|
||||
|
||||
// Trivial mapping of Android variants to Android source set names is impossible here,
|
||||
// because some variants have their dedicated source sets with mismatching names,
|
||||
// because some variants have their dedicated source sets with mismatching names,
|
||||
// e.g. variant 'fooBarDebugAndroidTest' <-> source set 'androidTestFooBarDebug'
|
||||
|
||||
// In single-platform projects, the Kotlin compilations already reference the Android plugin's configurations by the names,
|
||||
@@ -974,6 +970,8 @@ abstract class AbstractAndroidProjectHandler(private val kotlinConfigurationTool
|
||||
|
||||
// Register the source only after the task is created, because the task is required for that:
|
||||
compilation.source(defaultSourceSet)
|
||||
|
||||
compilation.androidVariant.forEachKotlinSourceSet { kotlinSourceSet -> compilation.source(kotlinSourceSet) }
|
||||
}
|
||||
|
||||
private fun postprocessVariant(
|
||||
@@ -983,7 +981,6 @@ abstract class AbstractAndroidProjectHandler(private val kotlinConfigurationTool
|
||||
androidExt: BaseExtension,
|
||||
androidPlugin: BasePlugin
|
||||
) {
|
||||
val javaTask = variantData.getJavaTaskProvider()
|
||||
|
||||
getTestedVariantData(variantData)?.let { testedVariant ->
|
||||
val testedVariantName = getVariantName(testedVariant)
|
||||
@@ -991,34 +988,24 @@ abstract class AbstractAndroidProjectHandler(private val kotlinConfigurationTool
|
||||
compilation.associateWith(testedCompilation)
|
||||
}
|
||||
|
||||
val javaTask = variantData.getJavaTaskProvider()
|
||||
val kotlinTask = compilation.compileKotlinTaskProvider
|
||||
processAndroidKotlinAndJavaSources(
|
||||
compilation,
|
||||
addKotlinSources = { kotlinSourceSet -> compilation.source(kotlinSourceSet) },
|
||||
addJavaSources = { sources -> compilation.compileKotlinTaskProvider.configure { it.source(sources) } }
|
||||
)
|
||||
compilation.androidVariant.forEachJavaSourceDir { sources -> kotlinTask.configure { it.source(sources) } }
|
||||
wireKotlinTasks(project, compilation, androidPlugin, androidExt, variantData, javaTask, kotlinTask)
|
||||
}
|
||||
}
|
||||
|
||||
private fun getAllJavaSources(variantData: BaseVariant): Iterable<File> =
|
||||
variantData.getSourceFolders(SourceKind.JAVA).map { it.dir }
|
||||
|
||||
internal fun processAndroidKotlinAndJavaSources(
|
||||
compilation: KotlinJvmAndroidCompilation,
|
||||
addKotlinSources: (KotlinSourceSet) -> Unit,
|
||||
addJavaSources: (Iterable<File>) -> Unit
|
||||
) {
|
||||
val variantData = compilation.androidVariant
|
||||
|
||||
for (provider in variantData.sourceSets) {
|
||||
val kotlinSourceSet = provider.getConvention(KOTLIN_DSL_NAME) as? KotlinSourceSet ?: continue
|
||||
addKotlinSources(kotlinSourceSet)
|
||||
}
|
||||
|
||||
addJavaSources(getAllJavaSources(variantData))
|
||||
internal inline fun BaseVariant.forEachKotlinSourceSet(action: (KotlinSourceSet) -> Unit) {
|
||||
sourceSets
|
||||
.mapNotNull { provider -> provider.getConvention(KOTLIN_DSL_NAME) as? KotlinSourceSet }
|
||||
.forEach(action)
|
||||
}
|
||||
|
||||
internal inline fun BaseVariant.forEachJavaSourceDir(action: (File) -> Unit) {
|
||||
getSourceFolders(SourceKind.JAVA).map { it.dir }.forEach(action)
|
||||
}
|
||||
|
||||
|
||||
internal fun configureJavaTask(
|
||||
kotlinTaskProvider: TaskProvider<out KotlinCompile>,
|
||||
javaTaskProvider: TaskProvider<out AbstractCompile>
|
||||
|
||||
@@ -486,4 +486,4 @@ fun Configuration.usesPlatformOf(target: KotlinTarget): Configuration {
|
||||
attributes.attribute(KotlinNativeTarget.konanTargetAttribute, target.konanTarget.name)
|
||||
}
|
||||
return this
|
||||
}
|
||||
}
|
||||
|
||||
@@ -51,12 +51,8 @@ internal fun Project.runOnceAfterEvaluated(name: String, task: TaskProvider<*>,
|
||||
}
|
||||
|
||||
internal fun Project.runOnceAfterEvaluated(runOnce: RunOnceAfterEvaluated, task: TaskProvider<*>) {
|
||||
if (state.executed) {
|
||||
runOnce.onEvaluated()
|
||||
} else {
|
||||
afterEvaluate { runOnce.onEvaluated() }
|
||||
}
|
||||
whenEvaluated { runOnce.onEvaluated() }
|
||||
task.configure {
|
||||
runOnce.onConfigure()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -114,11 +114,8 @@ class SubpluginEnvironment(
|
||||
|
||||
internal fun addCompilationSourcesToExternalCompileTask(compilation: KotlinCompilation<*>, task: TaskProvider<out AbstractCompile>) {
|
||||
if (compilation is KotlinJvmAndroidCompilation) {
|
||||
processAndroidKotlinAndJavaSources(
|
||||
compilation,
|
||||
addKotlinSources = { sourceSet -> task.configure { it.source(sourceSet.kotlin) } },
|
||||
addJavaSources = { sources -> task.configure { it.source(sources) }}
|
||||
)
|
||||
compilation.androidVariant.forEachKotlinSourceSet { sourceSet -> task.configure { it.source(sourceSet.kotlin) } }
|
||||
compilation.androidVariant.forEachJavaSourceDir { sources -> task.configure { it.source(sources) } }
|
||||
} else {
|
||||
task.configure { taskInstance ->
|
||||
compilation.allKotlinSourceSets.forEach { sourceSet -> taskInstance.source(sourceSet.kotlin) }
|
||||
@@ -174,4 +171,4 @@ internal fun findJavaTaskForKotlinCompilation(compilation: KotlinCompilation<*>)
|
||||
is KotlinWithJavaCompilation -> compilation.compileJavaTaskProvider
|
||||
is KotlinJvmCompilation -> compilation.compileJavaTaskProvider // may be null for Kotlin-only JVM target in MPP
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,4 +38,4 @@ class KotlinCommonCompilation(
|
||||
val friendSourceSets = getVisibleSourceSetsFromAssociateCompilations(target.project, defaultSourceSet)
|
||||
project.files(friendSourceSets.mapNotNull { target.compilations.findByName(it.name)?.output?.classesDirs })
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -139,4 +139,4 @@ private fun Project.resolvableConfigurationFromCompilationByScope(
|
||||
}
|
||||
|
||||
return project.configurations.getByName(configurationName)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -363,4 +363,4 @@ internal object CompilationSourceSetUtil {
|
||||
private val invalidModuleNameCharactersRegex = """[\\/\r\n\t]""".toRegex()
|
||||
|
||||
private fun filterModuleName(moduleName: String): String =
|
||||
moduleName.replace(invalidModuleNameCharactersRegex, "_")
|
||||
moduleName.replace(invalidModuleNameCharactersRegex, "_")
|
||||
|
||||
@@ -238,4 +238,4 @@ abstract class KotlinOnlyTarget<T : KotlinCompilation<*>>(
|
||||
|
||||
override var disambiguationClassifier: String? = null
|
||||
internal set
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@ import org.jetbrains.kotlin.gradle.plugin.LanguageSettingsBuilder
|
||||
import org.jetbrains.kotlin.gradle.plugin.mpp.*
|
||||
import org.jetbrains.kotlin.gradle.plugin.mpp.GranularMetadataTransformation
|
||||
import org.jetbrains.kotlin.gradle.plugin.mpp.MetadataDependencyResolution
|
||||
import org.jetbrains.kotlin.gradle.plugin.whenEvaluated
|
||||
import org.jetbrains.kotlin.gradle.utils.*
|
||||
import java.io.File
|
||||
import java.lang.reflect.Constructor
|
||||
@@ -84,7 +85,7 @@ class DefaultKotlinSourceSet(
|
||||
// Fail-fast approach: check on each new added edge and report a circular dependency at once when the edge is added.
|
||||
checkForCircularDependencies()
|
||||
|
||||
project.afterEvaluate { defaultSourceSetLanguageSettingsChecker.runAllChecks(this, other) }
|
||||
project.whenEvaluated { defaultSourceSetLanguageSettingsChecker.runAllChecks(this@DefaultKotlinSourceSet, other) }
|
||||
}
|
||||
|
||||
private val dependsOnSourceSetsImpl = mutableSetOf<KotlinSourceSet>()
|
||||
@@ -247,4 +248,4 @@ private fun <T> Class<T>.constructorOrNull(vararg parameterTypes: Class<*>): Con
|
||||
getConstructor(*parameterTypes)
|
||||
} catch (e: NoSuchMethodException) {
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,7 +43,9 @@ open class KotlinAndroidTarget(
|
||||
* all library variants will be published, but not test or application variants. */
|
||||
var publishLibraryVariants: List<String>? = listOf()
|
||||
// Workaround for Groovy GString items in a list:
|
||||
set(value) { field = value?.map(Any::toString) }
|
||||
set(value) {
|
||||
field = value?.map(Any::toString)
|
||||
}
|
||||
|
||||
/** Add Android library variant names to [publishLibraryVariants]. */
|
||||
fun publishLibraryVariants(vararg names: String) {
|
||||
@@ -91,11 +93,16 @@ open class KotlinAndroidTarget(
|
||||
KotlinAndroidPlugin.androidTargetHandler(project.getKotlinPluginVersion()!!, this).doCreateComponents()
|
||||
}
|
||||
|
||||
private fun isVariantPublished(variant: BaseVariant): Boolean {
|
||||
return publishLibraryVariants?.contains(getVariantName(variant)) ?: true
|
||||
}
|
||||
|
||||
private fun AbstractAndroidProjectHandler.doCreateComponents(): Set<KotlinTargetComponent> {
|
||||
|
||||
val publishableVariants = mutableListOf<BaseVariant>()
|
||||
.apply { project.forEachVariant { add(it) } }
|
||||
.toList() // Defensive copy against unlikely modification by the lambda that captures the list above in forEachVariant { }
|
||||
.filter { getLibraryOutputTask(it) != null && publishLibraryVariants?.contains(getVariantName(it)) ?: true }
|
||||
.filter { getLibraryOutputTask(it) != null }
|
||||
|
||||
val publishableVariantGroups = publishableVariants.groupBy { variant ->
|
||||
val flavorNames = getFlavorNames(variant)
|
||||
@@ -118,12 +125,12 @@ open class KotlinAndroidTarget(
|
||||
|
||||
val artifactClassifier = buildTypeName.takeIf { it != "release" && publishLibraryVariantsGroupedByFlavor }
|
||||
|
||||
val usageContexts = createAndroidUsageContexts(androidVariant, compilation, artifactClassifier)
|
||||
createKotlinVariant(
|
||||
lowerCamelCaseName(compilation.target.name, *flavorGroupNameParts.toTypedArray()),
|
||||
compilation,
|
||||
usageContexts
|
||||
createAndroidUsageContexts(androidVariant, compilation, artifactClassifier)
|
||||
).apply {
|
||||
publishable = isVariantPublished(androidVariant)
|
||||
sourcesArtifacts = setOf(
|
||||
sourcesJarArtifact(
|
||||
compilation, compilation.disambiguateName(""),
|
||||
@@ -148,10 +155,10 @@ open class KotlinAndroidTarget(
|
||||
|
||||
if (publishLibraryVariantsGroupedByFlavor) {
|
||||
JointAndroidKotlinTargetComponent(
|
||||
this@KotlinAndroidTarget,
|
||||
nestedVariants,
|
||||
flavorGroupNameParts,
|
||||
nestedVariants.flatMap { it.sourcesArtifacts }.toSet()
|
||||
target = this@KotlinAndroidTarget,
|
||||
nestedVariants = nestedVariants.filter { it.publishable }.toSet(),
|
||||
flavorNames = flavorGroupNameParts,
|
||||
sourcesArtifacts = nestedVariants.filter { it.publishable }.flatMap { it.sourcesArtifacts }.toSet()
|
||||
)
|
||||
} else {
|
||||
nestedVariants.single()
|
||||
@@ -195,4 +202,4 @@ open class KotlinAndroidTarget(
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -70,4 +70,4 @@ class ParcelizeSubplugin : KotlinCompilerPluginSupportPlugin {
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -88,4 +88,4 @@ class KotlinJsDcePlugin : Plugin<Project> {
|
||||
private const val DCE_TASK_PREFIX = "runDce"
|
||||
private const val DEFAULT_OUT_DIR = "kotlin-js-min"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -98,4 +98,4 @@ internal fun jsPluginDeprecationMessage(id: String): String =
|
||||
The `$id` Gradle plugin has been deprecated.
|
||||
Please use `org.jetbrains.kotlin.js` plugin instead `kotlin2js` and `org.jetbrains.kotlin.frontend`
|
||||
For usage details, see https://kotlinlang.org/docs/reference/js-project-setup.html
|
||||
""".trimIndent()
|
||||
""".trimIndent()
|
||||
|
||||
@@ -128,4 +128,4 @@ class KotlinJsSingleTargetPreset(
|
||||
override fun createKotlinTargetConfigurator() = KotlinJsTargetConfigurator(
|
||||
kotlinPluginVersion
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -256,4 +256,4 @@ abstract class KotlinJsIrSubTarget(
|
||||
|
||||
const val PREPARE_JS_LIBRARY_TASK_NAME = "prepare"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -94,4 +94,4 @@ class KotlinJsIrSingleTargetPreset(
|
||||
|
||||
override fun createKotlinTargetConfigurator(): KotlinOnlyTargetConfigurator<KotlinJsIrCompilation, KotlinJsIrTarget> =
|
||||
KotlinJsIrTargetConfigurator(kotlinPluginVersion)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -127,4 +127,4 @@ internal class KotlinProjectNpmResolver(
|
||||
*/
|
||||
internal fun <T : Task, R : Any> TaskCollection<T>.implementing(kclass: KClass<R>): TaskCollection<T> =
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
withType(kclass.java as Class<T>)
|
||||
withType(kclass.java as Class<T>)
|
||||
|
||||
@@ -166,4 +166,4 @@ abstract class KotlinJsSubTarget(
|
||||
companion object {
|
||||
const val RUN_TASK_NAME = "run"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -76,4 +76,4 @@ class KotlinJvmTargetConfigurator(kotlinPluginVersion: String) :
|
||||
val tasksProvider = KotlinTasksProvider(compilation.target.targetName)
|
||||
return Kotlin2JvmSourceSetProcessor(tasksProvider, compilation, kotlinPluginVersion)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -77,4 +77,4 @@ import org.jetbrains.kotlin.gradle.tasks.AbstractKotlinCompile
|
||||
|
||||
val compileJavaTaskProvider: TaskProvider<out JavaCompile>
|
||||
get() = target.project.tasks.withType(JavaCompile::class.java).named(javaSourceSet.compileJavaTaskName)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@ import org.jetbrains.kotlin.gradle.dsl.kotlinExtension
|
||||
import org.jetbrains.kotlin.gradle.dsl.multiplatformExtension
|
||||
import org.jetbrains.kotlin.gradle.plugin.*
|
||||
import org.jetbrains.kotlin.gradle.plugin.mpp.*
|
||||
import org.jetbrains.kotlin.gradle.plugin.mpp.CompilationSourceSetUtil.compilationsBySourceSets
|
||||
import org.jetbrains.kotlin.gradle.plugin.sources.*
|
||||
import org.jetbrains.kotlin.gradle.plugin.statistics.KotlinBuildStatsService
|
||||
import org.jetbrains.kotlin.gradle.tasks.*
|
||||
@@ -163,7 +164,7 @@ class KotlinMetadataTargetConfigurator(kotlinPluginVersion: String) :
|
||||
|
||||
private fun setupDependencyTransformationForCommonSourceSets(target: KotlinMetadataTarget) {
|
||||
target.project.whenEvaluated {
|
||||
val publishedCommonSourceSets: Set<KotlinSourceSet> = getPublishedCommonSourceSets(project)
|
||||
val publishedCommonSourceSets: Set<KotlinSourceSet> = getCommonSourceSetsForMetadataCompilation(project)
|
||||
|
||||
kotlinExtension.sourceSets.all {
|
||||
setupDependencyTransformationForSourceSet(target.project, it, it in publishedCommonSourceSets)
|
||||
@@ -177,12 +178,17 @@ class KotlinMetadataTargetConfigurator(kotlinPluginVersion: String) :
|
||||
) = target.project.whenEvaluated {
|
||||
// Do this after all targets are configured by the user build script
|
||||
|
||||
val publishedCommonSourceSets: Set<KotlinSourceSet> = getPublishedCommonSourceSets(project)
|
||||
val publishedCommonSourceSets: Set<KotlinSourceSet> = getCommonSourceSetsForMetadataCompilation(project)
|
||||
val hostSpecificSourceSets: Set<KotlinSourceSet> = getHostSpecificSourceSets(project).toSet()
|
||||
|
||||
val sourceSetsWithMetadataCompilations: Map<KotlinSourceSet, AbstractKotlinCompilation<*>> =
|
||||
publishedCommonSourceSets.associate { sourceSet ->
|
||||
sourceSet to createMetadataCompilation(target, sourceSet, allMetadataJar, sourceSet in hostSpecificSourceSets)
|
||||
val sourceSetsWithMetadataCompilations: Map<KotlinSourceSet, AbstractKotlinCompilation<*>> = publishedCommonSourceSets
|
||||
.associateWith { sourceSet ->
|
||||
createMetadataCompilation(target, sourceSet, allMetadataJar, sourceSet in hostSpecificSourceSets)
|
||||
}
|
||||
.onEach { (sourceSet, compilation) ->
|
||||
if (!isMetadataCompilationSupported(target.project, sourceSet)) {
|
||||
compilation.compileKotlinTaskProvider.configure { it.enabled = false }
|
||||
}
|
||||
}
|
||||
|
||||
if (project.isCompatibilityMetadataVariantEnabled) {
|
||||
@@ -195,6 +201,30 @@ class KotlinMetadataTargetConfigurator(kotlinPluginVersion: String) :
|
||||
}
|
||||
}
|
||||
|
||||
private fun isMetadataCompilationSupported(project: Project, sourceSet: KotlinSourceSet): Boolean {
|
||||
val platforms = compilationsBySourceSets(project)[sourceSet].orEmpty()
|
||||
.filter { it.target !is KotlinMetadataTarget }
|
||||
.map { it.target.platformType }.distinct()
|
||||
|
||||
/*
|
||||
Android and jvm do share the JVM backend which is not supported for metadata compilation
|
||||
See [HMPP: Bad IDEA dependencies for JVM and Android intermediate source set](https://youtrack.jetbrains.com/issue/KT-42383)
|
||||
See [HMPP: JVM and Android intermediate source set publication](https://youtrack.jetbrains.com/issue/KT-42468)
|
||||
*/
|
||||
if (platforms.all { it == KotlinPlatformType.jvm || it == KotlinPlatformType.androidJvm }) {
|
||||
return false
|
||||
}
|
||||
|
||||
/* Metadata compilation for a single platform is only supported native and common source sets */
|
||||
if (platforms.size == 1) {
|
||||
val platform = platforms.single()
|
||||
return platform == KotlinPlatformType.native || platform == KotlinPlatformType.common
|
||||
}
|
||||
|
||||
/* Source sets sharing code between multiple backends are supported */
|
||||
return true
|
||||
}
|
||||
|
||||
private fun configureProjectStructureMetadataGeneration(project: Project, allMetadataJar: TaskProvider<out Jar>) {
|
||||
val generateMetadata = project.createGenerateProjectStructureMetadataTask()
|
||||
|
||||
@@ -256,7 +286,7 @@ class KotlinMetadataTargetConfigurator(kotlinPluginVersion: String) :
|
||||
|
||||
val compilationName = sourceSet.name
|
||||
|
||||
val platformCompilations = CompilationSourceSetUtil.compilationsBySourceSets(project).getValue(sourceSet)
|
||||
val platformCompilations = compilationsBySourceSets(project).getValue(sourceSet)
|
||||
|
||||
val isNativeSourceSet = platformCompilations.all { compilation -> compilation.target is KotlinNativeTarget }
|
||||
|
||||
@@ -271,7 +301,6 @@ class KotlinMetadataTargetConfigurator(kotlinPluginVersion: String) :
|
||||
return compilationFactory.create(compilationName).apply {
|
||||
target.compilations.add(this@apply)
|
||||
addExactSourceSetsEagerly(setOf(sourceSet))
|
||||
|
||||
configureMetadataDependenciesForCompilation(this@apply)
|
||||
|
||||
if (!isHostSpecific) {
|
||||
@@ -513,14 +542,18 @@ class KotlinMetadataTargetConfigurator(kotlinPluginVersion: String) :
|
||||
}
|
||||
}
|
||||
|
||||
internal fun getPublishedCommonSourceSets(project: Project): Set<KotlinSourceSet> {
|
||||
/**
|
||||
* @return All common source sets that can potentially be published. Right now, not all combinations of platforms actually
|
||||
* support metadata compilation (see [KotlinMetadataTargetConfigurator.isMetadataCompilationSupported].
|
||||
* Those compilations will be created but the corresponding tasks will be disabled.
|
||||
*/
|
||||
internal fun getCommonSourceSetsForMetadataCompilation(project: Project): Set<KotlinSourceSet> {
|
||||
val compilationsBySourceSet: Map<KotlinSourceSet, Set<KotlinCompilation<*>>> =
|
||||
CompilationSourceSetUtil.compilationsBySourceSets(project)
|
||||
compilationsBySourceSets(project)
|
||||
|
||||
val sourceSetsUsedInMultipleTargets = compilationsBySourceSet.filterValues { compilations ->
|
||||
compilations.map { it.target.platformType }.distinct().run {
|
||||
size > 1 && toSet() != setOf(KotlinPlatformType.androidJvm, KotlinPlatformType.jvm) ||
|
||||
singleOrNull() == KotlinPlatformType.native && compilations.map { it.target }.distinct().size > 1
|
||||
size > 1 || singleOrNull() == KotlinPlatformType.native && compilations.map { it.target }.distinct().size > 1
|
||||
// TODO: platform-shared source sets other than Kotlin/Native ones are not yet supported; support will be needed for JVM, JS
|
||||
}
|
||||
}
|
||||
@@ -565,4 +598,4 @@ internal fun Project.filesWithUnpackedArchives(from: FileCollection, extensions:
|
||||
|
||||
internal fun Project.getMetadataCompilationForSourceSet(sourceSet: KotlinSourceSet): AbstractKotlinCompilation<*>? {
|
||||
return multiplatformExtension.metadata().compilations.findByName(sourceSet.name)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -166,4 +166,4 @@ open class KotlinNativeTargetWithHostTests @Inject constructor(project: Project,
|
||||
KotlinNativeTargetWithTests<KotlinNativeHostTestRun>(project, konanTarget)
|
||||
|
||||
open class KotlinNativeTargetWithSimulatorTests @Inject constructor(project: Project, konanTarget: KonanTarget) :
|
||||
KotlinNativeTargetWithTests<KotlinNativeSimulatorTestRun>(project, konanTarget)
|
||||
KotlinNativeTargetWithTests<KotlinNativeSimulatorTestRun>(project, konanTarget)
|
||||
|
||||
@@ -593,4 +593,4 @@ open class KotlinCocoapodsPlugin : Plugin<Project> {
|
||||
gemListRetCode == 0 && gemListOutput.contains("cocoapods-generate")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
/*
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.gradle.utils
|
||||
|
||||
internal val androidPluginIds = listOf(
|
||||
"android", "com.android.application", "android-library", "com.android.library",
|
||||
"com.android.test", "com.android.feature", "com.android.dynamic-feature", "com.android.instantapp"
|
||||
)
|
||||
Reference in New Issue
Block a user