
In Gradle, an automated build system, the buildSrc approach has already become the standard for implementing custom plugins and tasks, as well as creating common configurations such as lists of dependencies and versions. But it has a significant drawback: when changing, the buildSrcassembly cache becomes invalid.
Gradle — , . , buildSrc .
Gradle
Gradle Android Android Studio. : Android- , , , Eclipse Android-. .
Gradle Groovy ( ) Stack Overflow. , build.gradle.
, - . build.gradle . , , , . , build.gradle .
// projectRoot/build.gradle
public void configureAndroid(Project project) {
project.android {
compileSdkVersion 9
}
}
// projectRoot/app/build.gradle
configureAndroid(this)
android {
// Module specific configuration
}
, . build.gradle . data, core, domain presentation, : Gradle .
// projectRoot/android.gradle
project.android {
compileSdkVersion 9
}
// projectRoot/app/build.gradle
apply from: '../android.gradle'
IDE, . build.gradle plugins { }, .
, , , , buildSrc . buildSrc . JVM-, IDE. : ( JUnit ) , Gradle . , , Gradle?!
buildSrc
, . buildSrc . remote , . , . , Gradle , .

: compile (Java-) -> report ( ). compile JavaCompile, Java-. report — , : buildSrc build.gradle.
report , -. buildSrc- compile report , compile . build.gradle report. , - compile , . Gradle , report , , .
, compile ? buildSrc .
, . , , build.gradle. . , , Gradle-. (included) .
buildSrc , buildSrc Gradle . ( , Android Gradle plugin). Gradle .
, . , classpath. , FROM-CACHE. , .
Gradle , . , UP-TO-DATE.
buildSrc
Reaktive . :
- buildSrc, ;
- binary-compatibility.gradle;
- build.gradle.
, . , .
. buildSrc buildSrc2. buildSrc, . classpath . buildSrc, . Gradle , settings.gradle :
// projectRoot/settings.gradle.kts
pluginManagement {
repositories {
google()
jcenter()
gradlePluginPortal()
}
}
includeBuild("buildSrc2")
// include(":module")
buildscript { repositories { } }. includeBuild Gradle buildSrc2 .
buildSrc2? .
// projectRoot/buildSrc2/build.gradle.kts
plugins {
`kotlin-dsl`
`java-gradle-plugin`
}
gradlePlugin {
// ,
plugins.register("class-loader-plugin") {
id = "class-loader-plugin"
implementationClass = "com.example.ClassLoaderPlugin"
}
// , ,
}
java-gradle-plugin properties, . java-gradle-plugin .
buildSrc, , Gradle-.
// ClassLoaderPlugin.kt
class ClassLoaderPlugin: Plugin<Project> {
override fun apply(target: Project) {
// no-op
}
}
// Deps.kt
object Deps {
const val kotlinStdLib = "..."
}
class-loader-plugin Deps. .
// projectRoot/app/build.gradle
plugins {
id 'class-loader-plugin'
}
dependencies {
implementation(Deps.kotlinStdLib)
}
build.gradle setupMultiplatformLibrary.
// projectRoot/build.gradle
void setupMultiplatformLibrary(Project project) {
project.apply plugin: 'org.jetbrains.kotlin.multiplatform'
project.kotlin {
sourceSets {
commonMain {
dependencies {
implementation Deps.kotlin.stdlib.common
}
}
commonTest {
dependencies {
implementation Deps.kotlin.test.common
implementation Deps.kotlin.test.annotationsCommon
}
}
}
}
}
. Kotlin Multiplatform .
Gradle- :
// projectRoot/buildSrc2/build.gradle.kts
dependencies {
// Kotlin Gradle plugin,
implementation("org.jetbrains.kotlin:kotlin-gradle-plugin:1.3.72")
}
gradlePlugin {
//
plugins.register("mpp-configuration") {
id = "mpp-configuration"
implementationClass = "com.badoo.reaktive.configuration.MppConfigurationPlugin"
}
}
// MppConfigurationPlugin.kt
class MppConfigurationPlugin : Plugin<Project> {
override fun apply(target: Project) {
// "kotlin" "android"
target.extensions.create("configuration", MppConfigurationExtension::class.java, target)
// , , Kotlin
setupMultiplatformLibrary(target)
}
private fun setupMultiplatformLibrary(target: Project) {
// project.apply plugin: 'org.jetbrains.kotlin.multiplatform'
target.apply(plugin = "org.jetbrains.kotlin.multiplatform")
// project.kotlin {
target.extensions.configure(KotlinMultiplatformExtension::class.java) {
sourceSets {
maybeCreate("commonMain").dependencies { implementation(Deps.kotlin.stdlib.common) }
maybeCreate("commonTest").dependencies {
implementation(Deps.kotlin.test.common)
implementation(Deps.kotlin.test.annotationsCommon)
}
}
}
}
}
setupAllTargetsWithDefaultSourceSets isLinuxArm32HfpEnabled. linuxArm32Hfp, . linuxArm32Hfp, . project.name, . , .
// MppConfigurationExtension.kt
open class MppConfigurationExtension @Inject constructor(
private val project: Project
) {
var isLinuxArm32HfpEnabled: Boolean = false
private set
// , ARM32
fun enableLinuxArm32Hfp() {
if (isLinuxArm32HfpEnabled) return
project.plugins.findPlugin(MppConfigurationPlugin::class.java)?.setupLinuxArm32HfpTarget(project)
isLinuxArm32HfpEnabled = true
}
}
// MppConfigurationPlugin.kt
class MppConfigurationPlugin : Plugin<Project> {
override fun apply(target: Project) {
target.extensions.create("configuration", MppConfigurationExtension::class.java, target)
...
}
fun setupLinuxArm32HfpTarget(project: Project) {
if (!Target.shouldDefineTarget(project, Target.LINUX)) return
project.kotlin {
linuxArm32Hfp()
sourceSets {
maybeCreate("linuxArm32HfpMain").dependsOn(getByName("linuxCommonMain"))
maybeCreate("linuxArm32HfpTest").dependsOn(getByName("linuxCommonTest"))
}
}
}
}
, (disableLinuxArm32Hfp() ), Kotlin ( ). mpp-configuration configuration.
// projectRoot/reaktive/build.gradle
plugins {
id 'mpp-configuration'
}
//
configuration {
enableLinuxArm32Hfp()
}
.

