Can the new `KotlinTargetHierarchyDsl` be used to ...
# gradle
n
Can the new
KotlinTargetHierarchyDsl
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.kts
o
theoretically yes You can take a look on
sourceSetTrees
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:
Copy code
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-Beta
may be there is easier way for you concrete use case, it depends on what you are trying to archive in the end by splitting debug and release code
n
Hey, thanks a lot for your help. Do you know what’s the difference between associating compilations (
debug.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.
o
overall, this are 2 different concepts. •
dependsOn
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.dependsOndesktopMainhttps://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 🙂
n
My goal is to produce binaries with slightly different code, depending on the
NativeBuildType
. 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!
This is with 1.9.10, going to try with 1.9.20-Beta before opening a ticket 😄 I am reluctant because I read many reports of K/N performance degradation with 1.9.20-Beta.
o
Yeah, better to create an issue - or it’s a bug, or it should not be allowed to change compilation of binary (not sure, that’s
var
is expected there) or some other mechanism should be provided here
👍 1
d
I'm sorry about resurrecting an old thread here, but I'm trying to achieve the same result and running into trouble, using Kotlin 2.0.20. Mattia, did you ever get this working? I'm trying to make a "debug" source set that gets compiled into the binary only for the NativeBuildType.DEBUG buildType. Here's my relevant configuration:
Copy code
listOf(
    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:
Copy code
> 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`:
Copy code
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:
Copy code
Compilation failed: IrPropertySymbolImpl is already bound.
	at org.jetbrains.kotlin.ir.symbols.impl.IrSymbolBase.bind(IrSymbolImpl.kt:67)
Any help is appreciated.