Construction composite comme alternative à buildSrc dans Gradle



Dans Gradle, un système de construction automatisé, l'approche buildSrc est déjà devenue la norme pour implémenter des plugins et des tâches personnalisés, ainsi que pour créer des configurations communes telles que des listes de dépendances et de versions. Mais il présente un inconvénient majeur: lors du changement, le buildSrccache d'assembly devient invalide.



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 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. :



  1. apply plugin: 'custom-plugin' . , -.
  2. project.afterEvaluate { }. : , afterEvaluate afterEvaluate .
  3. API, . Gradle API, .




buildSrc, Gradle. . Groovy-, plugins { }. , .




All Articles