[Gradle, JS] Necessary to use approach with traversing all source sets
Because common source sets included into JS compilation, it can be detected as JS associated compilations. So necessary to set attribute about JS compiler attribute only (at least at the beginning) to JS only source sets (source sets which are not included into any non js compilations) [Gradle, JS] Add test with resolving JS variant of MPP library [Gradle, JS] Add additional filtering of JS targets [Gradle, JS] Add test on local resolve ^KT-47163 fixed ^KT-47114 fixed
This commit is contained in:
committed by
TeamCityServer
parent
03f85bea8f
commit
594cc29dd2
+69
@@ -10,11 +10,13 @@ import org.gradle.api.logging.LogLevel
|
||||
import org.gradle.api.logging.configuration.WarningMode
|
||||
import org.gradle.util.GradleVersion
|
||||
import org.jetbrains.kotlin.gradle.plugin.KotlinJsCompilerType
|
||||
import org.jetbrains.kotlin.gradle.plugin.sources.METADATA_CONFIGURATION_NAME_SUFFIX
|
||||
import org.jetbrains.kotlin.gradle.targets.js.ir.KLIB_TYPE
|
||||
import org.jetbrains.kotlin.gradle.targets.js.npm.*
|
||||
import org.jetbrains.kotlin.gradle.tasks.USING_JS_INCREMENTAL_COMPILATION_MESSAGE
|
||||
import org.jetbrains.kotlin.gradle.tasks.USING_JS_IR_BACKEND_MESSAGE
|
||||
import org.jetbrains.kotlin.gradle.util.*
|
||||
import org.junit.Assert
|
||||
import org.junit.Assume.assumeFalse
|
||||
import org.junit.Test
|
||||
import java.io.File
|
||||
@@ -743,6 +745,73 @@ abstract class AbstractKotlin2JsGradlePluginIT(val irBackend: Boolean) : BaseGra
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testResolveJsProjectDependencyToMetadata() = with(Project("kotlin-js-browser-project")) {
|
||||
setupWorkingDir()
|
||||
gradleBuildScript().modify(::transformBuildScriptWithPluginsDsl)
|
||||
gradleSettingsScript().modify(::transformBuildScriptWithPluginsDsl)
|
||||
gradleProperties().appendText("kotlin.js.compiler=both")
|
||||
|
||||
val compiler = if (irBackend) "IR" else "LEGACY"
|
||||
|
||||
val pathPrefix = "metadataDependency: "
|
||||
|
||||
val appBuild = projectDir.resolve("app/build.gradle.kts")
|
||||
appBuild.modify {
|
||||
it.replace("target {", "js($compiler) {")
|
||||
}
|
||||
appBuild.appendText(
|
||||
"\n" + """
|
||||
kotlin.sourceSets {
|
||||
val main by getting {
|
||||
dependencies {
|
||||
// add these dependencies to check that they are resolved to metadata
|
||||
api(project(":base"))
|
||||
implementation(project(":base"))
|
||||
compileOnly(project(":base"))
|
||||
runtimeOnly(project(":base"))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
task("printMetadataFiles") {
|
||||
doFirst {
|
||||
listOf("api", "implementation", "compileOnly", "runtimeOnly").forEach { kind ->
|
||||
val configuration = configurations.getByName(kind + "DependenciesMetadata")
|
||||
configuration.files.forEach { println("$pathPrefix" + configuration.name + "->" + it.name) }
|
||||
}
|
||||
}
|
||||
}
|
||||
""".trimIndent()
|
||||
)
|
||||
|
||||
val metadataDependencyRegex = "$pathPrefix(.*?)->(.*)".toRegex()
|
||||
|
||||
build(
|
||||
"printMetadataFiles",
|
||||
options = defaultBuildOptions().copy(jsCompilerType = if (irBackend) KotlinJsCompilerType.IR else KotlinJsCompilerType.LEGACY)
|
||||
) {
|
||||
assertSuccessful()
|
||||
|
||||
val suffix = if (irBackend) "ir" else "legacy"
|
||||
val ext = if (irBackend) "klib" else "jar"
|
||||
|
||||
val expectedFileName = "base-$suffix.$ext"
|
||||
|
||||
val paths = metadataDependencyRegex
|
||||
.findAll(output).map { it.groupValues[1] to it.groupValues[2] }
|
||||
.filter { (_, f) -> "base" in f }
|
||||
.toSet()
|
||||
|
||||
Assert.assertEquals(
|
||||
listOf("api", "implementation", "compileOnly", "runtimeOnly").map {
|
||||
"$it$METADATA_CONFIGURATION_NAME_SUFFIX" to expectedFileName
|
||||
}.toSet(),
|
||||
paths
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testNoUnintendedDevDependencies() = with(Project("kotlin-js-browser-project")) {
|
||||
setupWorkingDir()
|
||||
|
||||
+70
@@ -905,6 +905,76 @@ class NewMultiplatformIT : BaseGradleIT() {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testResolveJsPartOfMppLibDependencyToMetadata() {
|
||||
val libProject = Project("sample-lib", gradleVersion, "new-mpp-lib-and-app")
|
||||
val appProject = Project("sample-app", gradleVersion, "new-mpp-lib-and-app")
|
||||
|
||||
libProject.build(
|
||||
"publish",
|
||||
options = defaultBuildOptions().copy(jsCompilerType = BOTH)
|
||||
) {
|
||||
assertSuccessful()
|
||||
}
|
||||
val localRepo = libProject.projectDir.resolve("repo")
|
||||
val localRepoUri = localRepo.toURI()
|
||||
|
||||
with(appProject) {
|
||||
setupWorkingDir()
|
||||
|
||||
val pathPrefix = "metadataDependency: "
|
||||
|
||||
gradleBuildScript().appendText(
|
||||
"\n" + """
|
||||
repositories { maven { url '$localRepoUri' } }
|
||||
|
||||
kotlin.sourceSets {
|
||||
nodeJsMain {
|
||||
dependencies {
|
||||
// add these dependencies to check that they are resolved to metadata
|
||||
api 'com.example:sample-lib-nodejs:1.0'
|
||||
implementation 'com.example:sample-lib-nodejs:1.0'
|
||||
compileOnly 'com.example:sample-lib-nodejs:1.0'
|
||||
runtimeOnly 'com.example:sample-lib-nodejs:1.0'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
task('printMetadataFiles') {
|
||||
doFirst {
|
||||
['Api', 'Implementation', 'CompileOnly', 'RuntimeOnly'].each { kind ->
|
||||
def configuration = configurations.getByName("nodeJsMain${'$'}kind" + '$METADATA_CONFIGURATION_NAME_SUFFIX')
|
||||
configuration.files.each { println '$pathPrefix' + configuration.name + '->' + it.name }
|
||||
}
|
||||
}
|
||||
}
|
||||
""".trimIndent()
|
||||
)
|
||||
val metadataDependencyRegex = "$pathPrefix(.*?)->(.*)".toRegex()
|
||||
|
||||
build(
|
||||
"printMetadataFiles",
|
||||
options = defaultBuildOptions().copy(jsCompilerType = IR)
|
||||
) {
|
||||
assertSuccessful()
|
||||
|
||||
val expectedFileName = "sample-lib-nodejsir-1.0.klib"
|
||||
|
||||
val paths = metadataDependencyRegex
|
||||
.findAll(output).map { it.groupValues[1] to it.groupValues[2] }
|
||||
.filter { (_, f) -> "sample-lib" in f }
|
||||
.toSet()
|
||||
|
||||
Assert.assertEquals(
|
||||
listOf("Api", "Implementation", "CompileOnly", "RuntimeOnly").map {
|
||||
"nodeJsMain$it$METADATA_CONFIGURATION_NAME_SUFFIX" to expectedFileName
|
||||
}.toSet(),
|
||||
paths
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testResolveMppProjectDependencyToMetadata() {
|
||||
val libProject = Project("sample-lib", gradleVersion, "new-mpp-lib-and-app")
|
||||
|
||||
+3
-1
@@ -46,6 +46,8 @@ kotlin {
|
||||
}
|
||||
}
|
||||
|
||||
js('nodeJs')
|
||||
|
||||
targets {
|
||||
fromPreset(presets.jvm, 'jvm6') {
|
||||
attributes.attribute(TargetJvmVersion.TARGET_JVM_VERSION_ATTRIBUTE, 6)
|
||||
@@ -61,7 +63,7 @@ kotlin {
|
||||
}
|
||||
}
|
||||
}
|
||||
fromPreset(presets.js, 'nodeJs')
|
||||
|
||||
fromPreset(presets.linuxX64, 'linux64')
|
||||
|
||||
configure([linux64]) {
|
||||
|
||||
+8
-3
@@ -59,7 +59,7 @@ interface KotlinTargetConfigurator<KotlinTargetType : KotlinTarget> {
|
||||
fun defineConfigurationsForTarget(target: KotlinTargetType)
|
||||
fun configureArchivesAndComponent(target: KotlinTargetType)
|
||||
fun configureBuild(target: KotlinTargetType)
|
||||
fun configureSourceSet(target: KotlinTarget)
|
||||
fun configureSourceSet(target: KotlinTargetType)
|
||||
|
||||
fun configurePlatformSpecificModel(target: KotlinTargetType) = Unit
|
||||
}
|
||||
@@ -105,7 +105,7 @@ abstract class AbstractKotlinTargetConfigurator<KotlinTargetType : KotlinTarget>
|
||||
}
|
||||
}
|
||||
|
||||
override fun configureSourceSet(target: KotlinTarget) {
|
||||
override fun configureSourceSet(target: KotlinTargetType) {
|
||||
val project = target.project
|
||||
|
||||
target.compilations.all { compilation ->
|
||||
@@ -254,7 +254,12 @@ abstract class AbstractKotlinTargetConfigurator<KotlinTargetType : KotlinTarget>
|
||||
}
|
||||
}
|
||||
|
||||
private fun addDependsOnTaskInOtherProjects(project: Project, taskProvider: TaskProvider<*>, useDependedOn: Boolean, configurationName: String) {
|
||||
private fun addDependsOnTaskInOtherProjects(
|
||||
project: Project,
|
||||
taskProvider: TaskProvider<*>,
|
||||
useDependedOn: Boolean,
|
||||
configurationName: String
|
||||
) {
|
||||
val configuration = project.configurations.getByName(configurationName)
|
||||
taskProvider.configure { task ->
|
||||
task.dependsOn(configuration.getTaskDependencyFromProjectDependency(useDependedOn, taskProvider.name))
|
||||
|
||||
+65
-3
@@ -7,11 +7,16 @@ package org.jetbrains.kotlin.gradle.plugin.sources
|
||||
|
||||
import org.gradle.api.NamedDomainObjectFactory
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.api.artifacts.Configuration
|
||||
import org.gradle.api.attributes.Usage
|
||||
import org.jetbrains.kotlin.gradle.plugin.KotlinPlatformType
|
||||
import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet
|
||||
import org.jetbrains.kotlin.gradle.dsl.kotlinExtension
|
||||
import org.jetbrains.kotlin.gradle.plugin.*
|
||||
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinJsCompilation
|
||||
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinUsages
|
||||
import org.jetbrains.kotlin.gradle.plugin.usageByName
|
||||
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.targets
|
||||
import org.jetbrains.kotlin.gradle.targets.js.KotlinJsCompilerAttribute
|
||||
import org.jetbrains.kotlin.gradle.targets.js.KotlinJsTarget
|
||||
import org.jetbrains.kotlin.gradle.targets.js.ir.KotlinJsIrTarget
|
||||
import org.jetbrains.kotlin.gradle.targets.metadata.isKotlinGranularMetadataEnabled
|
||||
import java.io.File
|
||||
|
||||
@@ -92,10 +97,67 @@ internal class DefaultKotlinSourceSetFactory(
|
||||
if (project.isKotlinGranularMetadataEnabled) {
|
||||
attributes.attribute(Usage.USAGE_ATTRIBUTE, project.usageByName(KotlinUsages.KOTLIN_METADATA))
|
||||
}
|
||||
|
||||
project.whenEvaluated {
|
||||
setJsCompilerIfNecessary(sourceSet, this@apply)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// KT-47163
|
||||
// It is necessary to set jsCompilerAttribute to configurations which associated with ONLY js source sets
|
||||
// Otherwise configuration cannot be resolved because ambiguity between IR and Legacy variants inside one module
|
||||
private val notOnlyJsSourceSets = mutableSetOf<KotlinSourceSet>()
|
||||
|
||||
private val jsOnlySourceSetsAttributes = mutableMapOf<KotlinSourceSet, KotlinJsCompilerAttribute>()
|
||||
|
||||
private fun setJsCompilerIfNecessary(sourceSet: KotlinSourceSet, configuration: Configuration) {
|
||||
if (sourceSet in notOnlyJsSourceSets) return
|
||||
|
||||
if (sourceSet in jsOnlySourceSetsAttributes) {
|
||||
configuration.attributes.attribute(
|
||||
KotlinJsCompilerAttribute.jsCompilerAttribute,
|
||||
jsOnlySourceSetsAttributes.getValue(sourceSet)
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
project.kotlinExtension.targets
|
||||
.filter { it !is KotlinJsIrTarget && it !is KotlinJsTarget }
|
||||
.forEach { target ->
|
||||
target.compilations.forEach { compilation ->
|
||||
notOnlyJsSourceSets.addAll(compilation.allKotlinSourceSets)
|
||||
}
|
||||
}
|
||||
|
||||
if (sourceSet in notOnlyJsSourceSets) return
|
||||
|
||||
fun chooseCompilerAttribute(target: KotlinTarget): KotlinJsCompilerAttribute {
|
||||
if (target is KotlinJsIrTarget) {
|
||||
return KotlinJsCompilerAttribute.ir
|
||||
}
|
||||
|
||||
target as KotlinJsTarget
|
||||
return if (target.irTarget != null) KotlinJsCompilerAttribute.ir else KotlinJsCompilerAttribute.legacy
|
||||
}
|
||||
|
||||
project.kotlinExtension.targets
|
||||
.filter { it is KotlinJsTarget || it is KotlinJsIrTarget }
|
||||
.forEach { target ->
|
||||
target.compilations
|
||||
.filterIsInstance<KotlinJsCompilation>()
|
||||
.forEach { compilation ->
|
||||
if (sourceSet in compilation.allKotlinSourceSets) {
|
||||
val compilerAttribute = chooseCompilerAttribute(target)
|
||||
jsOnlySourceSetsAttributes[sourceSet] = compilerAttribute
|
||||
configuration.attributes.attribute(KotlinJsCompilerAttribute.jsCompilerAttribute, compilerAttribute)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun doCreateSourceSet(name: String): DefaultKotlinSourceSet {
|
||||
return DefaultKotlinSourceSet(project, name)
|
||||
}
|
||||
|
||||
+5
-2
@@ -6,8 +6,9 @@
|
||||
package org.jetbrains.kotlin.gradle.targets.js
|
||||
|
||||
import org.gradle.api.Named
|
||||
import org.gradle.api.attributes.Attribute
|
||||
import org.gradle.api.attributes.AttributesSchema
|
||||
import org.gradle.api.attributes.*
|
||||
import org.jetbrains.kotlin.gradle.plugin.KotlinPlatformType
|
||||
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinUsages
|
||||
import java.io.Serializable
|
||||
|
||||
// For Gradle attributes
|
||||
@@ -15,6 +16,8 @@ import java.io.Serializable
|
||||
enum class KotlinJsCompilerAttribute : Named, Serializable {
|
||||
legacy,
|
||||
ir,
|
||||
|
||||
@Deprecated("This value is not used in Gradle plugin. You don't need to use it. It will be removed in next major.")
|
||||
both;
|
||||
|
||||
override fun getName(): String =
|
||||
|
||||
+6
-1
@@ -52,7 +52,12 @@ constructor(
|
||||
}
|
||||
|
||||
internal val commonFakeApiElementsConfigurationName: String
|
||||
get() = disambiguateName("commonFakeApiElements")
|
||||
get() = lowerCamelCaseName(
|
||||
irTarget?.let {
|
||||
this.disambiguationClassifierInPlatform
|
||||
} ?: disambiguationClassifier,
|
||||
"commonFakeApiElements"
|
||||
)
|
||||
|
||||
val disambiguationClassifierInPlatform: String?
|
||||
get() = if (irTarget != null) {
|
||||
|
||||
+1
@@ -119,6 +119,7 @@ open class KotlinJsTargetConfigurator :
|
||||
isCanBeConsumed = true
|
||||
attributes.attribute<Usage>(Usage.USAGE_ATTRIBUTE, KotlinUsages.producerApiUsage(target))
|
||||
attributes.attribute(KotlinPlatformType.attribute, KotlinPlatformType.common)
|
||||
setupAsPublicConfigurationIfSupported(target)
|
||||
}
|
||||
}
|
||||
}
|
||||
+7
-1
@@ -72,7 +72,13 @@ constructor(
|
||||
}
|
||||
|
||||
internal val commonFakeApiElementsConfigurationName: String
|
||||
get() = disambiguateName("commonFakeApiElements")
|
||||
get() = lowerCamelCaseName(
|
||||
if (mixedMode)
|
||||
disambiguationClassifierInPlatform
|
||||
else
|
||||
disambiguationClassifier,
|
||||
"commonFakeApiElements"
|
||||
)
|
||||
|
||||
val disambiguationClassifierInPlatform: String?
|
||||
get() = if (mixedMode) {
|
||||
|
||||
+1
@@ -143,6 +143,7 @@ open class KotlinJsIrTargetConfigurator() :
|
||||
isCanBeConsumed = true
|
||||
attributes.attribute<Usage>(Usage.USAGE_ATTRIBUTE, KotlinUsages.producerApiUsage(target))
|
||||
attributes.attribute(KotlinPlatformType.attribute, KotlinPlatformType.common)
|
||||
setupAsPublicConfigurationIfSupported(target)
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user