How to reuse parts of Android configuration in Kotlin Gradle DSL for multiple modules?

Viewed 1055

I have a multi-module Android project & Kotlin Gradle DSL. There is some configuration which has to be repeated in every module and I would like to reuse the code. I would like to reuse for example this code:

android {
    sourceSets {
        getByName("main").java.srcDirs("src/main/kotlin")
        getByName("test").java.srcDirs("src/test/kotlin")
    }
}

There are two methods documented in Kotlin DSL samples:

apply(from = "foo.gradle.kts")

and extension functions in buildSrc like this:

fun Project.kotlinProject() {
   dependencies {
     "compile"(kotlin("stdlib"))
   }
}

However both these methods work only for top-level configuration, I can't access Android plugin's stuff. I'm getting errors like Unresolved reference: BaseExtension

2 Answers

At the end I was inspired by SUPERCILEX's code:

allprojects {
    val parent = (group as String).split(".").getOrNull(1)
    when {
        name == "app" -> {
            apply(plugin = "com.android.application")
            configureAndroidModule()
        }
        parent == "common-android" -> {
            apply(plugin = "com.android.library")
            configureAndroidModule()
        }
    }
}

fun Project.configureAndroidModule() {
    configure<BaseExtension> {
        sourceSets {
            getByName("main").java.srcDirs("src/main/kotlin")
            getByName("test").java.srcDirs("src/test/kotlin")
        }
    }
}​

How about using subprojects block? I have a multi-module Android project and this is how I reuse code in my build scripts.

subprojects {
    apply plugin: 'com.android.library'
    android {
        sourceSets {
            getByName("main").java.srcDirs("src/main/kotlin")
            getByName("test").java.srcDirs("src/test/kotlin")
        }
    }
}

Unresolved reference: BaseExtension

As for the above error message, if you want to use android block, you should declare your modules as android application or library by applying plugins like above build script.

If you want the settings to be repeated in only some of the modules, you can use configure block like this:

configure(subprojects - project(':${module_name}')) {
    dependencies {
        implementation 'com.x.y.z:abc:1.0.0'
    }
}

The above block will define the dependency on all modules except the module with the given name.

Related