[Gradle][MPP] MppCInteropDependencyTransformationIT

^KT-46198
This commit is contained in:
sebastian.sellmair
2021-10-21 14:43:22 +02:00
committed by Space
parent 86296a8ced
commit 5f125006f7
57 changed files with 1772 additions and 65 deletions
@@ -976,3 +976,7 @@ Finished executing task ':$taskName'|
private fun String.normalizePath() = replace("\\", "/")
}
fun BaseGradleIT.BuildOptions.withFreeCommandLineArgument(argument: String) = copy(
freeCommandLineArgs = freeCommandLineArgs + argument
)
@@ -433,28 +433,29 @@ class CommonizerIT : BaseGradleIT() {
val isMac = HostManager.hostIsMac
val isWindows = HostManager.hostIsMingw
val testSourceSetsDependingOnMainParameter = "-PtestSourceSetsDependingOnMain=$testSourceSetsDependingOnMain"
fun CompiledProject.assertTestSourceSetsDependingOnMainParameter() {
val message = "testSourceSetsDependingOnMain is set"
if (testSourceSetsDependingOnMain) assertContains(message) else assertNotContains(message)
}
reportSourceSetCommonizerDependencies(this, testSourceSetsDependingOnMainParameter) {
val testSourceSetsDependingOnMainParameterOption = defaultBuildOptions()
.withFreeCommandLineArgument("-PtestSourceSetsDependingOnMain=$testSourceSetsDependingOnMain")
reportSourceSetCommonizerDependencies(this, options = testSourceSetsDependingOnMainParameterOption) {
it.assertTestSourceSetsDependingOnMainParameter()
/* this source sets are also shared with a jvm target */
getCommonizerDependencies("commonMain").assertEmpty()
getCommonizerDependencies("commonTest").assertEmpty()
getCommonizerDependencies("nativeMain").onlyCInterops().apply {
getCommonizerDependencies("nativeMain").withoutNativeDistributionDependencies().apply {
assertDependencyFilesMatches(".*nativeHelper")
assertTargetOnAllDependencies(
CommonizerTarget(IOS_X64, IOS_ARM64, LINUX_X64, LINUX_ARM64, MACOS_X64, MINGW_X64, MINGW_X86)
)
}
getCommonizerDependencies("nativeTest").onlyCInterops().apply {
getCommonizerDependencies("nativeTest").withoutNativeDistributionDependencies().apply {
assertDependencyFilesMatches(".*nativeHelper", ".*nativeTestHelper")
assertTargetOnAllDependencies(
CommonizerTarget(IOS_X64, IOS_ARM64, LINUX_X64, LINUX_ARM64, MACOS_X64, MINGW_X64, MINGW_X86)
@@ -462,22 +463,22 @@ class CommonizerIT : BaseGradleIT() {
}
if (isUnix) {
getCommonizerDependencies("unixMain").onlyCInterops().apply {
getCommonizerDependencies("unixMain").withoutNativeDistributionDependencies().apply {
assertDependencyFilesMatches(".*nativeHelper", ".*unixHelper")
assertTargetOnAllDependencies(CommonizerTarget(IOS_X64, IOS_ARM64, LINUX_X64, LINUX_ARM64, MACOS_X64))
}
getCommonizerDependencies("unixTest").onlyCInterops().apply {
getCommonizerDependencies("unixTest").withoutNativeDistributionDependencies().apply {
assertDependencyFilesMatches(".*nativeHelper", ".*unixHelper", ".*nativeTestHelper")
assertTargetOnAllDependencies(CommonizerTarget(IOS_X64, IOS_ARM64, LINUX_X64, LINUX_ARM64, MACOS_X64))
}
getCommonizerDependencies("linuxMain").onlyCInterops().apply {
getCommonizerDependencies("linuxMain").withoutNativeDistributionDependencies().apply {
assertDependencyFilesMatches(".*nativeHelper", ".*unixHelper")
assertTargetOnAllDependencies(CommonizerTarget(LINUX_X64, LINUX_ARM64))
}
getCommonizerDependencies("linuxTest").onlyCInterops().apply {
getCommonizerDependencies("linuxTest").withoutNativeDistributionDependencies().apply {
assertDependencyFilesMatches(".*nativeHelper", ".*unixHelper", ".*nativeTestHelper")
assertTargetOnAllDependencies(CommonizerTarget(LINUX_X64, LINUX_ARM64))
}
@@ -489,22 +490,22 @@ class CommonizerIT : BaseGradleIT() {
}
if (isMac) {
getCommonizerDependencies("appleMain").onlyCInterops().apply {
getCommonizerDependencies("appleMain").withoutNativeDistributionDependencies().apply {
assertDependencyFilesMatches(".*nativeHelper", ".*unixHelper", ".*appleHelper")
assertTargetOnAllDependencies(CommonizerTarget(IOS_X64, IOS_ARM64, MACOS_X64))
}
getCommonizerDependencies("appleTest").onlyCInterops().apply {
getCommonizerDependencies("appleTest").withoutNativeDistributionDependencies().apply {
assertDependencyFilesMatches(".*nativeHelper", ".*unixHelper", ".*appleHelper", ".*nativeTestHelper")
assertTargetOnAllDependencies(CommonizerTarget(IOS_X64, IOS_ARM64, MACOS_X64))
}
getCommonizerDependencies("iosMain").onlyCInterops().apply {
getCommonizerDependencies("iosMain").withoutNativeDistributionDependencies().apply {
assertDependencyFilesMatches(".*nativeHelper", ".*unixHelper", ".*appleHelper")
assertTargetOnAllDependencies(CommonizerTarget(IOS_X64, IOS_ARM64))
}
getCommonizerDependencies("iosTest").onlyCInterops().apply {
getCommonizerDependencies("iosTest").withoutNativeDistributionDependencies().apply {
assertDependencyFilesMatches(
".*nativeHelper", ".*unixHelper", ".*appleHelper", ".*nativeTestHelper", ".*iosTestHelper"
)
@@ -520,12 +521,12 @@ class CommonizerIT : BaseGradleIT() {
}
if (isWindows) {
getCommonizerDependencies("windowsMain").onlyCInterops().apply {
getCommonizerDependencies("windowsMain").withoutNativeDistributionDependencies().apply {
assertDependencyFilesMatches(".*nativeHelper", ".*windowsHelper")
assertTargetOnAllDependencies(CommonizerTarget(MINGW_X86, MINGW_X64))
}
getCommonizerDependencies("windowsTest").onlyCInterops().apply {
getCommonizerDependencies("windowsTest").withoutNativeDistributionDependencies().apply {
assertDependencyFilesMatches(".*nativeHelper", ".*windowsHelper", ".*nativeTestHelper")
assertTargetOnAllDependencies(CommonizerTarget(MINGW_X86, MINGW_X64))
}
@@ -537,44 +538,44 @@ class CommonizerIT : BaseGradleIT() {
}
}
build(":assemble", testSourceSetsDependingOnMainParameter) {
build(":assemble", options = testSourceSetsDependingOnMainParameterOption) {
assertTestSourceSetsDependingOnMainParameter()
assertSuccessful()
assertContains("Native Distribution Commonization: Cache hit")
assertTasksUpToDate(":commonizeCInterop")
}
build(":compileNativeMainKotlinMetadata", testSourceSetsDependingOnMainParameter) {
build(":compileNativeMainKotlinMetadata", options = testSourceSetsDependingOnMainParameterOption) {
assertTestSourceSetsDependingOnMainParameter()
assertSuccessful()
}
if (isUnix) {
build(":compileUnixMainKotlinMetadata", testSourceSetsDependingOnMainParameter) {
build(":compileUnixMainKotlinMetadata", options = testSourceSetsDependingOnMainParameterOption) {
assertTestSourceSetsDependingOnMainParameter()
assertSuccessful()
}
build(":compileLinuxMainKotlinMetadata", testSourceSetsDependingOnMainParameter) {
build(":compileLinuxMainKotlinMetadata", options = testSourceSetsDependingOnMainParameterOption) {
assertTestSourceSetsDependingOnMainParameter()
assertSuccessful()
}
}
if (isMac) {
build(":compileAppleMainKotlinMetadata", testSourceSetsDependingOnMainParameter) {
build(":compileAppleMainKotlinMetadata", options = testSourceSetsDependingOnMainParameterOption) {
assertTestSourceSetsDependingOnMainParameter()
assertSuccessful()
}
build(":compileIosMainKotlinMetadata", testSourceSetsDependingOnMainParameter) {
build(":compileIosMainKotlinMetadata", options = testSourceSetsDependingOnMainParameterOption) {
assertTestSourceSetsDependingOnMainParameter()
assertSuccessful()
}
}
if (isWindows) {
build(":compileWindowsMainKotlinMetadata", testSourceSetsDependingOnMainParameter) {
build(":compileWindowsMainKotlinMetadata", options = testSourceSetsDependingOnMainParameterOption) {
assertTestSourceSetsDependingOnMainParameter()
assertSuccessful()
}
@@ -587,12 +588,12 @@ class CommonizerIT : BaseGradleIT() {
with(Project("commonize-kt-48118-c-interop-in-common-main")) {
reportSourceSetCommonizerDependencies(this) {
val upperMain = getCommonizerDependencies("upperMain")
upperMain.onlyCInterops().assertDependencyFilesMatches(".*cinterop-dummy")
upperMain.onlyNativeDistribution().assertNotEmpty()
upperMain.withoutNativeDistributionDependencies().assertDependencyFilesMatches(".*cinterop-dummy")
upperMain.onlyNativeDistributionDependencies().assertNotEmpty()
val commonMain = getCommonizerDependencies("commonMain")
commonMain.onlyCInterops().assertDependencyFilesMatches(".*cinterop-dummy")
commonMain.onlyNativeDistribution().assertNotEmpty()
commonMain.withoutNativeDistributionDependencies().assertDependencyFilesMatches(".*cinterop-dummy")
commonMain.onlyNativeDistributionDependencies().assertNotEmpty()
}
build(":compileCommonMainKotlinMetadata") {
@@ -633,13 +634,13 @@ class CommonizerIT : BaseGradleIT() {
with(Project("commonize-kt-48138-nativeMain-nativeTest-different-targets")) {
reportSourceSetCommonizerDependencies(this) {
val nativeMain = getCommonizerDependencies("nativeMain")
nativeMain.onlyCInterops().assertDependencyFilesMatches(".*cinterop-dummy")
nativeMain.onlyNativeDistribution().assertNotEmpty()
nativeMain.withoutNativeDistributionDependencies().assertDependencyFilesMatches(".*cinterop-dummy")
nativeMain.onlyNativeDistributionDependencies().assertNotEmpty()
nativeMain.assertTargetOnAllDependencies(CommonizerTarget(LINUX_X64, LINUX_ARM64, LINUX_ARM32_HFP))
val nativeTest = getCommonizerDependencies("nativeTest")
nativeTest.onlyNativeDistribution().assertNotEmpty()
nativeTest.onlyCInterops().assertDependencyFilesMatches(".*cinterop-dummy")
nativeTest.onlyNativeDistributionDependencies().assertNotEmpty()
nativeTest.withoutNativeDistributionDependencies().assertDependencyFilesMatches(".*cinterop-dummy")
nativeTest.assertTargetOnAllDependencies(CommonizerTarget(LINUX_X64, LINUX_ARM64))
}
}
@@ -0,0 +1,269 @@
/*
* Copyright 2010-2021 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.gradle.api.logging.configuration.WarningMode
import org.jetbrains.kotlin.commonizer.CommonizerTarget
import org.jetbrains.kotlin.gradle.util.WithSourceSetCommonizerDependencies
import org.jetbrains.kotlin.gradle.util.reportSourceSetCommonizerDependencies
import org.jetbrains.kotlin.konan.target.HostManager
import org.jetbrains.kotlin.konan.target.KonanTarget.*
import org.junit.Test
/**
* Runs Tests on a Gradle project with three subprojects
*
* p1: Depends on two cinterops (cinterop-simple & cinterop-withPosix) that will get commonized
* p2: Depends on p1 (either as project or repository dependency)
* p3: Depends on p2 (and has slightly different source set layout)
*
* The tests can run in two modes
* - dependency-mode=project: In this case p2 will just declare a regular project dependency on p1
* - dependency-mode=repository: In this case p2 will rely on a previously published version of p1
*/
class MppCInteropDependencyTransformationIT : BaseGradleIT() {
private val baseBuildOptions = defaultBuildOptions().copy(
forceOutputToStdout = true,
warningMode = WarningMode.Fail,
parallelTasksInProject = true,
freeCommandLineArgs = defaultBuildOptions().freeCommandLineArgs + "-s"
)
private val projectDependencyOptions = baseBuildOptions.copy(
freeCommandLineArgs = baseBuildOptions.freeCommandLineArgs + "-PdependencyMode=project"
)
private val repositoryDependencyOptions = baseBuildOptions.copy(
freeCommandLineArgs = baseBuildOptions.freeCommandLineArgs + "-PdependencyMode=repository"
)
private val project by lazy { Project("cinterop-MetadataDependencyTransformation") }
@Test
fun `test - compile project - dependencyMode=project`() {
testCompileProject(projectDependencyOptions) {
assertProjectDependencyMode()
assertTasksExecuted(":p1:commonizeCInterop")
}
}
@Test
fun `test - compile project - dependencyMode=repository`() {
publishP1ToBuildRepository()
testCompileProject(repositoryDependencyOptions) {
assertRepositoryDependencyMode()
}
}
private fun testCompileProject(options: BuildOptions, check: CompiledProject.() -> Unit = {}) {
project.build("compileAll", options = options) {
check()
assertSuccessful()
/* Assert p2 & p3 compiled metadata */
assertTasksExecuted(":p2:compileNativeMainKotlinMetadata")
assertTasksExecuted(":p2:compileLinuxMainKotlinMetadata")
assertTasksExecuted(":p3:compileNativeMainKotlinMetadata")
if (HostManager.hostIsMac) {
assertTasksExecuted(":p2:compileAppleMainKotlinMetadata")
assertTasksExecuted(":p2:compileIosMainKotlinMetadata")
assertTasksExecuted(":p3:compileAppleAndLinuxMainKotlinMetadata")
assertTasksExecuted(":p3:compileIosMainKotlinMetadata")
}
if (HostManager.hostIsMingw || HostManager.hostIsMac) {
assertTasksExecuted(":p2:compileWindowsMainKotlinMetadata")
assertTasksExecuted(":p3:compileWindowsMainKotlinMetadata")
}
/* Assert p2 & p3 transformed cinterop dependencies */
assertTasksExecuted(":p2:transformNativeMainCInteropDependenciesMetadata")
assertTasksExecuted(":p3:transformNativeMainCInteropDependenciesMetadata")
/* Assert p2 & p3 compiled tests */
assertTasksExecuted(":p2:compileTestKotlinLinuxX64")
assertTasksExecuted(":p3:compileTestKotlinLinuxX64")
}
}
@Test
fun `test - source set dependencies - dependencyMode=project`() {
reportSourceSetCommonizerDependencies(project, "p2", projectDependencyOptions) {
it.assertProjectDependencyMode()
it.assertTasksExecuted(":p2:transformNativeMainCInteropDependenciesMetadataForIde")
it.assertTasksNotExecuted(".*[cC]ompile.*")
assertP2SourceSetDependencies()
}
reportSourceSetCommonizerDependencies(project, "p3", projectDependencyOptions) {
it.assertProjectDependencyMode()
it.assertTasksExecuted(":p3:transformNativeMainCInteropDependenciesMetadataForIde")
it.assertTasksNotExecuted(".*[cC]ompile.*")
assertP3SourceSetDependencies()
}
}
@Test
fun `test - source set dependencies - dependencyMode=repository`() {
publishP1ToBuildRepository()
reportSourceSetCommonizerDependencies(project, "p2", repositoryDependencyOptions) {
it.assertRepositoryDependencyMode()
it.assertTasksExecuted(":p2:transformNativeMainCInteropDependenciesMetadataForIde")
it.assertTasksNotExecuted(".*[cC]ompile.*")
assertP2SourceSetDependencies()
}
reportSourceSetCommonizerDependencies(project, "p3", repositoryDependencyOptions) {
it.assertRepositoryDependencyMode()
it.assertTasksExecuted(":p3:transformNativeMainCInteropDependenciesMetadataForIde")
it.assertTasksNotExecuted(".*[cC]ompile.*")
assertP3SourceSetDependencies()
}
}
private fun WithSourceSetCommonizerDependencies.assertP2SourceSetDependencies() {
listOf("nativeMain", "nativeTest").forEach { sourceSetName ->
getCommonizerDependencies(sourceSetName).withoutNativeDistributionDependencies()
.assertDependencyFilesMatches(".*cinterop-simple.*", ".*cinterop-withPosix.*")
.assertTargetOnAllDependencies(
CommonizerTarget(LINUX_ARM64, LINUX_X64, IOS_ARM64, IOS_X64, MACOS_X64, MINGW_X64, MINGW_X86)
)
}
if (HostManager.hostIsMac) {
listOf("appleAndLinuxMain", "appleAndLinuxTest").forEach { sourceSetName ->
getCommonizerDependencies(sourceSetName).withoutNativeDistributionDependencies()
.assertDependencyFilesMatches(".*cinterop-simple.*", ".*cinterop-withPosix.*")
.assertTargetOnAllDependencies(CommonizerTarget(LINUX_ARM64, LINUX_X64, IOS_ARM64, IOS_X64, MACOS_X64))
}
listOf("appleMain", "appleTest").forEach { sourceSetName ->
getCommonizerDependencies(sourceSetName).withoutNativeDistributionDependencies()
.assertDependencyFilesMatches(".*cinterop-simple.*", ".*cinterop-withPosix.*")
.assertTargetOnAllDependencies(CommonizerTarget(IOS_ARM64, IOS_X64, MACOS_X64))
}
listOf("iosMain", "iosTest").forEach { sourceSetName ->
getCommonizerDependencies(sourceSetName).withoutNativeDistributionDependencies()
.assertDependencyFilesMatches(".*cinterop-simple.*", ".*cinterop-withPosix.*")
.assertTargetOnAllDependencies(CommonizerTarget(IOS_ARM64, IOS_X64))
}
}
if (HostManager.hostIsMingw || HostManager.hostIsMac) {
listOf("windowsMain", "windowsTest").forEach { sourceSetName ->
getCommonizerDependencies(sourceSetName).withoutNativeDistributionDependencies()
.assertDependencyFilesMatches(".*cinterop-simple.*", ".*cinterop-withPosix.*")
.assertTargetOnAllDependencies(CommonizerTarget(MINGW_X64, MINGW_X86))
}
listOf("linuxMain", "linuxTest").forEach { sourceSetName ->
getCommonizerDependencies(sourceSetName).withoutNativeDistributionDependencies()
.assertDependencyFilesMatches(".*cinterop-simple.*", ".*cinterop-withPosix.*")
.assertTargetOnAllDependencies(CommonizerTarget(LINUX_ARM64, LINUX_X64))
}
}
}
private fun WithSourceSetCommonizerDependencies.assertP3SourceSetDependencies() {
/*
windowsAndLinuxMain / windowsAndLinuxTest will not have a 'perfect target match' in p1.
They will choose cinterops associated with 'nativeMain'
*/
listOf("nativeMain", "nativeTest", "windowsAndLinuxMain", "windowsAndLinuxTest").forEach { sourceSetName ->
getCommonizerDependencies(sourceSetName).withoutNativeDistributionDependencies()
.assertDependencyFilesMatches(".*cinterop-simple.*", ".*cinterop-withPosix.*")
.assertTargetOnAllDependencies(
CommonizerTarget(LINUX_ARM64, LINUX_X64, IOS_ARM64, IOS_X64, MACOS_X64, MINGW_X64, MINGW_X86)
)
}
if (HostManager.hostIsMac) {
listOf("appleAndLinuxMain", "appleAndLinuxTest").forEach { sourceSetName ->
getCommonizerDependencies(sourceSetName).withoutNativeDistributionDependencies()
.assertDependencyFilesMatches(".*cinterop-simple.*", ".*cinterop-withPosix.*")
.assertTargetOnAllDependencies(CommonizerTarget(LINUX_ARM64, LINUX_X64, IOS_ARM64, IOS_X64, MACOS_X64))
}
listOf("iosMain", "iosTest").forEach { sourceSetName ->
getCommonizerDependencies(sourceSetName).withoutNativeDistributionDependencies()
.assertDependencyFilesMatches(".*cinterop-simple.*", ".*cinterop-withPosix.*")
.assertTargetOnAllDependencies(CommonizerTarget(IOS_ARM64, IOS_X64))
}
}
if (HostManager.hostIsMingw || HostManager.hostIsMac) {
listOf("windowsMain", "windowsTest").forEach { sourceSetName ->
getCommonizerDependencies(sourceSetName).withoutNativeDistributionDependencies()
.assertDependencyFilesMatches(".*cinterop-simple.*", ".*cinterop-withPosix.*")
.assertTargetOnAllDependencies(CommonizerTarget(MINGW_X64, MINGW_X86))
}
}
}
@Test
fun `test - transformation - UP-TO-DATE behaviour`() {
publishP1ToBuildRepository()
project.build(":p3:transformNativeMainCInteropDependenciesMetadata", options = repositoryDependencyOptions) {
assertSuccessful()
assertTasksExecuted(":p3:transformNativeMainCInteropDependenciesMetadata")
}
project.build(":p3:transformNativeMainCInteropDependenciesMetadata", options = repositoryDependencyOptions) {
assertSuccessful()
assertTasksNotExecuted(":p3:transformNativeMainCInteropDependenciesMetadata")
assertTasksUpToDate(":p3:transformNativeMainCInteropDependenciesMetadata")
}
val p3BuildGradleKts = project.projectDir.resolve("p3/build.gradle.kts")
val p3BuildGradleKtsContent = p3BuildGradleKts.readText()
// Remove dependency on p2 | Task should re-run
p3BuildGradleKts.writeText(p3BuildGradleKtsContent.replace("""implementation(project(":p2"))""", ""))
project.build(":p3:transformNativeMainCInteropDependenciesMetadata", options = repositoryDependencyOptions) {
assertSuccessful()
assertTasksExecuted(":p3:transformNativeMainCInteropDependenciesMetadata")
}
// Re-add dependency on p3 | Task should re-run for the next invocation
p3BuildGradleKts.writeText(p3BuildGradleKtsContent)
project.build(":p3:transformNativeMainCInteropDependenciesMetadata", options = repositoryDependencyOptions) {
assertSuccessful()
assertTasksExecuted(":p3:transformNativeMainCInteropDependenciesMetadata")
}
project.build(":p3:transformNativeMainCInteropDependenciesMetadata", options = repositoryDependencyOptions) {
assertSuccessful()
assertTasksNotExecuted(":p3:transformNativeMainCInteropDependenciesMetadata")
assertTasksUpToDate(":p3:transformNativeMainCInteropDependenciesMetadata")
}
// Replace dependency to :p2 with coordinates directly
p3BuildGradleKts.writeText(
p3BuildGradleKtsContent.replace("""project(":p2")""", """"kotlin-multiplatform-projects:p1:1.0.0-SNAPSHOT"""")
)
project.build(":p3:transformNativeMainCInteropDependenciesMetadata", options = repositoryDependencyOptions) {
assertSuccessful()
assertTasksExecuted(":p3:transformNativeMainCInteropDependenciesMetadata")
}
}
private fun publishP1ToBuildRepository() {
project.build(":p1:publishAllPublicationsToBuildRepository", options = repositoryDependencyOptions) {
assertSuccessful()
}
}
private fun CompiledProject.assertProjectDependencyMode() {
assertContains("dependencyMode = 'project'")
}
private fun CompiledProject.assertRepositoryDependencyMode() {
assertContains("dependencyMode = 'repository'")
}
}
@@ -9,10 +9,13 @@ import org.intellij.lang.annotations.Language
import org.intellij.lang.annotations.RegExp
import org.jetbrains.kotlin.commonizer.CommonizerTarget
import org.jetbrains.kotlin.commonizer.SharedCommonizerTarget
import org.jetbrains.kotlin.commonizer.parseCommonizerTargetOrNull
import org.jetbrains.kotlin.commonizer.parseCommonizerTarget
import org.jetbrains.kotlin.commonizer.util.transitiveClosure
import org.jetbrains.kotlin.gradle.BaseGradleIT
import org.jetbrains.kotlin.gradle.BaseGradleIT.CompiledProject
import org.jetbrains.kotlin.library.ToolingSingleFileKlibResolveStrategy
import org.jetbrains.kotlin.library.commonizerTarget
import org.jetbrains.kotlin.library.resolveSingleFileKlib
import java.io.File
import javax.annotation.RegEx
import kotlin.test.fail
@@ -28,29 +31,29 @@ data class SourceSetCommonizerDependencies(
val dependencies: Set<SourceSetCommonizerDependency>
) {
fun onlyCInterops(): SourceSetCommonizerDependencies {
fun withoutNativeDistributionDependencies(): SourceSetCommonizerDependencies {
return SourceSetCommonizerDependencies(
sourceSetName,
dependencies.filter { dependency ->
/* Cinterop dependencies are located in the project's '.gradle' directory */
dependency.file.allParents.any { parentFile -> parentFile.name == ".gradle" }
}.toSet()
dependencies.filter { dependency -> !dependency.isFromNativeDistribution() }.toSet()
)
}
fun onlyNativeDistribution(): SourceSetCommonizerDependencies {
fun onlyNativeDistributionDependencies(): SourceSetCommonizerDependencies {
return SourceSetCommonizerDependencies(
sourceSetName,
dependencies.filter { dependency -> dependency.isFromNativeDistribution() }.toSet()
)
}
private fun SourceSetCommonizerDependency.isFromNativeDistribution(): Boolean {
val konanDataDir = System.getenv("KONAN_DATA_DIR")?.let(::File)
return SourceSetCommonizerDependencies(
sourceSetName,
dependencies.filter { dependency ->
(if (konanDataDir != null) dependency.file.startsWith(konanDataDir) else false) ||
dependency.file.allParents.any { parentFile -> parentFile.name == ".konan" }
}.toSet()
)
if (konanDataDir != null) {
return file.startsWith(konanDataDir)
}
return file.allParents.any { parentFile -> parentFile.name == ".konan" }
}
fun assertTargetOnAllDependencies(target: CommonizerTarget) {
fun assertTargetOnAllDependencies(target: CommonizerTarget) = apply {
dependencies.forEach { dependency ->
if (dependency.target != target) {
fail("$sourceSetName: Expected target $target but found dependency with target ${dependency.target}\n$dependency")
@@ -58,27 +61,27 @@ data class SourceSetCommonizerDependencies(
}
}
fun assertEmpty() {
fun assertEmpty() = apply {
if (dependencies.isNotEmpty()) {
fail("$sourceSetName: Expected no dependencies in set. Found $dependencies")
}
}
fun assertNotEmpty() {
fun assertNotEmpty() = apply {
if (dependencies.isEmpty()) {
fail("$sourceSetName: Missing dependencies")
}
}
fun assertDependencyFilesMatches(@Language("RegExp") @RegEx @RegExp vararg fileMatchers: String?) {
fun assertDependencyFilesMatches(@Language("RegExp") @RegEx @RegExp vararg fileMatchers: String?) = apply {
assertDependencyFilesMatches(fileMatchers.filterNotNull().map(::Regex).toSet())
}
fun assertDependencyFilesMatches(vararg fileMatchers: Regex?) {
fun assertDependencyFilesMatches(vararg fileMatchers: Regex?) = apply {
assertDependencyFilesMatches(fileMatchers.filterNotNull().toSet())
}
fun assertDependencyFilesMatches(fileMatchers: Set<Regex>) {
fun assertDependencyFilesMatches(fileMatchers: Set<Regex>) = apply {
val unmatchedDependencies = dependencies.filter { dependency ->
fileMatchers.none { matcher -> dependency.file.absolutePath.matches(matcher) }
}
@@ -107,7 +110,8 @@ fun interface WithSourceSetCommonizerDependencies {
fun BaseGradleIT.reportSourceSetCommonizerDependencies(
project: BaseGradleIT.Project,
vararg additionalBuildParameters: String,
subproject: String? = null,
options: BaseGradleIT.BuildOptions = defaultBuildOptions(),
test: WithSourceSetCommonizerDependencies.(compiledProject: CompiledProject) -> Unit
) = with(project) {
@@ -115,15 +119,18 @@ fun BaseGradleIT.reportSourceSetCommonizerDependencies(
setupWorkingDir()
}
gradleBuildScript().apply {
gradleBuildScript(subproject).apply {
appendText("\n\n")
appendText(taskSourceCode)
appendText("\n\n")
}
build(
*(listOf(":reportCommonizerSourceSetDependencies") + additionalBuildParameters).toTypedArray(),
) {
val taskName = buildString {
if (subproject != null) append(":$subproject")
append(":reportCommonizerSourceSetDependencies")
}
build(taskName, options = options) {
assertSuccessful()
val dependencyReports = output.lineSequence().filter { line -> line.contains("SourceSetCommonizerDependencyReport") }.toList()
@@ -134,21 +141,30 @@ fun BaseGradleIT.reportSourceSetCommonizerDependencies(
val reportForSourceSet = dependencyReports.firstOrNull { line -> line.contains(reportMarker) }
?: fail("Missing dependency report for $sourceSetName")
val files = reportForSourceSet.split(reportMarker, limit = 2).last().split("|#+#|").map(::File)
val dependencies = files.mapNotNull { file ->
val allParents = file.allParents
if (allParents.any { it.name == "commonized" } || allParents.any { it.name == "commonizer" }) {
val target = parseCommonizerTargetOrNull(file.parentFile.name) as? SharedCommonizerTarget ?: return@mapNotNull null
SourceSetCommonizerDependency(sourceSetName, target, file)
} else null
}
SourceSetCommonizerDependencies(sourceSetName, dependencies.toSet())
val files = reportForSourceSet.split(reportMarker, limit = 2).last().split("|#+#|")
.map(String::trim).filter(String::isNotEmpty).map(::File)
val dependencies = files.mapNotNull { file -> createSourceSetCommonizerDependencyOrNull(sourceSetName, file) }.toSet()
SourceSetCommonizerDependencies(sourceSetName, dependencies)
}
withSourceSetCommonizerDependencies.test(this)
}
}
private fun createSourceSetCommonizerDependencyOrNull(sourceSetName: String, libraryFile: File): SourceSetCommonizerDependency? {
return SourceSetCommonizerDependency(
sourceSetName,
file = libraryFile,
target = inferCommonizerTargetOrNull(libraryFile) as? SharedCommonizerTarget ?: return null,
)
}
private fun inferCommonizerTargetOrNull(libraryFile: File): CommonizerTarget? = resolveSingleFileKlib(
libraryFile = org.jetbrains.kotlin.konan.file.File(libraryFile.path),
strategy = ToolingSingleFileKlibResolveStrategy
).commonizerTarget?.let(::parseCommonizerTarget)
private val File.allParents: Set<File> get() = transitiveClosure(this) { listOfNotNull(parentFile) }
private const val dollar = "\$"
@@ -0,0 +1,6 @@
gradlew
gradlew.bat
gradle
.idea
.gradle
**/build/**
@@ -0,0 +1,23 @@
import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension
plugins {
kotlin("multiplatform") apply false
}
allprojects {
repositories {
mavenLocal()
mavenCentral()
}
afterEvaluate {
extensions.findByType<KotlinMultiplatformExtension>()?.let { kotlin ->
val compileAll by tasks.creating
kotlin.targets.all {
compileAll.dependsOn(
provider { compilations.map { it.compileKotlinTaskName } }
)
}
}
}
}
@@ -0,0 +1,5 @@
kotlin.mpp.enableGranularSourceSetsMetadata=true
kotlin.native.enableDependencyPropagation=false
kotlin.mpp.enableCInteropCommonization=true
kotlin.mpp.enableHierarchicalCommonization=true
kotlin.mpp.enableIntransitiveMetadataConfiguration=true
@@ -0,0 +1,90 @@
import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget
operator fun KotlinSourceSet.invoke(builder: SourceSetHierarchyBuilder.() -> Unit): KotlinSourceSet {
SourceSetHierarchyBuilder(this).builder()
return this
}
class SourceSetHierarchyBuilder(private val node: KotlinSourceSet) {
operator fun KotlinSourceSet.unaryMinus() = this.dependsOn(node)
}
plugins {
kotlin("multiplatform")
`maven-publish`
}
version = "1.0.0-SNAPSHOT"
publishing {
repositories {
this.maven {
this.name = "build"
this.url = rootProject.buildDir.resolve("repo").toURI()
}
}
}
kotlin {
js().nodejs()
jvm()
linuxX64()
linuxArm64()
macosX64("macos")
ios()
mingwX64("windowsX64")
mingwX86("windowsX86")
val commonMain by sourceSets.getting
val concurrentMain by sourceSets.creating
val jvmMain by sourceSets.getting
val jsMain by sourceSets.getting
val nativeMain by sourceSets.creating
val appleAndLinuxMain by sourceSets.creating
val linuxMain by sourceSets.creating
val linuxX64Main by sourceSets.getting
val linuxArm64Main by sourceSets.getting
val appleMain by sourceSets.creating
val macosMain by sourceSets.getting
val iosMain by sourceSets.getting
val windowsMain by sourceSets.creating
val windowsX64Main by sourceSets.getting
val windowsX86Main by sourceSets.getting
commonMain {
-jsMain
-concurrentMain {
-jvmMain
-nativeMain {
-appleAndLinuxMain {
-appleMain {
-iosMain
-macosMain
}
-linuxMain {
-linuxArm64Main
-linuxX64Main
}
}
-windowsMain {
-windowsX64Main
-windowsX86Main
}
}
}
}
targets.withType<KotlinNativeTarget>().forEach { target ->
target.compilations.getByName("main").cinterops.create("withPosix") {
this.packageName = "withPosix"
header(file("libs/withPosix.h"))
}
target.compilations.getByName("main").cinterops.create("simple") {
header(file("libs/simple.h"))
}
}
}
@@ -0,0 +1,43 @@
#include <sys/stat.h>
#include <stdint.h>
#include <stdbool.h>
struct stat getStructFromPosix();
struct stat* getStructPointerFromPosix();
struct MyStruct getMyStruct();
struct MyStruct* getMyStructPointer();
struct MyStruct {
struct stat posixProperty;
#if _WIN32
long long longProperty;
#else
long longProperty;
#endif
double doubleProperty;
int32_t int32tProperty;
int64_t int64tProperty;
#if __linux__
bool linuxOnlyProperty;
#endif
#if __APPLE__
bool appleOnlyProperty;
#include "TargetConditionals.h"
#if TARGET_OS_IPHONE
bool iosOnlyProperty;
#endif
#endif
#if _WIN32
bool windowsOnlyProperty;
#endif
};
@@ -0,0 +1,24 @@
@file:Suppress("unused")
import kotlinx.cinterop.pointed
import platform.posix.stat
import simple.simpleInterop
import withPosix.getMyStructPointer
import withPosix.getStructFromPosix
import withPosix.getStructPointerFromPosix
object AppleAndLinuxMain {
val structFromPosix = getStructFromPosix()
val structPointerFromPosix = getStructPointerFromPosix()
object MyStruct {
val struct = getMyStructPointer()?.pointed ?: error("Missing my struct")
val posixProperty: stat = struct.posixProperty
val longProperty: Long = struct.longProperty
val doubleProperty: Double = struct.doubleProperty
val int32tProperty: Int = struct.int32tProperty
val int64TProperty: Long = struct.int64tProperty
}
val simple = simpleInterop()
}
@@ -0,0 +1,25 @@
@file:Suppress("unused")
import kotlinx.cinterop.pointed
import platform.posix.stat
import simple.simpleInterop
import withPosix.getMyStructPointer
import withPosix.getStructFromPosix
import withPosix.getStructPointerFromPosix
object AppleMain {
val structFromPosix = getStructFromPosix()
val structPointerFromPosix = getStructPointerFromPosix()
object MyStruct {
val struct = getMyStructPointer()?.pointed ?: error("Missing my struct")
val posixProperty: stat = struct.posixProperty
val longProperty: Long = struct.longProperty
val doubleProperty: Double = struct.doubleProperty
val int32tProperty: Int = struct.int32tProperty
val int64TProperty: Long = struct.int64tProperty
val appleOnlyProperty: Boolean = struct.appleOnlyProperty
}
val simple = simpleInterop()
}
@@ -0,0 +1,26 @@
@file:Suppress("unused")
import kotlinx.cinterop.pointed
import platform.posix.stat
import simple.simpleInterop
import withPosix.getMyStructPointer
import withPosix.getStructFromPosix
import withPosix.getStructPointerFromPosix
object IosMain {
val structFromPosix = getStructFromPosix()
val structPointerFromPosix = getStructPointerFromPosix()
object MyStruct {
val struct = getMyStructPointer()?.pointed ?: error("Missing my struct")
val posixProperty: stat = struct.posixProperty
val longProperty: Long = struct.longProperty
val doubleProperty: Double = struct.doubleProperty
val int32tProperty: Int = struct.int32tProperty
val int64TProperty: Long = struct.int64tProperty
val appleOnly: Boolean = struct.appleOnlyProperty
val iosOnly: Boolean = struct.iosOnlyProperty
}
val simple = simpleInterop()
}
@@ -0,0 +1,25 @@
@file:Suppress("unused")
import kotlinx.cinterop.pointed
import platform.posix.stat
import simple.simpleInterop
import withPosix.getMyStructPointer
import withPosix.getStructFromPosix
import withPosix.getStructPointerFromPosix
object LinuxArm64Main {
val structFromPosix = getStructFromPosix()
val structPointerFromPosix = getStructPointerFromPosix()
object MyStruct {
val struct = getMyStructPointer()?.pointed ?: error("Missing my struct")
val posixProperty: stat = struct.posixProperty
val longProperty: Long = struct.longProperty
val doubleProperty: Double = struct.doubleProperty
val int32tProperty: Int = struct.int32tProperty
val int64TProperty: Long = struct.int64tProperty
val linuxOnlyProperty: Boolean = struct.linuxOnlyProperty
}
val simple = simpleInterop()
}
@@ -0,0 +1,25 @@
@file:Suppress("unused")
import kotlinx.cinterop.pointed
import platform.posix.stat
import simple.simpleInterop
import withPosix.getMyStructPointer
import withPosix.getStructFromPosix
import withPosix.getStructPointerFromPosix
object LinuxMain {
val structFromPosix = getStructFromPosix()
val structPointerFromPosix = getStructPointerFromPosix()
object MyStruct {
val struct = getMyStructPointer()?.pointed ?: error("Missing my struct")
val posixProperty: stat = struct.posixProperty
val longProperty: Long = struct.longProperty
val doubleProperty: Double = struct.doubleProperty
val int32tProperty: Int = struct.int32tProperty
val int64TProperty: Long = struct.int64tProperty
val linuxOnlyProperty: Boolean = struct.linuxOnlyProperty
}
val simple = simpleInterop()
}
@@ -0,0 +1,25 @@
@file:Suppress("unused")
import kotlinx.cinterop.pointed
import platform.posix.stat
import simple.simpleInterop
import withPosix.getMyStructPointer
import withPosix.getStructFromPosix
import withPosix.getStructPointerFromPosix
object LinuxX64Main {
val structFromPosix = getStructFromPosix()
val structPointerFromPosix = getStructPointerFromPosix()
object MyStruct {
val struct = getMyStructPointer()?.pointed ?: error("Missing my struct")
val posixProperty: stat = struct.posixProperty
val longProperty: Long = struct.longProperty
val doubleProperty: Double = struct.doubleProperty
val int32tProperty: Int = struct.int32tProperty
val int64TProperty: Long = struct.int64tProperty
val linuxOnlyProperty: Boolean = struct.linuxOnlyProperty
}
val simple = simpleInterop()
}
@@ -0,0 +1,25 @@
@file:Suppress("unused")
import kotlinx.cinterop.pointed
import platform.posix.stat
import simple.simpleInterop
import withPosix.getMyStructPointer
import withPosix.getStructFromPosix
import withPosix.getStructPointerFromPosix
object MacosMain {
val structFromPosix = getStructFromPosix()
val structPointerFromPosix = getStructPointerFromPosix()
object MyStruct {
val struct = getMyStructPointer()?.pointed ?: error("Missing my struct")
val posixProperty: stat = struct.posixProperty
val longProperty: Long = struct.longProperty
val doubleProperty: Double = struct.doubleProperty
val int32tProperty: Int = struct.int32tProperty
val int64TProperty: Long = struct.int64tProperty
val appleOnlyProperty: Boolean = struct.appleOnlyProperty
}
val simple = simpleInterop()
}
@@ -0,0 +1,22 @@
@file:Suppress("unused")
import kotlinx.cinterop.pointed
import platform.posix.stat
import simple.simpleInterop
import withPosix.getMyStructPointer
import withPosix.getStructFromPosix
import withPosix.getStructPointerFromPosix
object NativeMain {
val structFromPosix = getStructFromPosix()
val structPointerFromPosix = getStructPointerFromPosix()
object MyStruct {
val struct = getMyStructPointer()?.pointed ?: error("Missing my struct")
val posixProperty: stat = struct.posixProperty
val longProperty: Long = struct.longProperty
val doubleProperty: Double = struct.doubleProperty
}
val simple = simpleInterop()
}
@@ -0,0 +1,25 @@
@file:Suppress("unused")
import kotlinx.cinterop.pointed
import platform.posix.stat
import simple.simpleInterop
import withPosix.getMyStructPointer
import withPosix.getStructFromPosix
import withPosix.getStructPointerFromPosix
object WindowsMain {
val structFromPosix = getStructFromPosix()
val structPointerFromPosix = getStructPointerFromPosix()
object MyStruct {
val struct = getMyStructPointer()?.pointed ?: error("Missing my struct")
val posixProperty: stat = struct.posixProperty
val longProperty: Long = struct.longProperty
val doubleProperty: Double = struct.doubleProperty
val int32tProperty: Int = struct.int32tProperty
val int64TProperty: Long = struct.int64tProperty
val windowsOnly: Boolean = struct.windowsOnlyProperty
}
val simple = simpleInterop()
}
@@ -0,0 +1,117 @@
import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet
operator fun KotlinSourceSet.invoke(builder: SourceSetHierarchyBuilder.() -> Unit): KotlinSourceSet {
SourceSetHierarchyBuilder(this).builder()
return this
}
class SourceSetHierarchyBuilder(private val node: KotlinSourceSet) {
operator fun KotlinSourceSet.unaryMinus() = this.dependsOn(node)
}
repositories {
maven {
url = rootProject.buildDir.resolve("repo").toURI()
}
}
plugins {
kotlin("multiplatform")
}
kotlin {
jvm()
linuxX64()
linuxArm64()
macosX64("macos")
ios()
mingwX64("windowsX64")
mingwX86("windowsX86")
val commonMain by sourceSets.getting
val commonTest by sourceSets.getting
val jvmMain by sourceSets.getting
val nativeMain by sourceSets.creating
val nativeTest by sourceSets.creating
val appleAndLinuxMain by sourceSets.creating
val appleAndLinuxTest by sourceSets.creating
val linuxMain by sourceSets.creating
val linuxTest by sourceSets.creating
val linuxX64Main by sourceSets.getting
val linuxX64Test by sourceSets.getting
val linuxArm64Main by sourceSets.getting
val linuxArm64Test by sourceSets.getting
val appleMain by sourceSets.creating
val appleTest by sourceSets.creating
val macosMain by sourceSets.getting
val macosTest by sourceSets.getting
val iosMain by sourceSets.getting
val iosTest by sourceSets.getting
val windowsMain by sourceSets.creating
val windowsTest by sourceSets.creating
val windowsX64Main by sourceSets.getting
val windowsX64Test by sourceSets.getting
val windowsX86Main by sourceSets.getting
val windowsX86Test by sourceSets.getting
commonMain {
-jvmMain
-nativeMain {
-appleAndLinuxMain {
-appleMain {
-iosMain
-macosMain
}
-linuxMain {
-linuxArm64Main
-linuxX64Main
}
}
-windowsMain {
-windowsX64Main
-windowsX86Main
}
}
}
commonTest {
-nativeTest {
-appleAndLinuxTest {
-appleTest {
-iosTest
-macosTest
}
-linuxTest {
-linuxArm64Test
-linuxX64Test
}
}
-windowsTest {
-windowsX64Test
-windowsX86Test
}
}
}
sourceSets.commonMain.get().dependencies {
when (project.properties["dependencyMode"]?.toString()) {
null -> {
logger.warn("dependencyMode = null -> Using 'project'")
api(project(":p1"))
}
"project" -> {
logger.quiet("dependencyMode = 'project'")
api(project(":p1"))
}
"repository" -> {
logger.quiet("dependencyMode = 'repository'")
api("kotlin-multiplatform-projects:p1:1.0.0-SNAPSHOT")
}
}
}
}
@@ -0,0 +1,25 @@
@file:Suppress("unused")
import kotlinx.cinterop.pointed
import platform.posix.stat
import simple.simpleInterop
import withPosix.getMyStructPointer
import withPosix.getStructFromPosix
import withPosix.getStructPointerFromPosix
object P2AppleAndLinuxMain {
val structFromPosix = getStructFromPosix()
val structPointerFromPosix = getStructPointerFromPosix()
object MyStruct {
val struct = getMyStructPointer()?.pointed ?: error("Missing my struct")
val posixProperty: stat = struct.posixProperty
val longProperty: Long = struct.longProperty
val doubleProperty: Double = struct.doubleProperty
val int32tProperty: Int = struct.int32tProperty
val int64TProperty: Long = struct.int64tProperty
}
val simple = simpleInterop()
val p1 = AppleAndLinuxMain.structFromPosix
}
@@ -0,0 +1,24 @@
import kotlinx.cinterop.pointed
import simple.simpleInterop
import withPosix.getMyStructPointer
import kotlin.test.Test
class P2AppleAndLinuxTest {
@Test
fun runTest() {
simpleInterop()
getMyStructPointer()?.pointed?.posixProperty
NativeMain.structFromPosix
NativeMain.structPointerFromPosix
NativeMain.simple
P2NativeMain.structFromPosix
P2NativeMain.structPointerFromPosix
P2NativeMain.simple
AppleAndLinuxMain.MyStruct.posixProperty
P2AppleAndLinuxMain.MyStruct.posixProperty
}
}
@@ -0,0 +1,27 @@
@file:Suppress("unused")
import kotlinx.cinterop.pointed
import platform.posix.stat
import simple.simpleInterop
import withPosix.getMyStructPointer
import withPosix.getStructFromPosix
import withPosix.getStructPointerFromPosix
object P2AppleMain {
val structFromPosix = getStructFromPosix()
val structPointerFromPosix = getStructPointerFromPosix()
object MyStruct {
val struct = getMyStructPointer()?.pointed ?: error("Missing my struct")
val posixProperty: stat = struct.posixProperty
val longProperty: Long = struct.longProperty
val doubleProperty: Double = struct.doubleProperty
val int32tProperty: Int = struct.int32tProperty
val int64TProperty: Long = struct.int64tProperty
val appleOnlyProperty: Boolean = struct.appleOnlyProperty
}
val simple = simpleInterop()
val p1 = AppleMain.structFromPosix
}
@@ -0,0 +1,27 @@
import kotlinx.cinterop.pointed
import simple.simpleInterop
import withPosix.getMyStructPointer
import kotlin.test.Test
class P2AppleTest {
@Test
fun runTest() {
simpleInterop()
getMyStructPointer()?.pointed?.appleOnlyProperty
NativeMain.structFromPosix
NativeMain.structPointerFromPosix
NativeMain.simple
P2NativeMain.structFromPosix
P2NativeMain.structPointerFromPosix
P2NativeMain.simple
AppleAndLinuxMain.MyStruct.posixProperty
P2AppleAndLinuxMain.MyStruct.posixProperty
AppleMain.MyStruct.appleOnlyProperty
P2AppleMain.MyStruct.appleOnlyProperty
}
}
@@ -0,0 +1,27 @@
@file:Suppress("unused")
import kotlinx.cinterop.pointed
import platform.posix.stat
import simple.simpleInterop
import withPosix.getMyStructPointer
import withPosix.getStructFromPosix
import withPosix.getStructPointerFromPosix
object P2IosMain {
val structFromPosix = getStructFromPosix()
val structPointerFromPosix = getStructPointerFromPosix()
object MyStruct {
val struct = getMyStructPointer()?.pointed ?: error("Missing my struct")
val posixProperty: stat = struct.posixProperty
val longProperty: Long = struct.longProperty
val doubleProperty: Double = struct.doubleProperty
val int32tProperty: Int = struct.int32tProperty
val int64TProperty: Long = struct.int64tProperty
val appleOnly: Boolean = struct.appleOnlyProperty
val iosOnly: Boolean = struct.iosOnlyProperty
}
val simple = simpleInterop()
val p1 = IosMain.structFromPosix
}
@@ -0,0 +1,31 @@
import kotlinx.cinterop.pointed
import simple.simpleInterop
import withPosix.getMyStructPointer
import kotlin.test.Test
class P2IosTest {
@Test
fun runTest() {
simpleInterop()
getMyStructPointer()?.pointed?.appleOnlyProperty
getMyStructPointer()?.pointed?.iosOnlyProperty
NativeMain.structFromPosix
NativeMain.structPointerFromPosix
NativeMain.simple
P2NativeMain.structFromPosix
P2NativeMain.structPointerFromPosix
P2NativeMain.simple
AppleAndLinuxMain.MyStruct.posixProperty
P2AppleAndLinuxMain.MyStruct.posixProperty
AppleMain.MyStruct.appleOnlyProperty
P2AppleMain.MyStruct.appleOnlyProperty
IosMain.MyStruct.iosOnly
P2IosMain.MyStruct.iosOnly
}
}
@@ -0,0 +1,26 @@
@file:Suppress("unused")
import kotlinx.cinterop.pointed
import platform.posix.stat
import simple.simpleInterop
import withPosix.getMyStructPointer
import withPosix.getStructFromPosix
import withPosix.getStructPointerFromPosix
object P2LinuxArm64Main {
val structFromPosix = getStructFromPosix()
val structPointerFromPosix = getStructPointerFromPosix()
object MyStruct {
val struct = getMyStructPointer()?.pointed ?: error("Missing my struct")
val posixProperty: stat = struct.posixProperty
val longProperty: Long = struct.longProperty
val doubleProperty: Double = struct.doubleProperty
val int32tProperty: Int = struct.int32tProperty
val int64TProperty: Long = struct.int64tProperty
val linuxOnlyProperty: Boolean = struct.linuxOnlyProperty
}
val simple = simpleInterop()
val p1 = LinuxArm64Main.structFromPosix
}
@@ -0,0 +1,28 @@
import kotlinx.cinterop.pointed
import simple.simpleInterop
import withPosix.getMyStructPointer
import kotlin.test.Test
class P2LinuxArm64Test {
@Test
fun runTest() {
simpleInterop()
getMyStructPointer()?.pointed?.posixProperty
getMyStructPointer()?.pointed?.linuxOnlyProperty
NativeMain.structFromPosix
NativeMain.structPointerFromPosix
NativeMain.simple
P2NativeMain.structFromPosix
P2NativeMain.structPointerFromPosix
P2NativeMain.simple
AppleAndLinuxMain.MyStruct.posixProperty
P2AppleAndLinuxMain.MyStruct.posixProperty
LinuxMain.MyStruct.linuxOnlyProperty
P2LinuxMain.MyStruct.linuxOnlyProperty
}
}
@@ -0,0 +1,26 @@
@file:Suppress("unused")
import kotlinx.cinterop.pointed
import platform.posix.stat
import simple.simpleInterop
import withPosix.getMyStructPointer
import withPosix.getStructFromPosix
import withPosix.getStructPointerFromPosix
object P2LinuxMain {
val structFromPosix = getStructFromPosix()
val structPointerFromPosix = getStructPointerFromPosix()
object MyStruct {
val struct = getMyStructPointer()?.pointed ?: error("Missing my struct")
val posixProperty: stat = struct.posixProperty
val longProperty: Long = struct.longProperty
val doubleProperty: Double = struct.doubleProperty
val int32tProperty: Int = struct.int32tProperty
val int64TProperty: Long = struct.int64tProperty
val linuxOnlyProperty: Boolean = struct.linuxOnlyProperty
}
val simple = simpleInterop()
val p1 = LinuxMain.structFromPosix
}
@@ -0,0 +1,28 @@
import kotlinx.cinterop.pointed
import simple.simpleInterop
import withPosix.getMyStructPointer
import kotlin.test.Test
class P2LinuxTest {
@Test
fun runTest() {
simpleInterop()
getMyStructPointer()?.pointed?.posixProperty
getMyStructPointer()?.pointed?.linuxOnlyProperty
NativeMain.structFromPosix
NativeMain.structPointerFromPosix
NativeMain.simple
P2NativeMain.structFromPosix
P2NativeMain.structPointerFromPosix
P2NativeMain.simple
AppleAndLinuxMain.MyStruct.posixProperty
P2AppleAndLinuxMain.MyStruct.posixProperty
LinuxMain.MyStruct.linuxOnlyProperty
P2LinuxMain.MyStruct.linuxOnlyProperty
}
}
@@ -0,0 +1,27 @@
@file:Suppress("unused")
import kotlinx.cinterop.pointed
import platform.posix.stat
import simple.simpleInterop
import withPosix.getMyStructPointer
import withPosix.getStructFromPosix
import withPosix.getStructPointerFromPosix
object P2LinuxX64Main {
val structFromPosix = getStructFromPosix()
val structPointerFromPosix = getStructPointerFromPosix()
object MyStruct {
val struct = getMyStructPointer()?.pointed ?: error("Missing my struct")
val posixProperty: stat = struct.posixProperty
val longProperty: Long = struct.longProperty
val doubleProperty: Double = struct.doubleProperty
val int32tProperty: Int = struct.int32tProperty
val int64TProperty: Long = struct.int64tProperty
val linuxOnlyProperty: Boolean = struct.linuxOnlyProperty
}
val simple = simpleInterop()
val p1 = LinuxX64Main.structFromPosix
}
@@ -0,0 +1,28 @@
import kotlinx.cinterop.pointed
import simple.simpleInterop
import withPosix.getMyStructPointer
import kotlin.test.Test
class P2LinuxX64Test {
@Test
fun runTest() {
simpleInterop()
getMyStructPointer()?.pointed?.posixProperty
getMyStructPointer()?.pointed?.linuxOnlyProperty
NativeMain.structFromPosix
NativeMain.structPointerFromPosix
NativeMain.simple
P2NativeMain.structFromPosix
P2NativeMain.structPointerFromPosix
P2NativeMain.simple
AppleAndLinuxMain.MyStruct.posixProperty
P2AppleAndLinuxMain.MyStruct.posixProperty
LinuxMain.MyStruct.linuxOnlyProperty
P2LinuxMain.MyStruct.linuxOnlyProperty
}
}
@@ -0,0 +1,27 @@
@file:Suppress("unused")
import kotlinx.cinterop.pointed
import platform.posix.stat
import simple.simpleInterop
import withPosix.getMyStructPointer
import withPosix.getStructFromPosix
import withPosix.getStructPointerFromPosix
object P2MacosMain {
val structFromPosix = getStructFromPosix()
val structPointerFromPosix = getStructPointerFromPosix()
object MyStruct {
val struct = getMyStructPointer()?.pointed ?: error("Missing my struct")
val posixProperty: stat = struct.posixProperty
val longProperty: Long = struct.longProperty
val doubleProperty: Double = struct.doubleProperty
val int32tProperty: Int = struct.int32tProperty
val int64TProperty: Long = struct.int64tProperty
val appleOnlyProperty: Boolean = struct.appleOnlyProperty
}
val simple = simpleInterop()
val p1 = MacosMain.structFromPosix
}
@@ -0,0 +1,31 @@
import kotlinx.cinterop.pointed
import simple.simpleInterop
import withPosix.getMyStructPointer
import kotlin.test.Test
class P2MacosTest {
@Test
fun runTest() {
simpleInterop()
getMyStructPointer()?.pointed?.posixProperty
getMyStructPointer()?.pointed?.appleOnlyProperty
NativeMain.structFromPosix
NativeMain.structPointerFromPosix
NativeMain.simple
P2NativeMain.structFromPosix
P2NativeMain.structPointerFromPosix
P2NativeMain.simple
AppleAndLinuxMain.MyStruct.posixProperty
P2AppleAndLinuxMain.MyStruct.posixProperty
AppleMain.MyStruct.appleOnlyProperty
P2AppleMain.MyStruct.appleOnlyProperty
MacosMain.MyStruct.appleOnlyProperty
MacosMain.MyStruct.appleOnlyProperty
}
}
@@ -0,0 +1,23 @@
@file:Suppress("unused")
import kotlinx.cinterop.pointed
import platform.posix.stat
import simple.simpleInterop
import withPosix.getMyStructPointer
import withPosix.getStructFromPosix
import withPosix.getStructPointerFromPosix
object P2NativeMain {
val structFromPosix = getStructFromPosix()
val structPointerFromPosix = getStructPointerFromPosix()
object MyStruct {
val struct = getMyStructPointer()?.pointed ?: error("Missing my struct")
val posixProperty: stat = struct.posixProperty
val longProperty: Long = struct.longProperty
val doubleProperty: Double = struct.doubleProperty
}
val simple = simpleInterop()
val p1 = NativeMain.structFromPosix
}
@@ -0,0 +1,21 @@
import kotlinx.cinterop.pointed
import simple.simpleInterop
import withPosix.getMyStructPointer
import kotlin.test.Test
class P2NativeTest {
@Test
fun runTest() {
simpleInterop()
getMyStructPointer()?.pointed?.posixProperty
NativeMain.structFromPosix
NativeMain.structPointerFromPosix
NativeMain.simple
P2NativeMain.structFromPosix
P2NativeMain.structPointerFromPosix
P2NativeMain.simple
}
}
@@ -0,0 +1,26 @@
@file:Suppress("unused")
import kotlinx.cinterop.pointed
import platform.posix.stat
import simple.simpleInterop
import withPosix.getMyStructPointer
import withPosix.getStructFromPosix
import withPosix.getStructPointerFromPosix
object P2WindowsMain {
val structFromPosix = getStructFromPosix()
val structPointerFromPosix = getStructPointerFromPosix()
object MyStruct {
val struct = getMyStructPointer()?.pointed ?: error("Missing my struct")
val posixProperty: stat = struct.posixProperty
val longProperty: Long = struct.longProperty
val doubleProperty: Double = struct.doubleProperty
val int32tProperty: Int = struct.int32tProperty
val int64TProperty: Long = struct.int64tProperty
val windowsOnly: Boolean = struct.windowsOnlyProperty
}
val simple = simpleInterop()
val p1 = WindowsMain.structFromPosix
}
@@ -0,0 +1,25 @@
import kotlinx.cinterop.pointed
import simple.simpleInterop
import withPosix.getMyStructPointer
import kotlin.test.Test
class P2WindowsTest {
@Test
fun runTest() {
simpleInterop()
getMyStructPointer()?.pointed?.posixProperty
getMyStructPointer()?.pointed?.windowsOnlyProperty
NativeMain.structFromPosix
NativeMain.structPointerFromPosix
NativeMain.simple
P2NativeMain.structFromPosix
P2NativeMain.structPointerFromPosix
P2NativeMain.simple
WindowsMain.MyStruct.windowsOnly
P2WindowsMain.MyStruct.windowsOnly
}
}
@@ -0,0 +1,103 @@
import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet
operator fun KotlinSourceSet.invoke(builder: SourceSetHierarchyBuilder.() -> Unit): KotlinSourceSet {
SourceSetHierarchyBuilder(this).builder()
return this
}
class SourceSetHierarchyBuilder(private val node: KotlinSourceSet) {
operator fun KotlinSourceSet.unaryMinus() = this.dependsOn(node)
}
repositories {
maven {
url = rootProject.buildDir.resolve("repo").toURI()
}
}
plugins {
kotlin("multiplatform")
}
kotlin {
jvm()
linuxX64()
ios()
mingwX64("windowsX64")
mingwX86("windowsX86")
val commonMain by sourceSets.getting
val commonTest by sourceSets.getting
val jvmMain by sourceSets.getting
val nativeMain by sourceSets.creating
val nativeTest by sourceSets.creating
val appleAndLinuxMain by sourceSets.creating
val appleAndLinuxTest by sourceSets.creating
val windowsAndLinuxMain by sourceSets.creating
val windowsAndLinuxTest by sourceSets.creating
val linuxX64Main by sourceSets.getting
val linuxX64Test by sourceSets.getting
val iosMain by sourceSets.getting
val iosTest by sourceSets.getting
val windowsMain by sourceSets.creating
val windowsTest by sourceSets.creating
val windowsX64Main by sourceSets.getting
val windowsX64Test by sourceSets.getting
val windowsX86Main by sourceSets.getting
val windowsX86Test by sourceSets.getting
commonMain {
-jvmMain
-nativeMain {
/*
Different from p1&p2:
- Does not include macos
- Does not include linuxArm64
*/
-appleAndLinuxMain {
-iosMain
-linuxX64Main
}
/*
Different from p1&p2:
- A source set with those targets only exists here
Expected to see p1:nativeMain cinterops
*/
-windowsAndLinuxMain {
-windowsMain
-linuxX64Main
}
-windowsMain {
-windowsX64Main
-windowsX86Main
}
}
}
commonTest {
-nativeTest {
-appleAndLinuxTest {
-iosTest
-linuxX64Test
}
-windowsAndLinuxTest {
-windowsTest
-linuxX64Test
}
-windowsTest {
-windowsX64Test
-windowsX86Test
}
}
}
sourceSets.commonMain.get().dependencies {
implementation(project(":p2"))
}
}
@@ -0,0 +1,25 @@
@file:Suppress("unused")
import kotlinx.cinterop.pointed
import platform.posix.stat
import simple.simpleInterop
import withPosix.getMyStructPointer
import withPosix.getStructFromPosix
import withPosix.getStructPointerFromPosix
object P3AppleAndLinuxMain {
val structFromPosix = getStructFromPosix()
val structPointerFromPosix = getStructPointerFromPosix()
object MyStruct {
val struct = getMyStructPointer()?.pointed ?: error("Missing my struct")
val posixProperty: stat = struct.posixProperty
val longProperty: Long = struct.longProperty
val doubleProperty: Double = struct.doubleProperty
val int32tProperty: Int = struct.int32tProperty
val int64TProperty: Long = struct.int64tProperty
}
val simple = simpleInterop()
val p1 = AppleAndLinuxMain.structFromPosix
}
@@ -0,0 +1,24 @@
import kotlinx.cinterop.pointed
import simple.simpleInterop
import withPosix.getMyStructPointer
import kotlin.test.Test
class P3AppleAndLinuxTest {
@Test
fun runTest() {
simpleInterop()
getMyStructPointer()?.pointed?.posixProperty
NativeMain.structFromPosix
NativeMain.structPointerFromPosix
NativeMain.simple
P2NativeMain.structFromPosix
P2NativeMain.structPointerFromPosix
P2NativeMain.simple
AppleAndLinuxMain.MyStruct.posixProperty
P3AppleAndLinuxMain.MyStruct.posixProperty
}
}
@@ -0,0 +1,27 @@
@file:Suppress("unused")
import kotlinx.cinterop.pointed
import platform.posix.stat
import simple.simpleInterop
import withPosix.getMyStructPointer
import withPosix.getStructFromPosix
import withPosix.getStructPointerFromPosix
object P3IosMain {
val structFromPosix = getStructFromPosix()
val structPointerFromPosix = getStructPointerFromPosix()
object MyStruct {
val struct = getMyStructPointer()?.pointed ?: error("Missing my struct")
val posixProperty: stat = struct.posixProperty
val longProperty: Long = struct.longProperty
val doubleProperty: Double = struct.doubleProperty
val int32tProperty: Int = struct.int32tProperty
val int64TProperty: Long = struct.int64tProperty
val appleOnly: Boolean = struct.appleOnlyProperty
val iosOnly: Boolean = struct.iosOnlyProperty
}
val simple = simpleInterop()
val p1 = IosMain.structFromPosix
}
@@ -0,0 +1,31 @@
import kotlinx.cinterop.pointed
import simple.simpleInterop
import withPosix.getMyStructPointer
import kotlin.test.Test
class P3IosTest {
@Test
fun runTest() {
simpleInterop()
getMyStructPointer()?.pointed?.appleOnlyProperty
getMyStructPointer()?.pointed?.iosOnlyProperty
NativeMain.structFromPosix
NativeMain.structPointerFromPosix
NativeMain.simple
P2NativeMain.structFromPosix
P2NativeMain.structPointerFromPosix
P2NativeMain.simple
AppleAndLinuxMain.MyStruct.posixProperty
P2AppleAndLinuxMain.MyStruct.posixProperty
AppleMain.MyStruct.appleOnlyProperty
P2AppleMain.MyStruct.appleOnlyProperty
IosMain.MyStruct.iosOnly
P3IosMain.MyStruct.iosOnly
}
}
@@ -0,0 +1,27 @@
@file:Suppress("unused")
import kotlinx.cinterop.pointed
import platform.posix.stat
import simple.simpleInterop
import withPosix.getMyStructPointer
import withPosix.getStructFromPosix
import withPosix.getStructPointerFromPosix
object P2LinuxX64Main {
val structFromPosix = getStructFromPosix()
val structPointerFromPosix = getStructPointerFromPosix()
object MyStruct {
val struct = getMyStructPointer()?.pointed ?: error("Missing my struct")
val posixProperty: stat = struct.posixProperty
val longProperty: Long = struct.longProperty
val doubleProperty: Double = struct.doubleProperty
val int32tProperty: Int = struct.int32tProperty
val int64TProperty: Long = struct.int64tProperty
val linuxOnlyProperty: Boolean = struct.linuxOnlyProperty
}
val simple = simpleInterop()
val p1 = LinuxX64Main.structFromPosix
}
@@ -0,0 +1,28 @@
import kotlinx.cinterop.pointed
import simple.simpleInterop
import withPosix.getMyStructPointer
import kotlin.test.Test
class P2LinuxX64Test {
@Test
fun runTest() {
simpleInterop()
getMyStructPointer()?.pointed?.posixProperty
getMyStructPointer()?.pointed?.linuxOnlyProperty
NativeMain.structFromPosix
NativeMain.structPointerFromPosix
NativeMain.simple
P2NativeMain.structFromPosix
P2NativeMain.structPointerFromPosix
P2NativeMain.simple
AppleAndLinuxMain.MyStruct.posixProperty
P3WindowsAndLinuxMain.MyStruct.posixProperty
LinuxMain.MyStruct.linuxOnlyProperty
P2LinuxMain.MyStruct.linuxOnlyProperty
}
}
@@ -0,0 +1,23 @@
@file:Suppress("unused")
import kotlinx.cinterop.pointed
import platform.posix.stat
import simple.simpleInterop
import withPosix.getMyStructPointer
import withPosix.getStructFromPosix
import withPosix.getStructPointerFromPosix
object P2NativeMain {
val structFromPosix = getStructFromPosix()
val structPointerFromPosix = getStructPointerFromPosix()
object MyStruct {
val struct = getMyStructPointer()?.pointed ?: error("Missing my struct")
val posixProperty: stat = struct.posixProperty
val longProperty: Long = struct.longProperty
val doubleProperty: Double = struct.doubleProperty
}
val simple = simpleInterop()
val p1 = NativeMain.structFromPosix
}
@@ -0,0 +1,21 @@
import kotlinx.cinterop.pointed
import simple.simpleInterop
import withPosix.getMyStructPointer
import kotlin.test.Test
class P2NativeTest {
@Test
fun runTest() {
simpleInterop()
getMyStructPointer()?.pointed?.posixProperty
NativeMain.structFromPosix
NativeMain.structPointerFromPosix
NativeMain.simple
P2NativeMain.structFromPosix
P2NativeMain.structPointerFromPosix
P2NativeMain.simple
}
}
@@ -0,0 +1,25 @@
@file:Suppress("unused")
import kotlinx.cinterop.pointed
import platform.posix.stat
import simple.simpleInterop
import withPosix.getMyStructPointer
import withPosix.getStructFromPosix
import withPosix.getStructPointerFromPosix
object P3WindowsAndLinuxMain {
val structFromPosix = getStructFromPosix()
val structPointerFromPosix = getStructPointerFromPosix()
object MyStruct {
val struct = getMyStructPointer()?.pointed ?: error("Missing my struct")
val posixProperty: stat = struct.posixProperty
val longProperty: Long = struct.longProperty
val doubleProperty: Double = struct.doubleProperty
val int32tProperty: Int = struct.int32tProperty
val int64TProperty: Long = struct.int64tProperty
}
val simple = simpleInterop()
val p1 = NativeMain.structFromPosix
}
@@ -0,0 +1,23 @@
import kotlinx.cinterop.pointed
import simple.simpleInterop
import withPosix.getMyStructPointer
import kotlin.test.Test
class P3WindowsAndLinuxTest {
@Test
fun runTest() {
simpleInterop()
getMyStructPointer()?.pointed?.posixProperty
NativeMain.structFromPosix
NativeMain.structPointerFromPosix
NativeMain.simple
P2NativeMain.structFromPosix
P2NativeMain.structPointerFromPosix
P2NativeMain.simple
NativeMain.MyStruct.posixProperty
}
}
@@ -0,0 +1,26 @@
@file:Suppress("unused")
import kotlinx.cinterop.pointed
import platform.posix.stat
import simple.simpleInterop
import withPosix.getMyStructPointer
import withPosix.getStructFromPosix
import withPosix.getStructPointerFromPosix
object P2WindowsMain {
val structFromPosix = getStructFromPosix()
val structPointerFromPosix = getStructPointerFromPosix()
object MyStruct {
val struct = getMyStructPointer()?.pointed ?: error("Missing my struct")
val posixProperty: stat = struct.posixProperty
val longProperty: Long = struct.longProperty
val doubleProperty: Double = struct.doubleProperty
val int32tProperty: Int = struct.int32tProperty
val int64TProperty: Long = struct.int64tProperty
val windowsOnly: Boolean = struct.windowsOnlyProperty
}
val simple = simpleInterop()
val p1 = WindowsMain.structFromPosix
}
@@ -0,0 +1,25 @@
import kotlinx.cinterop.pointed
import simple.simpleInterop
import withPosix.getMyStructPointer
import kotlin.test.Test
class P2WindowsTest {
@Test
fun runTest() {
simpleInterop()
getMyStructPointer()?.pointed?.posixProperty
getMyStructPointer()?.pointed?.windowsOnlyProperty
NativeMain.structFromPosix
NativeMain.structPointerFromPosix
NativeMain.simple
P2NativeMain.structFromPosix
P2NativeMain.structPointerFromPosix
P2NativeMain.simple
WindowsMain.MyStruct.windowsOnly
P2WindowsMain.MyStruct.windowsOnly
}
}
@@ -0,0 +1,16 @@
pluginManagement {
val kotlin_version: String? by settings
repositories {
mavenLocal()
gradlePluginPortal()
}
plugins {
kotlin("multiplatform") version (kotlin_version ?: "1.6.255-SNAPSHOT")
}
}
rootProject.name = "kotlin-multiplatform-projects"
include(":p1")
include(":p2")
include(":p3")