https://kotlinlang.org logo
#multiplatform
Title
# multiplatform
f

Federico d'Alonzo

11/18/2023, 6:59 PM
Gradle version: 8.5-rc3 Kotlin plugin version: 2.0.0-Beta1 I understand the reasoning behind https://kotlinlang.org/docs/multiplatform-compatibility-guide.html#declaring-several-similar-targets and https://youtrack.jetbrains.com/issue/KT-59316 is because:
Target is a pretty "heavy" concept in terms of build setup.
As such, I have been experimenting a bit with the new multiplatform api, for example:
Copy code
applyDefaultHierarchyTemplate {
    common {
        group("jvmCommon") {
            withJvm()
        }
    }
}
correctly creates the hierarchy shown in image
1
, where I can create an expect in
jvmCommonMain
and an actual in
jvmMain
like in images
2
and
3
But there appears to be no way I know of to compile to the jvm target with multiple "settings", like
kotlinOptions.jvmTarget
version. This would've been done previously by creating multiple jvm targets as stated in the compatibility guide:
Copy code
jvm("jvmKtor") { attributes.attribute(/* ... */) }
jvm("jvmOkHttp") { attributes.attribute(/* ... */) }
But this warning appears:
Copy code
w: Kotlin Target 'jvm()' is already declared.

Declaring multiple Kotlin Targets of the same type is not recommended
and will become an error in the upcoming Kotlin releases.
Creating a compilation
val secondary by compilations.creating
only seems to create an isolated
jvmSecondary
source set which shares nothing with the main tree. If I do create a kotlin source set tree by
withSourceSetTree(KotlinSourceSetTree("secondary"))
inside the hierarchy template, then the rest of the source sets will appear (commonSecondary, jvmCommonSecondary...), but no expect/actual association exists, not even by
associateWith(compilations.getByName("main"))
(which I understand is a way to let the current compilation see internal declarations from the associated compilation) in the
secondary
compilation (plus,
secondary
now appears as a test compilation). I could directly depend on jvmCommonMain inside of the defaultSourceSet for the secondary compilation
dependsOn(sourceSets.getByName("jvmCommonMain"))
, which actually appears to grant the behaviour I'm trying to achieve, but seems to be unwanted behaviour:
Copy code
w: Following Kotlin Source Set groups can't depend on 'jvmCommonMain' together as they belong to different Kotlin Source Set Trees.
Source Sets from 'main' Tree:
  * 'jvmMain'
Source Sets from 'secondary' Tree:
  * 'jvmSecondary'

Please keep dependsOn edges only from one group and remove the others.
This warning appears even if I remove
withSourceSetTree(KotlinSourceSetTree("secondary"))
or if I rename the compilation to
secondaryMain
. This brings me to my question: Is there a way to emulate multiple jvm targets with expect/actual support with the new api? I understand the approach described in the compatibility guide, but this seems to be a bit of a step-back as expect/actual is quite handy and easy to use compared to a manual check-and-switch for implementations.
t

tapchicoma

11/20/2023, 12:26 PM
I think it is kind-of-related issue. Though we need some proper design and it may end up to be similar to the Gradle feature variants inside target.
f

Federico d'Alonzo

11/20/2023, 3:39 PM
It is slightly related, but I think there are some differences: • BuildKonfig is used to bring configuration data into the compiled code by generating an object, which requires a gradle task (I believe it could be replaced by a "phandom" object via a K2 kotlin plugin when the IDE gets updated). This could be used to dynamically "link" to various implementations (at least on the JVM) but it is still mostly a manual process. Also IDE support is limited in a sense. • Gradle build variants seems to be the most apt to the behavior I wanted to describe, but, at least from the documentation, seems to be something limited to the java plugin:
While the engine supports feature variants independently of the ecosystem, this feature is currently only available using the Java plugins.
A generalization of both concepts could be possible: The concept of a source set tree and hierarchy system seems like a very good idea, but it could be expanded/refined by providing per-target flavors or variants. As I understand it now, the system works by providing a common source-set tree structure (defaultHierarchy for example), which is pruned to only contain branches that point to an existing target, and further pruned for each compilation to only contain targets for which a compilation by that name exists. (in my
secondary
compilation example, if I where to add a native target, that wouldn't appear in the secondary tree unless I add a secondary compilation under that target too). As of now, the
defaultSourceSet
for a target-specific compilation is the leaf source set for the whole structure. A natural extension of this system would be providing target-specific-variants, possibly like so:
Copy code
kotlin
jvm {
        // NamedDomainObjectContainer<KotlinJvmCompilation(Build)Variant>
        variants {
            // \/ doesn't depend on name, also possible via "val <name> by getting", always exists
            default {
                // can do most of the things you would imagine, might shift the load from compilations, possibly?
            }
            val debug by creating {
                kotlinOptions {
                    jvmTarget = "1.8"
                }
            }
            val another by creating {
                kotlinOptions {
                    jvmTarget = "17"
                }
            }
        }
    }
default source set locations could be provided like so:

https://i.gyazo.com/274f6b18356a055f85ca5efc82dd89c3.png

They would depend on the "default" variant source set and have expect/actual relations. The major problem that comes to mind with this is that there would be a severe clash between the functionality of build variants and compilations. (things like kotlinOptions mostly, association is perfectly fine in compilations). Another option could be by providing some sort of child/sub-compilation? But I don't see a trivial solution. There could also possibly be publishing and resolution problems. Is there anything of the sort planned for the future?
👍 1
t

tapchicoma

11/20/2023, 3:42 PM
Yeah, design could end up to be something like this 🙂 Anyway we are not planning to lift this warning to error without introducing some alternative to your valid use-case
👍 1
2 Views