Edoardo Luppi
08/09/2023, 6:04 PMplugins {
alias(libs.plugins.multiplatform) apply false
}
subprojects {
apply(plugin = "org.jetbrains.kotlin.multiplatform")
}
Now, in every module I find myself with this code.
kotlin {
explicitApi = ExplicitApiMode.Warning
jvm {
jvmToolchain(11)
withJava()
testRuns["test"].executionTask.configure {
useJUnitPlatform()
}
}
js {
moduleName = project.name
}
}
If I need to change something I have to do it three+ times, which is tedious.
How do I move this configuration at the root? Or at least, do it one time?Adam S
08/09/2023, 6:55 PMsubprojects {}
and allprojects {}
, even though in practice they really screws up project configuration. The better way of sharing configuration is to...
1. create buildSrc/build.gradle.kts
(example) and buildSrc/settings.gradle.kts
(example)
2. add the Kotlin plugin as a regular dependency in buildSrc/build.gradle.kts
- e.g.
dependencies {
implementation("org.jetbrains.kotlin:kotlin-gradle-plugin:1.9.0")
}
3. create some convention plugins - I prefer making one convention plugin per Kotlin target, so that I can apply each target specifically per subproject - but you could combine all of these into one single convention plugin
• Kotlin/Native convention
• Kotlin/JS convention
• Kotlin/JVM convention
4. now apply the convention plugins in the plugins block of each subproject
// my-cool-subproject/build.gradle.kts
plugins {
buildsrc.conventions.lang.`kotlin-multiplatform-jvm`
buildsrc.conventions.lang.`kotlin-multiplatform-js`
buildsrc.conventions.lang.`kotlin-multiplatform-native`
}
(the convention plugin has an ID of the package name + the filename before .gradle.kts
, e.g. id("buildsrc.conventions.lang.kotlin-multiplatform-jvm"
)Edoardo Luppi
08/09/2023, 6:58 PMAdam S
08/09/2023, 7:00 PMEdoardo Luppi
08/09/2023, 7:38 PMjs
target
kotlin {
targets {
js(IR) {
browser()
nodejs()
}
}
}
Will I be able to access that registered target and customize it further, if required?Adam S
08/09/2023, 7:50 PMEdoardo Luppi
08/09/2023, 7:58 PMimplementation("org.jetbrains.kotlin:kotlin-gradle-plugin:1.9.0")
Edoardo Luppi
08/09/2023, 8:04 PM/**
* The version of the Kotlin compiler embedded in gradle-kotlin-dsl (currently _1.8.20_).
*/
val embeddedKotlinVersion = "1.8.20"
Not sure how you control the Kotlin version in the snakeyaml libraryephemient
08/09/2023, 8:11 PMEdoardo Luppi
08/09/2023, 8:15 PMGradle's embedded Kotlin versionDo you mean that there is no way out of the embedded version? Sounds like a pain since for what I've read around
buildSrc
stuff is used a lotEdoardo Luppi
08/09/2023, 8:20 PMAdam S
08/10/2023, 9:36 AMOn a different note, while I was previously targeting Kotlin 1.9.0, it seems it's forcing me on 1.8.20 right now.that's very unusual! I've never seen, or heard of, such an issue before. The classpaths should be separate... What are you seeing? What is being forced to use Kotlin 1.8.20? It's okay if the build scripts are using the embedded Kotlin version
Edoardo Luppi
08/10/2023, 9:46 AMEdoardo Luppi
08/10/2023, 9:48 AMplugins {
id("org.jetbrains.kotlin.multiplatform") version "1.9.0" apply false
id("zproto.module") apply false
}
If I import the project again:
Error resolving plugin [id: 'org.jetbrains.kotlin.multiplatform', version: '1.9.0', apply: false]
> The request for this plugin could not be satisfied because the plugin is already on the classpath with an unknown version, so compatibility cannot be checked.
Adam S
08/10/2023, 9:48 AMbuildSrc/build.gradle.kts
then you mustn't specify the version anywhere else.
// some-other-subproject/build.gradle.kts
plugins {
id("org.jetbrains.kotlin.multiplatform") // no version needed
}
Adam S
08/10/2023, 9:51 AMbuildSrc/build.gradle.kts
dependencies, or in one of the other 5 different ways that I won't go into!) it gets added to the build script classpath. But if you add a plugin with a different version in two different places, then Gradle does not like it, and you get the error.Edoardo Luppi
08/10/2023, 9:53 AMbuildSrc/build.gradle.kts
file:
plugins {
`embedded-kotlin`
`java-gradle-plugin`
}
plugins.apply(SamWithReceiverGradleSubplugin::class.java)
extensions.configure(SamWithReceiverExtension::class.java) {
annotations(HasImplicitReceiver::class.qualifiedName!!)
}
dependencies {
implementation("org.jetbrains.kotlin:kotlin-gradle-plugin:1.9.0")
}
gradlePlugin {
plugins {
register("zproto.module") {
id = "zproto.module"
implementationClass = "zproto.build.plugins.ZProtoModulePlugin"
}
}
}
I can't see any import related to the Kotlin Multiplatform plugin. Is it imported by kotlin-gradle-plugin
?Adam S
08/10/2023, 9:53 AMimplementation("org.jetbrains.kotlin:kotlin-gradle-plugin:1.9.0")
contains all Kotlin Gradle PluginsEdoardo Luppi
08/10/2023, 9:54 AMAdam S
08/10/2023, 9:54 AMAdam S
08/10/2023, 9:54 AMAdam S
08/10/2023, 9:55 AMimplementation("org.jetbrains.kotlin:kotlin-gradle-plugin:1.9.0")
Edoardo Luppi
08/10/2023, 9:56 AMkotlin-gradle-plugin
is indeed correct. Or if I should import multiple other plugins instead of that single one.Edoardo Luppi
08/10/2023, 9:56 AMbuildSrc
, which conceptually doesn't sound correctAdam S
08/10/2023, 9:56 AMAdam S
08/10/2023, 9:59 AMBecause at this point is seems what drives the Kotlin version is buildSrc , which conceptually doesn't sound correctIndeed, it is weird, but it's also nice to have a single place where you can define all plugins, and so you can ensure that the versions of all plugins will be consistent in all subprojects. You can help things a bit by specifying the KGP dependency in a version catalog and using in in
buildSrc/build.gradle.kts
. You just need to add some config to tell Gradle where the version catalog is in buildSrc/settings.gradle.kts
I specify the Gradle plugins in libs.version.toml
in Dokkatoo (the gradlePlugin-
prefix is just a naming convention)Adam S
08/10/2023, 10:02 AMkotlin-dsl
and precompiled script plugins, purely because they tend to be more succinct and easier to maintain. But a custom class + a plugin definition in buildSrc/build.gradle.kts
will work perfectly well too.Edoardo Luppi
08/10/2023, 10:04 AMYou can help things a bit by specifying the KGP dependency in a version catalogOk! I guess if it's a sort of best approach I'll follow it.
I'd recommend going back to usingYeah I have noticed they're easer to read and implement. I need to get the multi-module setup working by tomorrow, so I guess I'll keep the binary one for now, and experiment on the weekend with the script one. One last question: how do I verify I'm really compiling with 1.9.0? Is there a task or a property that I can print out for this? I mean, I guess I could trust the dependency, but I'd like to be 100% sure I'm not importing older versions.and precompiled script pluginskotlin-dsl
Adam S
08/10/2023, 10:11 AMKotlinVersion.CURRENT
- that you can use in a build.gradle.kts.Edoardo Luppi
08/10/2023, 10:13 AMAdam S
08/10/2023, 10:14 AMEdoardo Luppi
08/10/2023, 10:16 AMthat'll be the combined list for both the classpath used to build the Gradle scriptsSo basically Gradle 8.2.1 is using 1.8.20
Adam S
08/10/2023, 10:16 AMAdam S
08/10/2023, 10:17 AMEdoardo Luppi
08/10/2023, 10:20 AMlibs
inside of buildSrc/build.gradle.kts
, but not inside my binary plugin
// Common test dependencies
kotlin.sourceSets.getByName("commonTest") {
dependencies {
implementation(kotlin("test"))
implementation(libs.kotlinx.coroutines.test) // Error
}
}
Is this expected?Adam S
08/10/2023, 10:20 AMAdam S
08/10/2023, 10:22 AMEdoardo Luppi
08/10/2023, 10:25 AMpluginManagement
entry with settings + applied it by id on each module.Adam S
08/10/2023, 10:29 AMEdoardo Luppi
08/10/2023, 10:40 AM[versions]
kotlin = "1.8.20" # should match Gradle's embedded Kotlin version
Is there a specific reason as to why you're explicitly matching the exact version?Adam S
08/10/2023, 10:50 AMembeddedKotlinVersion
util valAdam S
08/10/2023, 10:55 AMEdoardo Luppi
08/10/2023, 11:52 AMplugins.apply(SamWithReceiverGradleSubplugin::class.java)
extensions.configure(SamWithReceiverExtension::class.java) {
annotations(HasImplicitReceiver::class.qualifiedName!!)
}
I understand that if I don't do that, Kotlin code breaks. But then the question is, why that plugin isn't applied by default?mbonnin
08/10/2023, 11:52 AMmbonnin
08/10/2023, 11:53 AMmbonnin
08/10/2023, 11:54 AMit
instead of this
and it'd work the sameEdoardo Luppi
08/10/2023, 11:55 AMAdam S
08/10/2023, 11:56 AMkotlin-dsl
pluginEdoardo Luppi
08/10/2023, 11:56 AMAdam S
08/10/2023, 11:57 AMkotlin-dsl
plugin and also still write binary pluginsmbonnin
08/10/2023, 11:57 AMkotlinGradleDsl()
dependency because we don't need String.invoke()
in our classpath (also there were other side effects of kotlin-sdl
but can't remember the specifics)Edoardo Luppi
08/10/2023, 12:00 PMEdoardo Luppi
08/10/2023, 12:02 PMmbonnin
08/10/2023, 12:03 PMmbonnin
08/10/2023, 12:03 PMmbonnin
08/10/2023, 12:13 PMEdoardo Luppi
08/10/2023, 12:13 PMEdoardo Luppi
08/10/2023, 12:28 PMkotlin-embedded
and `kotlin-dsl`:
Like the ``embedded-kotlin`` plugin, it uses the same Kotlin version as your Gradle build. This is useful if you do not intend to distribute your plugins (i.e. convention plugins). If you need to distribute your plugin, make sure to use a Kotlin version that is compatible with the Gradle version you are targeting.Although I get the why, it's still unclear to me how I can drive the Kotlin version. And btw, I suppose we're talking about the Kotlin runtime version used by the plugin, right?
mbonnin
08/10/2023, 12:30 PMhow I can drive the Kotlin versionStandalone Gradle plugins are regular JVM projects. Just compile them with your Kotlin version of choice and set api/language version to be compatible with Gradle:
plugins {
id("org.jetbrains.kotlin.jvm").version("1.9.0")
id("java-gradle-plugin")
}
tasks.withType(KotlinCompile::class.java).configureEach {
kotlinOptions {
// Put whatever version the min Gradle version you want to support requires
// See <https://docs.gradle.org/current/userguide/compatibility.html>
apiVersion = "1.8"
languageVersion = "1.8"
}
}
(sorry for the edits, pressed enter a bit too fast)Edoardo Luppi
08/10/2023, 12:32 PMmbonnin
08/10/2023, 12:32 PMEdoardo Luppi
08/10/2023, 12:42 PMcompileOnly(gradleKotlinDsl())
is a bad idea then, because you're using stuff from your development Gradle version that may not be present on an older/newer version.mbonnin
08/10/2023, 12:44 PMgradleKotlinDsl()
at all. But if you want to I'm not sure actuallymbonnin
08/10/2023, 12:44 PMgradleKotlinDsl()
at runtime indeed but can't remember for surembonnin
08/10/2023, 12:46 PMGradle version
<=> gradleKotlinDsl() version
mapping somewhere like there is for Kotlin at https://docs.gradle.org/current/userguide/compatibility.html. You might have to looks at the Gradle sourceEdoardo Luppi
08/10/2023, 12:57 PMmbonnin
08/10/2023, 12:59 PMmbonnin
08/10/2023, 1:01 PMmbonnin
08/10/2023, 1:06 PMgradleKotlinDsl()
is builtin in the Gradle distribution, I got confused with the kotlin-dsl plugin, which is not builtin. So yea, definitely would not bet on it 😅 .mbonnin
08/10/2023, 1:08 PMgradleKotlinDsl()
in my classpath