Binary compatibility validator, . binary-compatibility.gradle build.gradle. , .
// projectRoot/binary-compatibility.gradle
if (Target.shouldDefineTarget(target, Target.ALL_LINUX_HOSTED)) {
apply plugin: kotlinx.validation.BinaryCompatibilityValidatorPlugin
apiValidation {
ignoredProjects += [
'benchmarks',
'jmh',
'sample-mpp-module',
'sample-android-app',
'sample-js-browser-app',
'sample-linuxx64-app',
'sample-ios-app',
'sample-macos-app'
]
}
}
.
// projectRoot/buildSrc2/build.gradle.kts
dependencies {
// Binary Compatibility Plugin
implementation("org.jetbrains.kotlinx:binary-compatibility-validator:0.2.3")
}
gradlePlugin {
//
plugins.register("binary-compatibility-configuration") {
id = "binary-compatibility-configuration"
implementationClass = "com.badoo.reaktive.compatibility.BinaryCompatibilityConfigurationPlugin"
}
}
// BinaryCompatibilityConfigurationPlugin.kt
class BinaryCompatibilityConfigurationPlugin : Plugin<Project> {
override fun apply(target: Project) {
if (Target.shouldDefineTarget(target, Target.ALL_LINUX_HOSTED)) {
target.apply(plugin = "binary-compatibility-validator")
target.extensions.configure(ApiValidationExtension::class) {
ignoredProjects.addAll(
listOf(
"benchmarks",
"jmh",
"sample-mpp-module",
"sample-android-app",
"sample-js-browser-app",
"sample-linuxx64-app",
"sample-ios-app",
"sample-macos-app"
)
)
}
}
}
}
build.gradle.
// projectRoot/build.gradle
plugins {
id 'binary-compatibility-configuration'
}
. , , , . . .
// rootProject/dependencies/build.gradle.kts
plugins {
`kotlin-dsl`
`java-gradle-plugin`
}
//
group = "com.badoo.reaktive.dependencies"
version = "SNAPSHOT"
repositories {
jcenter()
}
gradlePlugin {
// ,
plugins.register("dependencies") {
id = "dependencies"
implementationClass = "com.badoo.reaktive.dependencies.DependenciesPlugin"
}
}
Deps . . settings.gradle includeBuild("dependencies"). dependencies Deps.
// projectRoot/buildSrc2/build.gradle.kts
import com.badoo.reaktive.dependencies.Deps
plugins {
`kotlin-dsl`
`java-gradle-plugin`
id("dependencies")
}
dependencies {
// Deps
implementation(Deps.kotlin.plugin)
// implementation(implementation("com.badoo.reaktive.dependencies:dependencies:SNAPSHOT"))
}
// , implementation("com.badoo.reaktive.dependencies:dependencies:SNAPSHOT"),
kotlin.sourceSets.getByName("main").kotlin.srcDir("../dependencies/src/main/kotlin")
, , IDEA ( ). , Deps buildSrc2, , buildSrc2. , , . implementation("com.badoo.reaktive.dependencies:dependencies:SNAPSHOT").
dependencies .
buildSrc . , plugins { } apply plugin: 'id' . plugins , Groovy- . , . , .
, :
apply plugin: 'android-library'
android {
compileSdkVersion 30
}
apply plugin: 'custom-plugin'
class CustomPlugin: Plugin<Project> {
override fun apply(target: Project) {
target.logger.warn(
target.extentions.getByType(BaseExtension::class)
.compileSdkVersion.toString()
)
}
}
compileSdkVersion. 30. plugins { }.
plugins {
id 'android-library'
id 'custom-plugin'
}
android {
compileSdkVersion 30
}
null, custom-plugin android. :
-
apply plugin: 'custom-plugin'. , -. -
project.afterEvaluate { }. : ,afterEvaluateafterEvaluate. - API, . Gradle API, .
buildSrc, Gradle. . Groovy-, plugins { }. , .