13

I'm migrating Gradle build scripts from Groovy to Kotlin DSL and one of the things which is not really documented is how to populate extra properties.

In Groovy, I can write:

ext {
    comp = 'node_exporter'
    compVersion = '0.16.0'
    compProject = 'prometheus'
    arch = 'linux-amd64'
    tarball = "v${compVersion}/${comp}-${compVersion}.${arch}.tar.gz"
    downloadSrc = "https://github.com/${compProject}/${comp}/releases/download/${tarball}"
    unzipDir = "${comp}-${compVersion}.${arch}"
}

I figured out that in the Kotlin DSL, I can achive the same functionality with:

val comp by extra { "filebeat" }
val compVersion by extra { "6.4.0" }
val arch by extra { "linux-x86_64" }
val tarball by extra { "${comp}-${compVersion}-${arch}.tar.gz" }
val downloadSrc by extra { "https://artifacts.elastic.co/downloads/beats/${comp}/${tarball}" }
val unzipDir by extra { "${comp}-${compVersion}-${arch}" }

which looks pretty repetitive.

Implementation of ExtraPropertiesExtension in Kotlin is a little bit complex, but at the end, it holds just plain old Map<String, Object>.

So, my question: is it possible to populate extra object with multiple properties more easily, than just repeating val myProp by extra { "myValue"}?

Vít Kotačka
  • 1,472
  • 1
  • 15
  • 40
  • Maybe this question will be helpful: https://stackoverflow.com/questions/44589153/how-are-gradle-extra-properties-set-in-the-kotlin-dsl – Opal Sep 19 '18 at 09:03
  • 1
    @Opal I read the question you are mentioning, but although it tackles very similar topic, it doesn't ask, nor answer my issue. However, there is alternative solution in _Kotlin DSL_ (`mapOf` -> `forEach` -> `extra.set()`), but IMHO it obfuscates the purpose (it is less readable). – Vít Kotačka Sep 19 '18 at 09:16
  • Maybe something like this? `extra.properties.putAll(pairs = listOf( "comp" to "filebeat", "compVersion" to "6.4.0" ))` – Czar Nov 22 '18 at 09:10
  • or just a series of `extra["key"] = "value"` – Czar Nov 22 '18 at 09:25

2 Answers2

9

According the current (5.2.1) documentation:

All enhanced objects in Gradle’s domain model can hold extra user-defined properties. This includes, but is not limited to, projects, tasks, and source sets.

Extra properties can be added, read and set via the owning object’s extra property. Alternatively, they can be addressed via Kotlin delegated properties using by extra.

Here is an example of using extra properties on the Project and Task objects:

val kotlinVersion by extra { "1.3.21" }
val kotlinDslVersion by extra("1.1.3")
extra["isKotlinDsl"] = true

tasks.register("printExtProps") {
    extra["kotlinPositive"] = true

    doLast {
        // Extra properties defined on the Project object
        println("Kotlin version: $kotlinVersion")
        println("Kotlin DSL version: $kotlinDslVersion")
        println("Is Kotlin DSL: ${project.extra["isKotlinDsl"]}")
        // Extra properties defined on the Task object
        // this means the current Task
        println("Kotlin positive: ${this.extra["kotlinPositive"]}")
    }
}
Community
  • 1
  • 1
Vít Kotačka
  • 1,472
  • 1
  • 15
  • 40
4

You don't have to use delegation, just write extra.set("propertyName", "propertyValue"). You can do this with an apply block if you want:

extra.apply {
    set("propertyName", "propertyValue")
    set("propertyName2", "propertyValue2")
}
Malcolm
  • 41,014
  • 11
  • 68
  • 91