Search code examples
gradlekotlingradle-kotlin-dsl

How to create a "base" gradle file in Kotlin DSL for multi-module project?


To reuse code in gradle files I usually have a "base" gradle file for certain modules and just apply them and add whatever new dependencies it might need. I'm in the progress of converting all my gradle files to the new Kotlin DSL but I get "Unresolved reference" errors for keywords using the following "base" file.

plugins {
    id("com.android.library")
    kotlin("kotlin.android")
    kotlin("kapt")
}

android {
    compileSdkVersion(App.compileSdk)
    defaultConfig {
        minSdkVersion(App.minSdk)
        targetSdkVersion(App.targetSdk)
        versionCode = App.versionCode
        versionName = App.versionName
        testInstrumentationRunner = "android.support.test.runner.AndroidJUnitRunner"
    }

    buildTypes {
        getByName("release") {
            isMinifyEnabled = false
            proguardFiles(getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro")
        }
    }

    compileOptions {
        sourceCompatibility = JavaVersion.VERSION_1_8
        targetCompatibility = JavaVersion.VERSION_1_8
    }
}

dependencies {
    val implementation by configurations
    val testImplementation by configurations
    val androidTestImplementation by configurations

    implementation(fileTree(mapOf("dir" to "libs", "include" to listOf("*.jar"))))
    implementation(Libs.kotlin_stdlib_jdk8)
    implementation(Libs.appcompat_v7)
    testImplementation(Libs.junit)
    androidTestImplementation(Libs.com_android_support_test_runner)
    androidTestImplementation(Libs.espresso_core)
}

The above file is in my root project and I just use the following in the feature modules

apply(rootProject.file("base-android.gradle.kts"))

This worked fine in Groovy but breaks completely when moving to Kotlin, any ideas on what I'm doing wrong or how to properly have a "base" gradle file in the Kotlin DSL?

EDIT: Adding full error message

Script compilation errors:

  Line 10: android {
           ^ Unresolved reference: android

  Line 11:     compileSdkVersion(28)
               ^ Unresolved reference: compileSdkVersion

  Line 12:     defaultConfig {
               ^ Unresolved reference: defaultConfig

  Line 13:         minSdkVersion(21)
                   ^ Unresolved reference: minSdkVersion

  Line 14:         targetSdkVersion(28)
                   ^ Unresolved reference: targetSdkVersion

  Line 15:         versionCode = 1
                   ^ Unresolved reference: versionCode

  Line 16:         versionName = "1.0"
                   ^ Unresolved reference: versionName

  Line 17:         testInstrumentationRunner = "android.support.test.runner.AndroidJUnitRunner"
                   ^ Unresolved reference: testInstrumentationRunner

  Line 20:     buildTypes {
               ^ Unresolved reference: buildTypes

  Line 21:         getByName("release") {
                   ^ Unresolved reference. None of the following candidates is applicable because of receiver type mismatch: 
                       public inline fun <reified T : Any> NamedDomainObjectCollection<out Any>.getByName(name: String): TypeVariable(T) defined in org.gradle.kotlin.dsl
                       public inline fun <reified T : Any> NamedDomainObjectCollection<out Any>.getByName(name: String, configure: TypeVariable(T).() -> Unit): TypeVariable(T) defined in org.gradle.kotlin.dsl
                       public fun <T : Any> NamedDomainObjectCollection<out Any>.getByName(name: String, type: KClass<TypeVariable(T)>): TypeVariable(T) defined in org.gradle.kotlin.dsl
                       public fun <T : Any> NamedDomainObjectCollection<out Any>.getByName(name: String, type: KClass<TypeVariable(T)>, configure: TypeVariable(T).() -> Unit): TypeVariable(T) defined in org.gradle.kotlin.dsl
                       public inline fun <reified T : Any> ExtensionContainer.getByName(name: String): TypeVariable(T) defined in org.gradle.kotlin.dsl

  Line 22:             isMinifyEnabled = false
                       ^ Unresolved reference: isMinifyEnabled

  Line 23:             proguardFiles(getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro")
                       ^ Unresolved reference: proguardFiles

  Line 23:             proguardFiles(getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro")
                                     ^ Unresolved reference: getDefaultProguardFile

  Line 27:     compileOptions {
               ^ Unresolved reference: compileOptions

  Line 28:         sourceCompatibility = JavaVersion.VERSION_1_8
                   ^ Unresolved reference: sourceCompatibility

  Line 29:         targetCompatibility = JavaVersion.VERSION_1_8
                   ^ Unresolved reference: targetCompatibility

16 errors

Solution

  • We share a lot of build logic among several projects in a large build. The shared build logic contains configuration for Java projects, test setup (e.g. extensions for "ci tests") and repository configuration.

    We started with applying a base config file like in your example but moved to precompiled script plugins. With precompiled script plugins you move your shared build logic to small gradle plugins inside the buildScr folder. In every project you can just apply your plugins. In our project this circumvents the issues when applying other files in build.gradle.kts files.

    The documentation offers examples and further more gradle init generates "convention plugins" for shared build logic.