关于build-logic的一次小尝试

0 阅读3分钟

在Android Gradle Plugin 升级到9.0后,谷歌官方会推荐我们使用build-logic。通过统一构造plugin,在多个module中,可以对他们的build.gradle进行统一管理,减少重复代码,十分方便。

创建build-logic文件夹

  1. 在根目录下新建文件夹,"build-logic"。

  2. 在build-logic文件夹下,新建gradle文件"settings.gradle.kts"。

    pluginManagement {
        repositories {
            maven { url = uri("https://maven.aliyun.com/repository/public") }
            maven { url = uri("https://maven.aliyun.com/repository/google") }
            maven { url = uri("https://maven.aliyun.com/repository/central") }
            maven { url = uri("https://maven.aliyun.com/repository/gradle-plugin") }
            google {
                content {
                    includeGroupByRegex("com\.android.*")
                    includeGroupByRegex("com\.google.*")
                    includeGroupByRegex("androidx.*")
                }
            }
            mavenCentral()
            gradlePluginPortal()
        }
    }
    dependencyResolutionManagement {
        repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
        repositories {
            maven { url = uri("https://maven.aliyun.com/repository/public") }
            maven { url = uri("https://maven.aliyun.com/repository/google") }
            maven { url = uri("https://maven.aliyun.com/repository/central") }
            google()
            mavenCentral()
        }
        // 注意这个,添加libs的映射关系
        versionCatalogs {
            create("libs") {
                from(files("../gradle/libs.versions.toml"))
            }
        }
    }

    rootProject.name = "build-logic"
    // 等会添加
    // include(":convention")
  1. 在根目录中的"settings.gradle.kts"中,将我们的这个"build-logic"加入gradle中。
    pluginManagement {

        includeBuild("build-logic")

        repositories {
            /// ...
        }
    }
  1. 编译一下项目,应该可以看到,build-logic被Android Studio识别成了模块,说明是正常了

新建convention模块

  1. 在build-logic文件夹下,新建文件夹"convention"。

  2. 在"convention"文件夹中,新建build.gradle.kts文件

    import org.jetbrains.kotlin.gradle.dsl.JvmTarget

    plugins {
        `kotlin-dsl`
    }

    group = "com.zq.myapplication.buildlogic.convention"

    java {
        sourceCompatibility = JavaVersion.VERSION_17
        targetCompatibility = JavaVersion.VERSION_17
    }

    kotlin {
        compilerOptions {
            jvmTarget = JvmTarget.JVM_17
        }
    }

    dependencies {
        // TODO 用来添加模块中用到的依赖
    }


    gradlePlugin {
        plugins {
    		// TODO 用来注册
        }
    }
  1. 在根目录gradle文件夹下的libs.versions.toml文件中,添加用到的plugin依赖,注意是library下。
    [libraries]
    #build-logic
    android-gradlePlugin = { group = "com.android.tools.build", name = "gradle-api", version.ref = "androidGradlePlugin" }
    android-tools-common = { group = "com.android.tools", name = "common", version.ref = "androidTools" }
    kotlin-gradlePlugin = { group = "org.jetbrains.kotlin", name = "kotlin-gradle-plugin", version.ref = "kotlin" }
    compose-gradlePlugin = { module = "org.jetbrains.kotlin:compose-compiler-gradle-plugin", version.ref = "kotlin" }
    kotlin-gradlePlugin = { group = "org.jetbrains.kotlin", name = "kotlin-gradle-plugin", version.ref = "kotlin" }
    ksp-gradlePlugin = { group = "com.google.devtools.ksp", name = "com.google.devtools.ksp.gradle.plugin", version.ref = "ksp" }

    [plugins]
    ...
  1. 在"convention"下的build.gradle.kts中,添加依赖
    dependencies {
    	// 注意这边只需要compileOnly就行
        compileOnly(libs.android.gradlePlugin)
        compileOnly(libs.android.tools.common)
        compileOnly(libs.compose.gradlePlugin)
        compileOnly(libs.kotlin.gradlePlugin)
        compileOnly(libs.ksp.gradlePlugin)
    }
  1. 在"convention"下新建文件夹src/main/kotlin,给后续添加文件使用

  2. 在"build-logic"的settings.gradle.kts下,将convention模块添加

    pluginManagement {
        repositories {
            // ...
        }
    }
    dependencyResolutionManagement {
        repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
        repositories {
            // ...
        }
        versionCatalogs {
            create("libs") {
                from(files("../gradle/libs.versions.toml"))
            }
        }
    }

    rootProject.name = "build-logic"
    // 添加convention模块
    include(":convention")
  1. 再次编译一下项目,convention模块通过。

添加application的plugin类

  1. 在convention模块中新建一个类AndroidApplicationConventionPlugin
    class AndroidApplicationConventionPlugin: Plugin<Project> {
        override fun apply(target: Project) {
            with(target) {
                // 引入,标记为application
                apply(plugin = "com.android.application")

                // application 的 android { }
                extensions.configure<ApplicationExtension> {
                    defaultConfig.targetSdk = 36
                }
            }
        }
    }
  1. 前往libs.versions.toml文件中,在[plugin]下添加一个自定义的id
    [plugins]
    android-application = { id = "com.android.application", version.ref = "androidGradlePlugin" }
    /// ...
    # build-logic
    myapplication-android-application = { id = "myapplication.android.application" }
  1. 我们需要将这个id,跟我们实际的类AndroidApplicationConventionPlugin,进行一个绑定的方法。在convention模块下的build.gradle.kts中,添加映射关系。
    gradlePlugin {
        plugins {
            register("androidApplication") {
                id = libs.plugins.myapplication.android.application.get().pluginId
                implementationClass = "AndroidApplicationConventionPlugin"
            }
        }
    }
  1. 最后编译一下项目

使用自定义plugin

在app的build.gradle.kts中进行使用, 这样就可以了

plugins {
    alias(libs.plugins.myapplication.android.application)
}

Tips

  1. 关于对application和library的区分,以及使用
    // application 的 android { }
    extensions.configure<ApplicationExtension> {

    }

    // 当我依赖了application时,会执行下面方法
    pluginManager.withPlugin("com.android.application") {

    }
    // library 的 android { }
    extensions.configure<LibraryExtension> {

    }

    // 当我依赖了library时,会执行下面方法
    pluginManager.withPlugin("com.android.library") {

    }
  1. Android Gradle Plugin 9.0中,默认gradle.properties中会开启buildInKotlin, 从而我们不需要主动依赖"org.jetbrains.kotlin.android"。

  2. 在自定义plugin中,应用plugin时,不需要加版本号,gradle会自动查找

    apply(plugin = "com.android.application")

但是要注意,需要你在根目录的build.gradle.kts中添加,可能才能生效

    [plugins]
    room = { id = "androidx.room", version.ref = "room" }


    plugins {
        alias(libs.plugins.room) apply false
    }


    class AndroidRoomConventionPlugin : Plugin<Project> {

        override fun apply(target: Project) {
            with(target) {
                apply(plugin = "androidx.room")
                apply(plugin = "com.google.devtools.ksp")

                // 让room生成kotlin
                extensions.configure<KspExtension> {
                    arg("room.generateKotlin", "true")
                }

                // room存储生成的文件
                extensions.configure<RoomExtension> {
                    schemaDirectory("$projectDir/schemas")
                }

                dependencies {
                    "implementation"(libs.findLibrary("room-runtime").get())
                    "implementation"(libs.findLibrary("room-ktx").get())
                    "implementation"(libs.findLibrary("room-paging").get())
                    "ksp"(libs.findLibrary("room-compiler").get())
                }
            }
        }
    }