MPP granular source set metadata support

This commit is contained in:
Sergey Igushkin
2019-04-12 18:40:21 +03:00
parent fcb006b42a
commit 0c9d962f9f
96 changed files with 3089 additions and 109 deletions
@@ -0,0 +1,318 @@
/*
* Copyright 2010-2019 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
import org.jetbrains.kotlin.gradle.internals.parseKotlinSourceSetMetadataFromXml
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinProjectStructureMetadata
import org.jetbrains.kotlin.gradle.plugin.mpp.MULTIPLATFORM_PROJECT_METADATA_FILE_NAME
import org.jetbrains.kotlin.gradle.util.modify
import org.jetbrains.kotlin.konan.file.File
import java.util.zip.ZipFile
import javax.xml.parsers.DocumentBuilderFactory
import kotlin.test.Test
import kotlin.test.assertEquals
import kotlin.test.assertTrue
class HierarchicalMppIT : BaseGradleIT() {
companion object {
private val gradleVersion = GradleVersionRequired.AtLeast("5.0")
}
@Test
fun testPublishedModules() {
Project("third-party-lib", gradleVersion, "hierarchical-mpp-published-modules").run {
setupWorkingDir()
gradleBuildScript().modify(::transformBuildScriptWithPluginsDsl)
build("publish") {
assertSuccessful()
}
}
Project("my-lib-foo", gradleVersion, "hierarchical-mpp-published-modules").run {
setupWorkingDir()
gradleBuildScript().modify(::transformBuildScriptWithPluginsDsl)
build("publish") {
checkMyLibFoo(this, subprojectPrefix = null)
}
}
Project("my-lib-bar", gradleVersion, "hierarchical-mpp-published-modules").run {
setupWorkingDir()
gradleBuildScript().modify(::transformBuildScriptWithPluginsDsl)
build("publish") {
checkMyLibBar(this, subprojectPrefix = null)
}
}
Project("my-app", gradleVersion, "hierarchical-mpp-published-modules").run {
setupWorkingDir()
gradleBuildScript().modify(::transformBuildScriptWithPluginsDsl)
build("assemble") {
checkMyApp(this, subprojectPrefix = null)
}
}
}
@Test
fun testProjectDependencies() {
Project("third-party-lib", gradleVersion, "hierarchical-mpp-project-dependency").run {
setupWorkingDir()
gradleBuildScript().modify(::transformBuildScriptWithPluginsDsl)
build("publish") {
assertSuccessful()
}
}
with(Project("hierarchical-mpp-project-dependency", gradleVersion)) {
setupWorkingDir()
gradleBuildScript().modify(::transformBuildScriptWithPluginsDsl)
build("publish", "assemble") {
checkMyLibFoo(this, subprojectPrefix = "my-lib-foo")
checkMyLibBar(this, subprojectPrefix = "my-lib-bar")
checkMyApp(this, subprojectPrefix = "my-app")
}
}
}
private fun checkMyLibFoo(compiledProject: CompiledProject, subprojectPrefix: String? = null) = with(compiledProject) {
val taskPrefix = subprojectPrefix?.let { ":$it" }.orEmpty()
val directoryPrefix = subprojectPrefix?.let { "$it/" }.orEmpty()
assertSuccessful()
assertTasksExecuted(expectedTasks(subprojectPrefix))
ZipFile(
project.projectDir.parentFile.resolve(
"repo/com/example/foo/my-lib-foo-metadata/1.0/my-lib-foo-metadata-1.0-all.jar"
)
).use { publishedMetadataJar ->
publishedMetadataJar.checkAllEntryNamesArePresent(
"META-INF/$MULTIPLATFORM_PROJECT_METADATA_FILE_NAME",
"commonMain/META-INF/my-lib-foo.kotlin_module",
"commonMain/com/example/foo/FooKt.kotlin_metadata",
"jvmAndJsMain/META-INF/my-lib-foo_jvmAndJsMain.kotlin_module",
"jvmAndJsMain/com/example/foo/FooJvmAndJsKt.kotlin_metadata",
"linuxAndJsMain/META-INF/my-lib-foo_linuxAndJsMain.kotlin_module",
"linuxAndJsMain/com/example/foo/FooLinuxAndJsKt.kotlin_metadata"
)
val parsedProjectStructureMetadata: KotlinProjectStructureMetadata = publishedMetadataJar.getProjectStructureMetadata()
val expectedProjectStructureMetadata = expectedProjectStructureMetadata(
sourceSetModuleDependencies = mapOf(
"jvmAndJsMain" to setOf("com.example.thirdparty" to "third-party-lib"),
"linuxAndJsMain" to emptySet(),
"commonMain" to emptySet()
)
)
assertEquals(expectedProjectStructureMetadata, parsedProjectStructureMetadata)
}
}
private fun checkMyLibBar(compiledProject: CompiledProject, subprojectPrefix: String?) = with(compiledProject) {
val taskPrefix = subprojectPrefix?.let { ":$it" }.orEmpty()
assertSuccessful()
assertTasksExecuted(expectedTasks(subprojectPrefix))
ZipFile(
project.projectDir.parentFile.resolve(
"repo/com/example/bar/my-lib-bar-metadata/1.0/my-lib-bar-metadata-1.0-all.jar"
)
).use { publishedMetadataJar ->
publishedMetadataJar.checkAllEntryNamesArePresent(
"META-INF/$MULTIPLATFORM_PROJECT_METADATA_FILE_NAME",
"commonMain/META-INF/my-lib-bar.kotlin_module",
"commonMain/com/example/bar/BarKt.kotlin_metadata",
"jvmAndJsMain/META-INF/my-lib-bar_jvmAndJsMain.kotlin_module",
"jvmAndJsMain/com/example/bar/BarJvmAndJsKt.kotlin_metadata",
"linuxAndJsMain/META-INF/my-lib-bar_linuxAndJsMain.kotlin_module",
"linuxAndJsMain/com/example/bar/BarLinuxAndJsKt.kotlin_metadata"
)
val parsedProjectStructureMetadata: KotlinProjectStructureMetadata = publishedMetadataJar.getProjectStructureMetadata()
val expectedProjectStructureMetadata = expectedProjectStructureMetadata(
sourceSetModuleDependencies = mapOf(
"jvmAndJsMain" to setOf(),
"linuxAndJsMain" to emptySet(),
"commonMain" to setOf("com.example.foo" to "my-lib-foo")
)
)
assertEquals(expectedProjectStructureMetadata, parsedProjectStructureMetadata)
}
checkNamesOnCompileClasspath(
"$taskPrefix:compileKotlinMetadata",
shouldInclude = listOf(
"my-lib-foo" to "main"
),
shouldNotInclude = listOf(
"my-lib-foo" to "jvmAndJsMain",
"my-lib-foo" to "linuxAndJsMain",
"third-party-lib-metadata-1.0" to ""
)
)
checkNamesOnCompileClasspath(
"$taskPrefix:compileJvmAndJsMainKotlinMetadata",
shouldInclude = listOf(
"my-lib-foo" to "main",
"my-lib-foo" to "jvmAndJsMain",
"third-party-lib-metadata-1.0" to ""
),
shouldNotInclude = listOf(
"my-lib-foo" to "linuxAndJsMain"
)
)
checkNamesOnCompileClasspath(
"$taskPrefix:compileLinuxAndJsMainKotlinMetadata",
shouldInclude = listOf(
"my-lib-foo" to "linuxAndJsMain",
"my-lib-foo" to "main"
),
shouldNotInclude = listOf(
"my-lib-foo" to "jvmAndJsMain",
"third-party-lib-metadata-1.0" to ""
)
)
}
private fun checkMyApp(compiledProject: CompiledProject, subprojectPrefix: String?) = with(compiledProject) {
val taskPrefix = subprojectPrefix?.let { ":$it" }.orEmpty()
assertSuccessful()
assertTasksExecuted(expectedTasks(subprojectPrefix))
checkNamesOnCompileClasspath(
"$taskPrefix:compileKotlinMetadata",
shouldInclude = listOf(
"my-lib-bar" to "main",
"my-lib-foo" to "main"
),
shouldNotInclude = listOf(
"my-lib-bar" to "jvmAndJsMain",
"my-lib-bar" to "linuxAndJsMain",
"my-lib-foo" to "jvmAndJsMain",
"my-lib-foo" to "linuxAndJsMain",
"third-party-lib-metadata-1.0" to ""
)
)
checkNamesOnCompileClasspath(
"$taskPrefix:compileJvmAndJsMainKotlinMetadata",
shouldInclude = listOf(
"my-lib-bar" to "main",
"my-lib-bar" to "jvmAndJsMain",
"my-lib-foo" to "main",
"my-lib-foo" to "jvmAndJsMain",
"third-party-lib-metadata-1.0" to ""
),
shouldNotInclude = listOf(
"my-lib-bar" to "linuxAndJsMain",
"my-lib-foo" to "linuxAndJsMain"
)
)
checkNamesOnCompileClasspath(
"$taskPrefix:compileLinuxAndJsMainKotlinMetadata",
shouldInclude = listOf(
"my-lib-bar" to "main",
"my-lib-bar" to "linuxAndJsMain",
"my-lib-foo" to "main",
"my-lib-foo" to "linuxAndJsMain"
),
shouldNotInclude = listOf(
"my-lib-bar" to "jvmAndJsMain",
"my-lib-foo" to "jvmAndJsMain",
"third-party-lib-metadata-1.0" to ""
)
)
checkNamesOnCompileClasspath("$taskPrefix:compileLinuxAndJsMainKotlinMetadata")
}
private fun CompiledProject.checkNamesOnCompileClasspath(
taskPath: String,
shouldInclude: Iterable<Pair<String, String>> = emptyList(),
shouldNotInclude: Iterable<Pair<String, String>> = emptyList()
) {
val taskOutput = getOutputForTask(taskPath.removePrefix(":"))
val compilerArgsLine = taskOutput.lines().single { "Kotlin compiler args:" in it }
val classpathItems = compilerArgsLine.substringAfter("-classpath").substringBefore(" -").split(File.pathSeparator)
shouldInclude.forEach { (module, sourceSet) ->
assertTrue("expected module '$module' source set '$sourceSet' on the classpath of task $taskPath") {
classpathItems.any { module in it && it.contains(sourceSet, ignoreCase = true) }
}
}
shouldNotInclude.forEach { (module, sourceSet) ->
assertTrue("not expected module '$module' source set '$sourceSet' on the compile classpath of task $taskPath") {
classpathItems.none { module in it && it.contains(sourceSet, ignoreCase = true) }
}
}
}
private fun expectedTasks(subprojectPrefix: String?) = listOf(
"generateProjectStructureMetadata",
"transformCommonMainDependenciesMetadata",
"transformJvmAndJsMainDependenciesMetadata",
"transformLinuxAndJsMainDependenciesMetadata",
"compileKotlinMetadata",
"compileJvmAndJsMainKotlinMetadata",
"compileLinuxAndJsMainKotlinMetadata"
).map { subprojectPrefix?.let { ":$it" }.orEmpty() + ":" + it }
// the projects used in these tests are similar and only the dependencies differ:
private fun expectedProjectStructureMetadata(
sourceSetModuleDependencies: Map<String, Set<Pair<String, String>>>
): KotlinProjectStructureMetadata {
val jvmSourceSets = setOf("commonMain", "jvmAndJsMain")
val jsSourceSets = setOf("commonMain", "jvmAndJsMain", "linuxAndJsMain")
return KotlinProjectStructureMetadata(
sourceSetNamesByVariantName = mapOf(
"js-api" to jsSourceSets,
"js-runtime" to jsSourceSets,
"jvm-api" to jvmSourceSets,
"jvm-runtime" to jvmSourceSets,
"linuxX64-api" to setOf("commonMain", "linuxAndJsMain")
),
sourceSetsDependsOnRelation = mapOf(
"jvmAndJsMain" to setOf("commonMain"),
"linuxAndJsMain" to setOf("commonMain"),
"commonMain" to emptySet()
),
sourceSetModuleDependencies = sourceSetModuleDependencies
)
}
private fun ZipFile.checkAllEntryNamesArePresent(vararg expectedEntryNames: String) {
val entryNames = entries().asSequence().map { it.name }.toSet()
val entryNamesString = entryNames.joinToString()
expectedEntryNames.forEach {
assertTrue("expecting entry $it in entry names $entryNamesString") { it in entryNames }
}
}
private fun ZipFile.getProjectStructureMetadata(): KotlinProjectStructureMetadata {
val documentBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder()
val document = getInputStream(getEntry("META-INF/$MULTIPLATFORM_PROJECT_METADATA_FILE_NAME"))
.use { inputStream -> documentBuilder.parse(inputStream) }
return checkNotNull(parseKotlinSourceSetMetadataFromXml(document))
}
}
@@ -0,0 +1,11 @@
plugins {
kotlin("multiplatform").version("<pluginMarkerVersion>").apply(false)
}
allprojects {
repositories {
mavenLocal()
maven("$rootDir/../repo")
jcenter()
}
}
@@ -0,0 +1,88 @@
plugins {
kotlin("multiplatform")
}
repositories {
mavenLocal()
jcenter()
}
group = "com.example.app"
version = "1.0"
kotlin {
jvm()
js()
linuxX64()
sourceSets {
val commonMain by getting {
dependencies {
api(project(":my-lib-bar"))
implementation(kotlin("stdlib-common"))
}
}
val commonTest by getting {
dependencies {
implementation(kotlin("test-common"))
implementation(kotlin("test-annotations-common"))
}
}
val jvmAndJsMain by creating {
dependsOn(commonMain)
}
val jvmAndJsTest by creating {
dependsOn(commonTest)
}
val linuxAndJsMain by creating {
dependsOn(commonMain)
}
val linuxAndJsTest by creating {
dependsOn(commonTest)
}
jvm().compilations["main"].defaultSourceSet {
dependsOn(jvmAndJsMain)
dependencies {
implementation(kotlin("stdlib"))
}
}
jvm().compilations["test"].defaultSourceSet {
dependsOn(jvmAndJsTest)
dependencies {
implementation(kotlin("test-junit"))
}
}
js().compilations["main"].defaultSourceSet {
dependsOn(jvmAndJsMain)
dependsOn(linuxAndJsMain)
dependencies {
implementation(kotlin("stdlib-js"))
}
}
js().compilations["test"].defaultSourceSet {
dependsOn(jvmAndJsTest)
dependsOn(linuxAndJsTest)
dependencies {
implementation(kotlin("test-js"))
}
}
linuxX64().compilations["main"].defaultSourceSet {
dependsOn(linuxAndJsMain)
}
linuxX64().compilations["test"].defaultSourceSet {
dependsOn(linuxAndJsTest)
}
}
}
@@ -0,0 +1,11 @@
package com.example.app
import com.example.foo.*
import com.example.bar.*
fun appCommon() {
foo()
fooCommon()
bar()
barCommon()
}
@@ -0,0 +1,20 @@
package com.example.app
import com.example.bar.bar
import com.example.bar.barCommon
import com.example.foo.foo
import com.example.foo.fooCommon
import kotlin.test.Test
import kotlin.test.assertEquals
class AppTest {
@Test
fun testApp() {
appCommon()
assertEquals(foo(), fooCommon())
assertEquals(bar(), barCommon())
// fooJvmAndJs() // unresolved
// fooLinuxAndJs() // unresolved
// barJvmAndJs // unresolved
}
}
@@ -0,0 +1,17 @@
package com.example.app
import com.example.foo.*
import com.example.bar.*
import com.example.thirdparty.thirdPartyFun
fun appJvmAndJs() {
fooCommon()
fooJvmAndJs()
// fooLinuxAndJs() //unresolved
barCommon()
barJvmAndJs()
// barLinuxAndJs() // unresolved
thirdPartyFun()
}
@@ -0,0 +1,21 @@
package com.example.app
import com.example.bar.barCommon
import com.example.bar.barJvmAndJs
import com.example.foo.fooCommon
import com.example.foo.fooJvmAndJs
import com.example.thirdparty.thirdPartyFun
fun testAppJvmAndJs() {
fooCommon()
fooJvmAndJs()
// fooLinuxAndJs() //unresolved
barCommon()
barJvmAndJs()
// barLinuxAndJs() // unresolved
thirdPartyFun()
appJvmAndJs()
}
@@ -0,0 +1,19 @@
package com.example.app
import com.example.bar.barCommon
import com.example.bar.barJvmAndJs
import com.example.foo.fooCommon
import com.example.foo.fooJvmAndJs
import com.example.thirdparty.thirdPartyFun
import com.example.thirdparty.thirdPartyJvmFun
fun main() {
thirdPartyFun()
thirdPartyJvmFun()
fooCommon()
fooJvmAndJs()
barCommon()
barJvmAndJs()
}
@@ -0,0 +1,18 @@
package com.example.app
import com.example.bar.barCommon
import com.example.bar.barLinuxAndJs
import com.example.foo.fooCommon
import com.example.foo.fooLinuxAndJs
fun appLinuxAndJs() {
fooCommon()
fooLinuxAndJs()
// fooJvmAndJs() // unresolved
barCommon()
barLinuxAndJs()
// barJvmAndJs() // unresolved
// thirdPartyFun() // unresolved
}
@@ -0,0 +1,20 @@
package com.example.app
import com.example.bar.barCommon
import com.example.bar.barLinuxAndJs
import com.example.foo.fooCommon
import com.example.foo.fooLinuxAndJs
fun testAppLinuxAndJs() {
fooCommon()
fooLinuxAndJs()
// fooJvmAndJs() // unresolved
barCommon()
barLinuxAndJs()
// barJvmAndJs() // unresolved
// thirdPartyFun() // unresolved
appLinuxAndJs()
}
@@ -0,0 +1,8 @@
package com.example.bar
import com.example.foo.*
fun appLinux() {
fooLinuxAndJs()
barLinuxAndJs()
}
@@ -0,0 +1,95 @@
plugins {
kotlin("multiplatform")
`maven-publish`
}
repositories {
mavenLocal()
jcenter()
}
group = "com.example.bar"
version = "1.0"
kotlin {
jvm()
js()
linuxX64()
sourceSets {
val commonMain by getting {
dependencies {
api(project(":my-lib-foo"))
implementation(kotlin("stdlib-common"))
}
}
val commonTest by getting {
dependencies {
implementation(kotlin("test-common"))
implementation(kotlin("test-annotations-common"))
}
}
val jvmAndJsMain by creating {
dependsOn(commonMain)
}
val jvmAndJsTest by creating {
dependsOn(commonTest)
}
val linuxAndJsMain by creating {
dependsOn(commonMain)
}
val linuxAndJsTest by creating {
dependsOn(commonTest)
}
jvm().compilations["main"].defaultSourceSet {
dependsOn(jvmAndJsMain)
dependencies {
implementation(kotlin("stdlib"))
}
}
jvm().compilations["test"].defaultSourceSet {
dependsOn(jvmAndJsTest)
dependencies {
implementation(kotlin("test-junit"))
}
}
js().compilations["main"].defaultSourceSet {
dependsOn(jvmAndJsMain)
dependsOn(linuxAndJsMain)
dependencies {
implementation(kotlin("stdlib-js"))
}
}
js().compilations["test"].defaultSourceSet {
dependsOn(jvmAndJsTest)
dependsOn(linuxAndJsTest)
dependencies {
implementation(kotlin("test-js"))
}
}
linuxX64().compilations["main"].defaultSourceSet {
dependsOn(linuxAndJsMain)
}
linuxX64().compilations["test"].defaultSourceSet {
dependsOn(linuxAndJsTest)
}
}
}
publishing {
repositories {
maven("$rootDir/../repo")
}
}
@@ -0,0 +1,11 @@
package com.example.bar
import com.example.foo.*
expect fun bar(): String
fun barCommon(): String {
foo()
// thirdPartyFun() //unresolved
return fooCommon()
}
@@ -0,0 +1,17 @@
package com.example.bar
import com.example.foo.foo
import com.example.foo.fooCommon
import kotlin.test.Test
import kotlin.test.assertEquals
class BarTest {
@Test
fun testBar() {
// thirdPartyFun() // unresolved
// fooJvmAndJs() // unresolved
// fooLinuxAndJs() // unresolved
assertEquals(foo(), fooCommon())
assertEquals(bar(), barCommon())
}
}
@@ -0,0 +1,13 @@
package com.example.bar
import com.example.foo.*
import com.example.thirdparty.thirdPartyFun
actual fun bar(): String = barJvmAndJs()
fun barJvmAndJs(): String {
thirdPartyFun()
fooCommon()
// fooLinuxAndJs() //unresolved
return fooJvmAndJs()
}
@@ -0,0 +1,19 @@
package com.example.bar
import com.example.foo.foo
import com.example.thirdparty.thirdPartyFun
import kotlin.test.Test
import kotlin.test.assertEquals
class BarJvmAndJsTest {
@Test
fun testBarJvmAndJs() {
// barLinuxAndJs() // unresolved
assertEquals(foo(), barJvmAndJs())
}
@Test
fun testThirdParty() {
thirdPartyFun()
}
}
@@ -0,0 +1,10 @@
package com.example.bar
import com.example.foo.*
fun barLinuxAndJs(): String {
fooCommon()
// thirdPartyFun() // unresolved
// fooJvmAndJs() // unresolved
return fooLinuxAndJs()
}
@@ -0,0 +1,16 @@
package com.example.bar
import com.example.foo.fooCommon
import com.example.foo.fooLinuxAndJs
import kotlin.test.Test
class BarLinuxAndJsTest {
@Test
fun testBarLinuxAndJs() {
fooCommon()
fooLinuxAndJs()
// fooJvmAndJs() // unresolved
// thirdPartyFun() // unresolved
barLinuxAndJs()
}
}
@@ -0,0 +1,10 @@
package com.example.bar
import com.example.foo.*
actual fun bar(): String {
fooCommon()
fooLinuxAndJs()
// fooJvmAndJs() // unresolved
return barLinuxAndJs()
}
@@ -0,0 +1,100 @@
plugins {
kotlin("multiplatform")
`maven-publish`
}
repositories {
mavenLocal()
jcenter()
}
group = "com.example.foo"
version = "1.0"
kotlin {
jvm()
js()
// Add a target that the third-party-lib does not have:
linuxX64()
sourceSets {
val commonMain by getting {
dependencies {
implementation(kotlin("stdlib-common"))
}
}
val commonTest by getting {
dependencies {
implementation(kotlin("test-common"))
implementation(kotlin("test-annotations-common"))
}
}
val jvmAndJsMain by creating {
dependsOn(commonMain)
dependencies {
// Add the third-party-lib dependency only to these two platforms,
// as an API dependency, so that it is seen as transitive:
api("com.example.thirdparty:third-party-lib:1.0")
}
}
val jvmAndJsTest by creating {
dependsOn(commonTest)
}
val linuxAndJsMain by creating {
dependsOn(commonMain)
}
val linuxAndJsTest by creating {
dependsOn(commonTest)
}
jvm().compilations["main"].defaultSourceSet {
dependsOn(jvmAndJsMain)
dependencies {
implementation(kotlin("stdlib"))
}
}
jvm().compilations["test"].defaultSourceSet {
dependsOn(jvmAndJsTest)
dependencies {
implementation(kotlin("test-junit"))
}
}
js().compilations["main"].defaultSourceSet {
dependsOn(jvmAndJsMain)
dependsOn(linuxAndJsMain)
dependencies {
implementation(kotlin("stdlib-js"))
}
}
js().compilations["test"].defaultSourceSet {
dependsOn(jvmAndJsTest)
dependsOn(linuxAndJsTest)
dependencies {
implementation(kotlin("test-js"))
}
}
linuxX64().compilations["main"].defaultSourceSet {
dependsOn(linuxAndJsMain)
}
linuxX64().compilations["test"].defaultSourceSet {
dependsOn(linuxAndJsTest)
}
}
}
publishing {
repositories {
maven("$rootDir/../repo")
}
}
@@ -0,0 +1,5 @@
package com.example.foo
expect fun foo(): String
fun fooCommon() = "foo"
@@ -0,0 +1,11 @@
package com.example.foo
import kotlin.test.Test
import kotlin.test.assertEquals
class FooTest {
@Test
fun testFoo() {
assertEquals(foo(), fooCommon())
}
}
@@ -0,0 +1,10 @@
package com.example.foo
import com.example.thirdparty.thirdPartyFun
actual fun foo() = fooJvmAndJs()
fun fooJvmAndJs(): String {
thirdPartyFun()
return fooCommon()
}
@@ -0,0 +1,17 @@
package com.example.foo
import com.example.thirdparty.thirdPartyFun
import kotlin.test.Test
import kotlin.test.assertEquals
class FooJvmAndJsTest {
@Test
fun testFooJvmAndJs() {
assertEquals(fooJvmAndJs(), foo())
}
@Test
fun testThirdParty() {
thirdPartyFun()
}
}
@@ -0,0 +1,11 @@
package com.example.foo
import kotlin.test.*
class FooLinuxAndJsTest {
@Test
fun testFooJvmAndJs() {
assertEquals(foo(), fooCommon())
fooLinuxAndJs()
}
}
@@ -0,0 +1,12 @@
pluginManagement {
repositories {
mavenLocal()
gradlePluginPortal()
}
}
rootProject.name = "mpp-granular-metadata-demo"
include("my-lib-foo", "my-lib-bar", "my-app")
enableFeaturePreview("GRADLE_METADATA")
@@ -0,0 +1,57 @@
plugins {
kotlin("multiplatform").version("<pluginMarkerVersion>")
`maven-publish`
}
repositories {
mavenLocal()
jcenter()
}
group = "com.example.thirdparty"
version = "1.0"
kotlin {
jvm()
js()
sourceSets {
val commonMain by getting {
dependencies {
implementation(kotlin("stdlib-common"))
}
}
val commonTest by getting {
dependencies {
implementation(kotlin("test-common"))
implementation(kotlin("test-annotations-common"))
}
}
jvm().compilations["main"].defaultSourceSet {
dependencies {
implementation(kotlin("stdlib"))
}
}
jvm().compilations["test"].defaultSourceSet {
dependencies {
implementation(kotlin("test-junit"))
}
}
js().compilations["main"].defaultSourceSet {
dependencies {
implementation(kotlin("stdlib-js"))
}
}
js().compilations["test"].defaultSourceSet {
dependencies {
implementation(kotlin("test-js"))
}
}
}
}
publishing {
repositories {
maven("../repo")
}
}
@@ -0,0 +1,10 @@
pluginManagement {
repositories {
mavenLocal()
gradlePluginPortal()
}
}
rootProject.name = "third-party-lib"
enableFeaturePreview("GRADLE_METADATA")
@@ -0,0 +1,5 @@
package com.example.thirdparty
actual fun thirdPartyFun(): String = "thirdPartyFun @ js"
fun thirdPartyJsFun() { }
@@ -0,0 +1,5 @@
package com.example.thirdparty
actual fun thirdPartyFun(): String = "thirdPartyFun @ jvm"
fun thirdPartyJvmFun() { }
@@ -0,0 +1,89 @@
plugins {
kotlin("multiplatform").version("<pluginMarkerVersion>")
}
repositories {
mavenLocal()
maven("../repo")
jcenter()
}
group = "com.example.app"
version = "1.0"
kotlin {
jvm()
js()
linuxX64()
sourceSets {
val commonMain by getting {
dependencies {
api("com.example.bar:my-lib-bar:1.0")
implementation(kotlin("stdlib-common"))
}
}
val commonTest by getting {
dependencies {
implementation(kotlin("test-common"))
implementation(kotlin("test-annotations-common"))
}
}
val jvmAndJsMain by creating {
dependsOn(commonMain)
}
val jvmAndJsTest by creating {
dependsOn(commonTest)
}
val linuxAndJsMain by creating {
dependsOn(commonMain)
}
val linuxAndJsTest by creating {
dependsOn(commonTest)
}
jvm().compilations["main"].defaultSourceSet {
dependsOn(jvmAndJsMain)
dependencies {
implementation(kotlin("stdlib"))
}
}
jvm().compilations["test"].defaultSourceSet {
dependsOn(jvmAndJsTest)
dependencies {
implementation(kotlin("test-junit"))
}
}
js().compilations["main"].defaultSourceSet {
dependsOn(jvmAndJsMain)
dependsOn(linuxAndJsMain)
dependencies {
implementation(kotlin("stdlib-js"))
}
}
js().compilations["test"].defaultSourceSet {
dependsOn(jvmAndJsTest)
dependsOn(linuxAndJsTest)
dependencies {
implementation(kotlin("test-js"))
}
}
linuxX64().compilations["main"].defaultSourceSet {
dependsOn(linuxAndJsMain)
}
linuxX64().compilations["test"].defaultSourceSet {
dependsOn(linuxAndJsTest)
}
}
}
@@ -0,0 +1,10 @@
pluginManagement {
repositories {
mavenLocal()
gradlePluginPortal()
}
}
rootProject.name = "my-app"
enableFeaturePreview("GRADLE_METADATA")
@@ -0,0 +1,11 @@
package com.example.app
import com.example.foo.*
import com.example.bar.*
fun appCommon() {
foo()
fooCommon()
bar()
barCommon()
}
@@ -0,0 +1,20 @@
package com.example.app
import com.example.bar.bar
import com.example.bar.barCommon
import com.example.foo.foo
import com.example.foo.fooCommon
import kotlin.test.Test
import kotlin.test.assertEquals
class AppTest {
@Test
fun testApp() {
appCommon()
assertEquals(foo(), fooCommon())
assertEquals(bar(), barCommon())
// fooJvmAndJs() // unresolved
// fooLinuxAndJs() // unresolved
// barJvmAndJs // unresolved
}
}
@@ -0,0 +1,17 @@
package com.example.app
import com.example.foo.*
import com.example.bar.*
import com.example.thirdparty.thirdPartyFun
fun appJvmAndJs() {
fooCommon()
fooJvmAndJs()
// fooLinuxAndJs() //unresolved
barCommon()
barJvmAndJs()
// barLinuxAndJs() // unresolved
thirdPartyFun()
}
@@ -0,0 +1,21 @@
package com.example.app
import com.example.bar.barCommon
import com.example.bar.barJvmAndJs
import com.example.foo.fooCommon
import com.example.foo.fooJvmAndJs
import com.example.thirdparty.thirdPartyFun
fun testAppJvmAndJs() {
fooCommon()
fooJvmAndJs()
// fooLinuxAndJs() //unresolved
barCommon()
barJvmAndJs()
// barLinuxAndJs() // unresolved
thirdPartyFun()
appJvmAndJs()
}
@@ -0,0 +1,19 @@
package com.example.app
import com.example.bar.barCommon
import com.example.bar.barJvmAndJs
import com.example.foo.fooCommon
import com.example.foo.fooJvmAndJs
import com.example.thirdparty.thirdPartyFun
import com.example.thirdparty.thirdPartyJvmFun
fun main() {
thirdPartyFun()
thirdPartyJvmFun()
fooCommon()
fooJvmAndJs()
barCommon()
barJvmAndJs()
}
@@ -0,0 +1,18 @@
package com.example.app
import com.example.bar.barCommon
import com.example.bar.barLinuxAndJs
import com.example.foo.fooCommon
import com.example.foo.fooLinuxAndJs
fun appLinuxAndJs() {
fooCommon()
fooLinuxAndJs()
// fooJvmAndJs() // unresolved
barCommon()
barLinuxAndJs()
// barJvmAndJs() // unresolved
// thirdPartyFun() // unresolved
}
@@ -0,0 +1,20 @@
package com.example.app
import com.example.bar.barCommon
import com.example.bar.barLinuxAndJs
import com.example.foo.fooCommon
import com.example.foo.fooLinuxAndJs
fun testAppLinuxAndJs() {
fooCommon()
fooLinuxAndJs()
// fooJvmAndJs() // unresolved
barCommon()
barLinuxAndJs()
// barJvmAndJs() // unresolved
// thirdPartyFun() // unresolved
appLinuxAndJs()
}
@@ -0,0 +1,8 @@
package com.example.bar
import com.example.foo.*
fun appLinux() {
fooLinuxAndJs()
barLinuxAndJs()
}
@@ -0,0 +1,96 @@
plugins {
kotlin("multiplatform").version("<pluginMarkerVersion>")
`maven-publish`
}
repositories {
mavenLocal()
maven("../repo")
jcenter()
}
group = "com.example.bar"
version = "1.0"
kotlin {
jvm()
js()
linuxX64()
sourceSets {
val commonMain by getting {
dependencies {
api("com.example.foo:my-lib-foo:1.0")
implementation(kotlin("stdlib-common"))
}
}
val commonTest by getting {
dependencies {
implementation(kotlin("test-common"))
implementation(kotlin("test-annotations-common"))
}
}
val jvmAndJsMain by creating {
dependsOn(commonMain)
}
val jvmAndJsTest by creating {
dependsOn(commonTest)
}
val linuxAndJsMain by creating {
dependsOn(commonMain)
}
val linuxAndJsTest by creating {
dependsOn(commonTest)
}
jvm().compilations["main"].defaultSourceSet {
dependsOn(jvmAndJsMain)
dependencies {
implementation(kotlin("stdlib"))
}
}
jvm().compilations["test"].defaultSourceSet {
dependsOn(jvmAndJsTest)
dependencies {
implementation(kotlin("test-junit"))
}
}
js().compilations["main"].defaultSourceSet {
dependsOn(jvmAndJsMain)
dependsOn(linuxAndJsMain)
dependencies {
implementation(kotlin("stdlib-js"))
}
}
js().compilations["test"].defaultSourceSet {
dependsOn(jvmAndJsTest)
dependsOn(linuxAndJsTest)
dependencies {
implementation(kotlin("test-js"))
}
}
linuxX64().compilations["main"].defaultSourceSet {
dependsOn(linuxAndJsMain)
}
linuxX64().compilations["test"].defaultSourceSet {
dependsOn(linuxAndJsTest)
}
}
}
publishing {
repositories {
maven("../repo")
}
}
@@ -0,0 +1,10 @@
pluginManagement {
repositories {
mavenLocal()
gradlePluginPortal()
}
}
rootProject.name = "my-lib-bar"
enableFeaturePreview("GRADLE_METADATA")
@@ -0,0 +1,11 @@
package com.example.bar
import com.example.foo.*
expect fun bar(): String
fun barCommon(): String {
foo()
// thirdPartyFun() //unresolved
return fooCommon()
}
@@ -0,0 +1,17 @@
package com.example.bar
import com.example.foo.foo
import com.example.foo.fooCommon
import kotlin.test.Test
import kotlin.test.assertEquals
class BarTest {
@Test
fun testBar() {
// thirdPartyFun() // unresolved
// fooJvmAndJs() // unresolved
// fooLinuxAndJs() // unresolved
assertEquals(foo(), fooCommon())
assertEquals(bar(), barCommon())
}
}
@@ -0,0 +1,13 @@
package com.example.bar
import com.example.foo.*
import com.example.thirdparty.thirdPartyFun
actual fun bar(): String = barJvmAndJs()
fun barJvmAndJs(): String {
thirdPartyFun()
fooCommon()
// fooLinuxAndJs() //unresolved
return fooJvmAndJs()
}
@@ -0,0 +1,19 @@
package com.example.bar
import com.example.foo.foo
import com.example.thirdparty.thirdPartyFun
import kotlin.test.Test
import kotlin.test.assertEquals
class BarJvmAndJsTest {
@Test
fun testBarJvmAndJs() {
// barLinuxAndJs() // unresolved
assertEquals(foo(), barJvmAndJs())
}
@Test
fun testThirdParty() {
thirdPartyFun()
}
}
@@ -0,0 +1,10 @@
package com.example.bar
import com.example.foo.*
fun barLinuxAndJs(): String {
fooCommon()
// thirdPartyFun() // unresolved
// fooJvmAndJs() // unresolved
return fooLinuxAndJs()
}
@@ -0,0 +1,16 @@
package com.example.bar
import com.example.foo.fooCommon
import com.example.foo.fooLinuxAndJs
import kotlin.test.Test
class BarLinuxAndJsTest {
@Test
fun testBarLinuxAndJs() {
fooCommon()
fooLinuxAndJs()
// fooJvmAndJs() // unresolved
// thirdPartyFun() // unresolved
barLinuxAndJs()
}
}
@@ -0,0 +1,10 @@
package com.example.bar
import com.example.foo.*
actual fun bar(): String {
fooCommon()
fooLinuxAndJs()
// fooJvmAndJs() // unresolved
return barLinuxAndJs()
}
@@ -0,0 +1,101 @@
plugins {
kotlin("multiplatform").version("<pluginMarkerVersion>")
`maven-publish`
}
repositories {
mavenLocal()
maven("../repo")
jcenter()
}
group = "com.example.foo"
version = "1.0"
kotlin {
jvm()
js()
// Add a target that the third-party-lib does not have:
linuxX64()
sourceSets {
val commonMain by getting {
dependencies {
implementation(kotlin("stdlib-common"))
}
}
val commonTest by getting {
dependencies {
implementation(kotlin("test-common"))
implementation(kotlin("test-annotations-common"))
}
}
val jvmAndJsMain by creating {
dependsOn(commonMain)
dependencies {
// Add the third-party-lib dependency only to these two platforms,
// as an API dependency, so that it is seen as transitive:
api("com.example.thirdparty:third-party-lib:1.0")
}
}
val jvmAndJsTest by creating {
dependsOn(commonTest)
}
val linuxAndJsMain by creating {
dependsOn(commonMain)
}
val linuxAndJsTest by creating {
dependsOn(commonTest)
}
jvm().compilations["main"].defaultSourceSet {
dependsOn(jvmAndJsMain)
dependencies {
implementation(kotlin("stdlib"))
}
}
jvm().compilations["test"].defaultSourceSet {
dependsOn(jvmAndJsTest)
dependencies {
implementation(kotlin("test-junit"))
}
}
js().compilations["main"].defaultSourceSet {
dependsOn(jvmAndJsMain)
dependsOn(linuxAndJsMain)
dependencies {
implementation(kotlin("stdlib-js"))
}
}
js().compilations["test"].defaultSourceSet {
dependsOn(jvmAndJsTest)
dependsOn(linuxAndJsTest)
dependencies {
implementation(kotlin("test-js"))
}
}
linuxX64().compilations["main"].defaultSourceSet {
dependsOn(linuxAndJsMain)
}
linuxX64().compilations["test"].defaultSourceSet {
dependsOn(linuxAndJsTest)
}
}
}
publishing {
repositories {
maven("../repo")
}
}
@@ -0,0 +1,10 @@
pluginManagement {
repositories {
mavenLocal()
gradlePluginPortal()
}
}
rootProject.name = "my-lib-foo"
enableFeaturePreview("GRADLE_METADATA")
@@ -0,0 +1,5 @@
package com.example.foo
expect fun foo(): String
fun fooCommon() = "foo"
@@ -0,0 +1,11 @@
package com.example.foo
import kotlin.test.Test
import kotlin.test.assertEquals
class FooTest {
@Test
fun testFoo() {
assertEquals(foo(), fooCommon())
}
}
@@ -0,0 +1,10 @@
package com.example.foo
import com.example.thirdparty.thirdPartyFun
actual fun foo() = fooJvmAndJs()
fun fooJvmAndJs(): String {
thirdPartyFun()
return fooCommon()
}
@@ -0,0 +1,17 @@
package com.example.foo
import com.example.thirdparty.thirdPartyFun
import kotlin.test.Test
import kotlin.test.assertEquals
class FooJvmAndJsTest {
@Test
fun testFooJvmAndJs() {
assertEquals(fooJvmAndJs(), foo())
}
@Test
fun testThirdParty() {
thirdPartyFun()
}
}
@@ -0,0 +1,9 @@
package com.example.foo
class FooLinuxAndJsTest {
@Test
fun testFooJvmAndJs() {
assertEquals(foo(), fooCommon())
fooLinuxAndJs()
}
}
@@ -0,0 +1,57 @@
plugins {
kotlin("multiplatform").version("<pluginMarkerVersion>")
`maven-publish`
}
repositories {
mavenLocal()
jcenter()
}
group = "com.example.thirdparty"
version = "1.0"
kotlin {
jvm()
js()
sourceSets {
val commonMain by getting {
dependencies {
implementation(kotlin("stdlib-common"))
}
}
val commonTest by getting {
dependencies {
implementation(kotlin("test-common"))
implementation(kotlin("test-annotations-common"))
}
}
jvm().compilations["main"].defaultSourceSet {
dependencies {
implementation(kotlin("stdlib"))
}
}
jvm().compilations["test"].defaultSourceSet {
dependencies {
implementation(kotlin("test-junit"))
}
}
js().compilations["main"].defaultSourceSet {
dependencies {
implementation(kotlin("stdlib-js"))
}
}
js().compilations["test"].defaultSourceSet {
dependencies {
implementation(kotlin("test-js"))
}
}
}
}
publishing {
repositories {
maven("../repo")
}
}
@@ -0,0 +1,10 @@
pluginManagement {
repositories {
mavenLocal()
gradlePluginPortal()
}
}
rootProject.name = "third-party-lib"
enableFeaturePreview("GRADLE_METADATA")
@@ -0,0 +1,5 @@
package com.example.thirdparty
actual fun thirdPartyFun(): String = "thirdPartyFun @ js"
fun thirdPartyJsFun() { }
@@ -0,0 +1,5 @@
package com.example.thirdparty
actual fun thirdPartyFun(): String = "thirdPartyFun @ jvm"
fun thirdPartyJvmFun() { }