21

I'm trying to organize my build files as I would in groovy, by having values in a separate file to reuse. But I cannot understand the syntax to do the same thing in the kotlin DSL.

Here's what I'm using in root build.gradle.kts:

applyFrom("config.gradle.kts")

buildscript {
    repositories {
        google()
        jcenter()
    }
    dependencies {
        val test = project.extra["minSdkVer"]
        classpath("com.android.tools.build:gradle:3.0.0-alpha4")
        classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.1.2-5")
        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files
    }
}

allprojects {
    repositories {
        google()
        jcenter()
        mavenCentral()
    }
}

and here's whats in the config.gradle.kts that is being referenced:

mapOf(
        Pair("minSdkVer", 22),
        Pair("targetSdkVer", 25),
        Pair("compiledSdkVer", 25),
        Pair("buildToolsVer", "26-rc4")
).entries.forEach {
    project.extra.set(it.key, it.value)
}

But there's an error:

Cannot get property 'minSdkVer' on extra properties extension as it does not exist

eskatos
  • 4,174
  • 2
  • 40
  • 42
Daykm
  • 475
  • 1
  • 5
  • 13

1 Answers1

22

A correct fix: Gradle collects and applies the buildscript { ... } blocks from your script strictly before executing anything else from it. So, to make your properties from config.gradle.kts available inside the buildscript, you should move applyFrom("config.gradle.kts") to your buildscript { ... } block:

buildscript {
    applyFrom("config.gradle.kts")

    /* ... */
}

Another possible mistake is using an extra property as extra["minSdkVer"] in a scope of another ExtensionAware, like a task in this example:

val myTask = task("printMinSdkVer") {
    doLast {
        println("Extra property value: ${extra["minSdkVer"]}")
    }
}

In this case, extra.get(...) uses not the project.extra but the extra of the task.

To fix that, specify that you work with the project. Direct usage:

println(project.extra["minSdkVer"])

And for delegation.

val minSdkVer by project.extra
hotkey
  • 140,743
  • 39
  • 371
  • 326
  • Cool. Took me a second to figure out what you mean with scoping. Putting the applyFrom() inside the buildscript block works. It doesn't make complete sense since the project.extra's shouldn't be affected by the ExtensionAware scope, right? – Daykm Jun 16 '17 at 13:28
  • @Daykm, now I see that there was a completely different problem in your case: Gradle collects and executes the `buildscript` blocks strictly before anything else in the script, so, ideed, the correct fix was to apply another script in the `buildscript` block and not outside. – hotkey Jun 16 '17 at 13:34