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.