Slackbot
02/10/2024, 5:58 AMPhilip W
02/10/2024, 9:52 AMAnze Sodja
02/10/2024, 9:58 AMJavi
02/10/2024, 9:59 AMPhilip W
02/10/2024, 9:59 AMAnze Sodja
02/10/2024, 10:10 AMCan you share more details about “subset of Kotlin”?The idea that it will support just assignments + some specialized methods (e.g.
mavenCentral()
or implementation("group:name:value")
), also no loops and ifs. So it will be really declarative. But right now it's still in the experimental phase, so the format it's still evolvingJavi
02/10/2024, 10:16 AMni loops and ifsPlease support control flow. Easy setups will work with that, rest will be a frankenstein of mixing gradle old style with the new one. Compose UI is a declarative UI and it allows using the fully power of Kotlin. I can already share an example of why it will not be a good idea as I already have my own Amper like convention plugin but with Kotlin
Javi
02/10/2024, 10:18 AMAnze Sodja
02/10/2024, 10:22 AMJavi
02/10/2024, 10:24 AMJavi
02/10/2024, 10:32 AMJavi
02/10/2024, 10:33 AMhubdle {
config {
analysis() // detekt and sonar
coverage() // Kover
documentation {
api() // Dokka
}
publishing { // support the publication to MavenCentral, snapshot, and Gradle portal repositories
maven {
repositories {
mavenLocalTest() // add a custom custom repository for testing purposes
}
}
}
versioning {
semver() // automatic versioning with git tags
}
}
kotlin {
jvm {
features {
jvmVersion(JavaVersion.VERSION_11)
gradle {
plugin {
gradlePlugin {
plugins {
create("hubdle") {
id = "com.javiersc.hubdle"
displayName = "Hubdle"
// rest of the configuration ...
}
}
}
pluginUnderTestDependencies(
hubdle.android.tools.build.gradle,
hubdle.jetbrains.kotlin.gradle.plugin,
)
}
}
}
main {
dependencies {
// ...
}
}
testFixtures()
testFunctional()
testIntegration()
}
}
}
Javi
02/10/2024, 10:34 AMhubdle {
config {
analysis()
coverage()
documentation {
changelog() // handle automatically the changelog for the plugin updates
}
publishing {
maven {
repositories {
mavenLocalTest()
}
}
}
versioning {
semver()
}
}
kotlin {
jvm {
features {
gradle {
versionCatalogs {
catalog {
toml(rootDir.resolve("gradle/hubdle.libs.versions.toml"))
}
}
}
}
}
}
}
Javi
02/10/2024, 10:36 AMhubdle {
config {
analysis()
binaryCompatibilityValidator() // create `.api` files
coverage()
documentation {
api()
changelog() // automatically patch the general changelog for the project
readme {
badges() // automatically update readme badges (Kotlin version, Sonar, etc)
}
site() // mkdocs web page
}
nexus() // requirement to support publishing to MavenCentral/Snapshot repositories
}
}
Javi
02/10/2024, 10:42 AMmain/kotlin
instead of src/main/kotlin
, etcJavi
02/10/2024, 10:50 AMdev
versions I want my Gradle plugin support Kotlin Gradle plugin 2.+
versions
What could I do if I had a subset of Kotlin or Yaml? Crying a lot if the configuration that someone has created for me is not enough, and creating a Frankenstein elsewhere. This perfect configuration will not ever exist. I am creating my own DSL for my purposes, and even so, I have to write the next workaround. What are the chances of someone creating a very limited DSL for a random person on the internet that fits all needs?
With normal Kotlin plus Gradle, I can work around it
hubdle {
config {
// ...
versioning {
semver { //
val hasSameTagPrefix: Boolean = providedTagPrefix == tagPrefix
if (kotlinVersion.isNotBlank() && hasSameTagPrefix) {
mapVersion { gradleVersion ->
gradleVersion.mapIfKotlinVersionIsProvided(kotlinVersion)
}
}
}
}
testing {
test { //
systemProperties["KOTLIN_VERSION"] = kotlinVersion.orEmpty()
}
}
}
}
fun GradleVersion.mapIfKotlinVersionIsProvided(kotlinVersion: String): String {
// checks to avoid wrong provided Kotlin versions, wrong publiccations, and so on
}
Javi
02/10/2024, 10:57 AMhubdle {
config {
...
}
kotlin {
multiplatform {
features {
compose() // add compose
}
common {
main {
dependencies {
implementation(hubdle.jetbrains.compose.ui)
...
}
}
}
android {
main {
implementation(hubdle.androidx.random.lib)
}
}
jvm()
jvmAndAndroid()
...
}
}
}
Javi
02/10/2024, 11:06 AMplugins {
alias(libs.plugins.some.random.plugin)
}
hubdle {
kotlin {
multiplatform {
// fallback configuration
kotlin { // KotlinMultiplatformExtension from KGP
...
}
}
}
}
randomExtension {
...
}
Javi
02/10/2024, 11:25 AMbuildSrc
or build-logic
just to do a simple if/else
and binds it via custom plugin or whatever with a limited Kotlin DSL, Amper, or whatever configuration language.
Currently:
• Someone or a team who knows Gradle creates the convention plugin and maintains it.
• No-build engineers consume it
Future:
• Someone or a team who knows Gradle creates the whole Gradle logic with conventional plugins or custom functions and maintains it.
• Someone or a team who knows Gradle creates the bindings for the Kotlin DSL and/or Amper and maintains it.
• No-build engineers consume it
In my opinion:
• The tools to create declarative convention plugins exist. The Slack open-source plugin does that and my plugin was inspired by the Slack one too.
• It is a bit annoying dealing with ordering issues, but as you are the owner of the convention, you can decide the order of everything and it is safe.
• Except for non-lazy configuration third-party plugins you need to use and the abuse of afterEvaluate
.
Non-lazy configuration breaks creating those convention plugins easily (you need to deal with ordering problems).
afterEvaluate
must die, because it is a 2x1: it is a hack to deal with plugins that are old/wrong (non-lazy). This provokes old plugins can keep doing wrong things, and a new good convention plugin is forced to use it, so they are not "good" anymore.Javi
02/11/2024, 8:11 AMAnze Sodja
02/11/2024, 11:07 AMJavi
02/11/2024, 11:19 AMAnze Sodja
02/12/2024, 8:39 AMOleg Nenashev
02/12/2024, 6:05 PMJavi
02/12/2024, 6:06 PMOleg Nenashev
02/12/2024, 6:09 PMJavi
02/12/2024, 6:10 PMOleg Nenashev
02/12/2024, 6:13 PMOleg Nenashev
02/12/2024, 6:21 PMadam
02/12/2024, 7:35 PMkotlinVersion
are coming from. Is this something you'd expect a developer to pass on the command-line using -D
, for example?Javi
02/12/2024, 7:42 PMkotlinVersion
comes from -P
.
• The complete use case is to override the Kotlin version in the settings file:
versionCatalogs {
create("hubdle") {
if (kotlinVersion != null) {
version("kotlin") { //
strictly(kotlinVersion)
}
}
from(files(rootDir.resolve("gradle/hubdle.libs.versions.toml")))
}
}
• Publish the Gradle and version catalog plugins with the Kotlin version as the suffix, for example: 0.6.3+2.0.0-dev-14242-SNAPSHOT
(same as KSP does, without SNAPSHOT, to know the Kotlin version easily).
versioning {
semver { //
if (kotlinVersion.isNotNullNorBlank() && hasSameTagPrefix) {
mapVersion { gradleVersion ->
gradleVersion.mapIfKotlinVersionIsProvided(kotlinVersion)
}
}
}
}
Javi
02/12/2024, 8:04 PMhubdle {
kotlin {
multiplatform {
apple {
main { ... }
ios {
main { ... }
test { ... }
}
}
jvm {
main { ... }
test { ... }
}
}
}
}
I kept the main/test approach which is not in the image, but I think it is necessary, as you could want to put dependencies only for the test set and not the main set.
I understand you can have something like:
jvm {
dependencies { ... } // main suppressed to avoid nesting for simple projects
test {
dependencies { ... }
}
integrationTest { ... }
functionalTest { ... }
}
But everything is currently possible, just a matter of taste and/or trying to follow a missing standard on how to name or do some things.
I still have to read the doc as I had no time, so I am just guessing.