natario1
09/19/2023, 10:23 AMKotlinTargetHierarchyDsl be used to implement this in a clean way?
In addition to main and test, for all native leaf targets and all nodes shared among them, I’d like to have a <name>Debug and <name>Release source sets. Later I can create compilations that use these sets as default source set, and configure the binaries depending on NativeBuildType. Kind of like this: https://github.com/ilmat192/kotlin-native-gradle-samples/blob/master/debug-logger/build.gradle.ktsOleg Yukhnevich
09/19/2023, 12:50 PMsourceSetTrees function: https://github.com/JetBrains/kotlin/blob/30dc01dc0a335103c33af9dfb63a828eac023fa4/[…]in/org/jetbrains/kotlin/gradle/plugin/KotlinHierarchyBuilder.kt
So if you create separate debug compilation for targets f.e. macosX64 and linuxX64 - you will have 2 root sourcesets macosX64Debug and linuxX64Debug . And after applying hierarchy like this:
applyDefaultHierarchyTemplate {
sourceSetTrees(SourceSetTree("debug"))
}
It should create intermediate sourcesets like `commonDebug`/`nativeDebug` and so on.
Also most likely you will need to associate compilations: specifically associate debug compilation with main compilation, so you will be able to access declarations from commonMain in commonDebug
I haven’t tried it, but it should work 🙂
better to try it with 1.9.20-BetaOleg Yukhnevich
09/19/2023, 12:54 PMnatario1
09/19/2023, 1:44 PMdebug.associateWith(main)) and linking the source sets (debug.defaultSourceSet.dependsOn(main.defaultSourceSet) ? The github link I posted uses the latter. associateWith sounds more correct but I’m not sure why.Oleg Yukhnevich
09/19/2023, 2:06 PMdependsOn should be used only inside one tree and creates a hierarchy of sourceSets in this tree (like macosX64Main -> macosMain -> nativeMain -> commonMain)
• associateWith allows to connect separate compilations - think of it like you add an other binary dependency via dependencies { api(…) } block, but with possibility to access internal declarations from it.
You can’t (or at least should’t) add dependsOn from one tree to another. F.e. you should not do commonTest.dependsOn(commonMain) or jvmTest.dependsOn(jvmMain) (or in your case jvmDebug.dependsOn(jvmMain) because main and test are different compilations, and as so, they are compiled separately.
There are even issues for related cases - they are about main and test compilation, but it should be the same for custom compilation
• https://youtrack.jetbrains.com/issue/KT-60395/Discourage-or-warn-fail-on-desktopTest.dependsOndesktopMain
• https://youtrack.jetbrains.com/issue/KT-47144/Multiplatform-Warn-about-setting-Test.dependsOnMain
Also, github link you’ve posted is using kotlin 1.3.30, which is rather outdated. As I already said, better to try do it using kotlin 1.9.20-Beta - it has a lot of under-the-hood and API changes regarding how multiplatform code should be configured + also has nice new diagnostics when you are doing something wrong 🙂natario1
09/19/2023, 2:38 PMNativeBuildType. So the idea was to create the binary and then do binary.compilation = createCompilationBasedOnBuildType() , just like the outdated github sample.
But I think I hit a plugin bug. https://github.com/JetBrains/kotlin/blob/9ff3871a8b8a9739cfa6d927d2c6a54a3edd0a28/[…]etbrains/kotlin/gradle/targets/native/tasks/KotlinNativeLink.kt . KotlinNativeLink should not synchronously use compilation in the constructor, because it’s mutable (binary.compilation is a var).
This means that even if I override the compilation in the binary configuration, the link task which for some reason is created eagerly, will still be misconfigured and depend on the main compilation. Well, thanks for your help anyway!natario1
09/19/2023, 2:40 PMOleg Yukhnevich
09/19/2023, 2:52 PMvar is expected there) or some other mechanism should be provided herenatario1
09/19/2023, 3:43 PMDarron Schall
09/20/2024, 8:21 PMlistOf(
iosX64(),
iosArm64(),
iosSimulatorArm64(),
).forEach {
val debugCompilation = it.compilations.create("debug") {
associateWith(it.compilations["main"])
}
it.binaries {
framework(listOf(DEBUG, RELEASE)) {
if (buildType == DEBUG) {
compilation = debugCompilation
}
baseName = "shared"
export(libs.touchlab.kermit.simple)
// ...additional export() omitted for brevity
}
}
}
// Add a debug source set, so code in "commonDebug"
// ends up in the debug binary
@OptIn(ExperimentalKotlinGradlePluginApi::class)
applyDefaultHierarchyTemplate {
sourceSetTrees(KotlinSourceSetTree.main, KotlinSourceSetTree.test, KotlinSourceSetTree("debug"))
common {
withAndroidTarget()
group("ios") {
withIos()
}
}
}
This seems like it's close to working. Building for release seems to work fine and does not include any code from the commonDebug source set, which is great.
But, trying to build for debug fails:
> Following dependencies exported in the debugFramework binary are not specified as API-dependencies of a corresponding source set:
Showing Recent Messages
Files: [/Users/darron/.gradle/caches/modules-2/files-2.1/co.touchlab/kermit-simple-iossimulatorarm64/2.0.4/ddf62ebbda657bbbf05c183ad51d645e81e9a59d/kermit-simple.klib]
Please add them in the API-dependencies and rerun the build.
When I comment out the export(), this setup seems to work as expected in both the debug and release cases. But, I really need to be able to export dependencies in the framework.
I tried to fix this by adding the following to my `sourceSets`:
val commonDebug by getting {
dependsOn(getByName("commonMain"))
}
val iosDebug by getting {
dependsOn(getByName("commonDebug"))
dependsOn(getByName("iosMain"))
}
... but that throws an exception trying to build for debug:
Compilation failed: IrPropertySymbolImpl is already bound.
at org.jetbrains.kotlin.ir.symbols.impl.IrSymbolBase.bind(IrSymbolImpl.kt:67)
Any help is appreciated.