https://kotlinlang.org logo
#gradle
Title
# gradle
p

PHondogo

10/30/2023, 10:22 AM
Hello! After upgrade from Kotlin 1.9.10 to 1.9.20-RC2 warning appears during Gradle build (w: Kotlin Target 'jvm()' is already declared.) I indeed have two jvm targets in one Gradle module but with different names jvm("server") and jvm("client"). Does this warning mean that this case is not allowed now? How should i organize my Gradle module to produce two jars in one module? Now I'm doing like written here: https://kotlinlang.org/docs/multiplatform-set-up-targets.html#distinguish-several-targets-for-one-platform
👀 1
Matching documentation PR is here
I think the general idea is to use different Gradle projects or KGP compilations but I'm not 100% this covers all the use cases yet
Being able to use
expect
/
actual
was convenient and I have yet to find an equivalent
p

PHondogo

10/30/2023, 1:13 PM
Yes expect/actual is one of the cases. Other is to apply plugin on single module and have several outputs.
j

Javier

10/30/2023, 1:14 PM
and I have yet to find an equivalent
Is it even possible? 👀
m

mbonnin

10/30/2023, 1:14 PM
My hunch right now is "no" but that stuff is hard so maybe there is a way?
j

Javier

10/30/2023, 1:15 PM
I am not sure if Gradle variants + interface + default implementation could help here
If Gradle variants work like Android ones, it should be possible. Maybe Gradle, Android and JetBrains could agree about getting an API for that in Gradle, it would help a lot AGP or KMP world
🚫 1
m

mbonnin

10/30/2023, 1:16 PM
Ahah oh no, please no Android Variants 😅
j

Javier

10/30/2023, 1:16 PM
Well, Android variants are expect/actual
m

mbonnin

10/30/2023, 1:17 PM
Yea but without IDE support, right?
The fact that you have to "choose" your android variant in a dialog is a pita
j

Javier

10/30/2023, 1:17 PM
Yea but without IDE support, right?
That is more related to Android Studio plugin
m

mbonnin

10/30/2023, 1:18 PM
All I know is I have missed refactoring variant code multiple times because the IDE only knows of a given variant at a time
j

Javier

10/30/2023, 1:18 PM
Probably to reduce the load on low end computers, as there is no IDE support for unselected variants, but it should be possible to get it working in all variants at the same time
m

mbonnin

10/30/2023, 1:18 PM
My understanding is that
expect
/`actual` is the best way to make it work all variants at the same time
But 🤷
j

Javier

10/30/2023, 1:19 PM
Personally, I still prefer the explicit
expect
one, as it is missing on Android variants, it can be hard to reason about what you are doing on
main
without checking the debug/release (or whatever) source sets
💯 1
☝️ 1
m

mbonnin

10/30/2023, 1:20 PM
Exactly! Also
expect
/`actual` paves the way for
commonMain
artifacts, if we can ever have such a thing
j

Javier

10/30/2023, 1:21 PM
Is there any open issue about this on the Gradle repo?
m

mbonnin

10/30/2023, 1:22 PM
I think it's more a Kotlin/KGP thing, not Gradle?
j

Javier

10/30/2023, 1:23 PM
I haven’t played a lot with Gradle variants, I am not sure if there is any limitation
m

mbonnin

10/30/2023, 1:24 PM
Gradle variants will not help you with IDE support
j

Javier

10/30/2023, 1:26 PM
I think Gradle variants work on the IDE, only the expect part is missing, but that would be a KGP issue
m

mbonnin

10/30/2023, 1:27 PM
What do you mean? Gradle variants expose different artifacts. so you kind of have to "select" one
j

Javier

10/30/2023, 1:28 PM
KGP was exposing different artifacts too, right?
m

mbonnin

10/30/2023, 1:30 PM
Depends what you call artifacts I guess. I have
commonTests
that have
expect fun HttpEngine(): HttpEngine
. I can't really model that with Gradle variants
Or I guess I could produce
engine-ktor.jar
and
engine-okhttp.jar
j

Javier

10/30/2023, 1:31 PM
I am not sure, but I think that common just doesn’t exist. There is an artifact for each variant created in KMP, they are like little modules. Common just contributed to those “variant” artifacts
m

mbonnin

10/30/2023, 1:33 PM
Or I guess I could produce
engine-ktor.jar
and
engine-okhttp.jar
That "could" work. But then I need 2 different KGP compilations: "okhttpTest" and "ktorTest". Both of them having their own
SourceSet
("okHttpTest" and "ktorTest")
j

Javier

10/30/2023, 1:34 PM
I don't know what Gradle variant produces, but I guess it is producing that
and both have their source sets
m

mbonnin

10/30/2023, 1:35 PM
Which leaves me with 2 choices: • Either I duplicate all my tests (not cool) • Or I source (
srcDir()
) a common
jvmCommon
directory into both
okHttpTest
and
ktorTest
(breaks IDE. When I'm in
"jvmCommon"
, how do I know what ``HttpEngine`` I'm using)
j

Javier

10/30/2023, 1:36 PM
Said differently, this allows you to declare the dependencies specific to a feature in their own dependency scope, but everything is still compiled as a single source set. There will also be a single artifact (the component Jar) including support for all features.
Looks like variants are merged into one jar
And probably Gradle variants only work with Java too
m

mbonnin

10/30/2023, 1:37 PM
Is that the thing for supporting multiple Gradle versions?
This is wildly different, requires reflection/ServiceLoader and what not
j

Javier

10/30/2023, 1:37 PM
No, this is Gradle feature variants
👀 1
Copy code
sourceSets {
    create("mongodbSupport") {
        java {
            srcDir("src/mongodb/java")
        }
    }
}

java {
    registerFeature("mongodbSupport") {
        usingSourceSet(sourceSets["mongodbSupport"])
    }
}
m

mbonnin

10/30/2023, 1:38 PM
Right. I still fail to see how this helps the IDE
Unless the .jar could have some "information" about the different variants of a symbol and where they're located
Which duplicates the
expect
/`actual` functionality I guess?
j

Javier

10/30/2023, 1:40 PM
Unless the .jar could have some "information" about the different variants of a symbol and where they're located (edited)
Yeah...
Maybe Gradle, Android and JetBrains could agree
nod 1
I think there are a lot of "duplicated" behaviors which could be provided by an abstract API from Gradle, with custom(and easy) implementation on plugins
variants is only one more
m

mbonnin

10/30/2023, 1:41 PM
Also this all should work with Maven 👀 😛
Ideally this is a Kotlin feature that works with multiple build systems
j

Javier

10/30/2023, 1:41 PM
For example, KGP has its own source sets as the Gradle ones are too Java
nod 1
I hope they can improve all of this after the cleanup of APIs in Gradle 9.0
🤞 1
m

mbonnin

10/30/2023, 1:47 PM
Back to OP's question, @PHondogo if you don't have
expect
/`actual` , you can split your project in several projects (
:common
,
:server
,
:client
). If you're using convention plugins it shouldn't complicate your build a lot more. If you don't then there'll be an initial cost but this will make your build more maintainable if it grows bigger.
You have instruction how to do this here
p

PHondogo

10/30/2023, 2:36 PM
In my case i have a lot of modules with such plugin. With splitting each module to several projects there will be multiplication of them by number of variants. I'm trying to avoid this.
4 Views