美文网首页
是时候把构建脚本从 Groovy 迁移至 Kotlin 了

是时候把构建脚本从 Groovy 迁移至 Kotlin 了

作者: BlueSocks | 来源:发表于2023-05-11 16:51 被阅读0次

Kotlin scripting 的优势

对于开发者来说,保证整个项目中语言和代码的一致性是很重要的。尤其是对于 Android 开发者来说,使用 Kotlin 语言编写业务代码,同样也希望使用 Kotlin 语言来构建项目。虽然 Kotlin 脚本目前还是 Experimental 的,但是 Gradle Kotlin DSL已经足够成熟和稳定,可以胜任 Android 的构建管理
除此之外,Kotlin 脚本相对于 Groovy 来说可读性更高,也更利于 IDE 的语法检查、自动补全和跳转。所以迁移至 Kotlin 脚本是一个很好的选择

基础使用

顶级 settings.gradle.kts

顶级 settings.gradle.kts 用来定义工程级的仓库配置以及用来构建应用的 module

pluginManagement {
    repositories {
        google()
        mavenCentral()
        gradlePluginPortal()
    }
}
dependencyResolutionManagement {
    repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
    repositories {
        google()
        mavenCentral()
    }
}

rootProject.name = "My Application"
include(":app")

pluginManagement() 用来配置各种 Gradle 插件的配置,包括插件所属仓库、依赖处理策略、依赖版本等
dependencyResolutionManagement() 用来配置 Project 以及各个子 module 共用的仓库和依赖(module 独有的依赖最好在 module 自己的 build.gradle.kts 中配置)

顶级 build.gradle.kts

顶级 build.gradle.kts 用来定义 Project 以及各个子 module 共用的插件和属性

plugins {
    id("com.android.application") version "8.2.0-alpha02" apply false
    id("org.jetbrains.kotlin.android") version "1.8.10" apply false
}

尽管可以使用如下的方法定义 module 共用的属性,但是为了解耦,尽量不要这样用

ext {
    extra["sdkVersion"] = 33
    extra["appcompatVersion"] = "1.6.1"
}
// compileSdk = rootProject.extra["sdkVersion"]

module 级 build.gradle.kts

module 级 build.gradle.kts 用来配置 module 自己的依赖和配置信息

plugins {
    id("com.android.application")
    id("org.jetbrains.kotlin.android")
}

android {
    namespace = "com.yourapp.myapplication"
    compileSdk = 33

    defaultConfig {
        applicationId = "com.yourapp.myapplication"
        minSdk = 24
        targetSdk = 33
        versionCode = 1
        versionName = "1.0"

        testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
        vectorDrawables {
            useSupportLibrary = true
        }
    }

    buildTypes {
        release {
            isMinifyEnabled = false
            proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro")
        }
    }
    compileOptions {
        sourceCompatibility = JavaVersion.VERSION_1_8
        targetCompatibility = JavaVersion.VERSION_1_8
    }
    kotlinOptions {
        jvmTarget = "1.8"
    }
    buildFeatures {
        compose = true
    }
    composeOptions {
        kotlinCompilerExtensionVersion = "1.4.3"
    }
    packaging {
        resources {
            excludes += "/META-INF/{AL2.0,LGPL2.1}"
        }
    }
}

dependencies {
    implementation("androidx.core:core-ktx:1.9.0")
}

Groovy 迁移

补充赋值的 =,如 compileSdkVersion 30 变为 compileSdk = 33
调整字符串语法,如 "$project.rootDir/tools/proguard-rules-debug.pro" 变为 "${project.rootDir}/tools/proguard-rules-debug.pro"
val/var 替换 def 进行变量声明,如 def building64Bit = false 变为 val building64Bit = false
调整 list 和 map 语法,如 jvmOptions += ["-Xms4000m", "-Xmx4000m"] 变为 jvmOptions += listOf("-Xms4000m", "-Xmx4000m")

最佳实践

上面我们已经提到,在顶级 build.gradle.kts 中定义 module/subproject 共用的属性不利于解耦,那各个 module 怎么优雅地添加中央化的 dependency 和 version 呢?
一种比较好的方式是使用 Gradle version catalog,使用方式就像直接使用目录层级引用一样,如:

implementation(libs.accompanist.systemuicontroller)
implementation(libs.androidx.activity.compose)
implementation(libs.androidx.appcompat)
implementation(libs.androidx.core.ktx)

前提是需要在根目录下的 gradle 目录下创建一个 libs.versions.toml 文件,它使用 TOML(一种简洁高效的配置文件格式)格式来书写,在这里咱们可以用来声明 [versions], [libraries], [bundles], [plugins],如:

[versions]
accompanist = "0.28.0"
androidGradlePlugin = "8.0.0"
androidxActivity = "1.7.0"

[libraries]
accompanist-systemuicontroller = { group = "com.google.accompanist", name = "accompanist-systemuicontroller", version.ref = "accompanist" }
androidx-activity-compose = { group = "androidx.activity", name = "activity-compose", version.ref = "androidxActivity" }

[plugins]
android-application = { id = "com.android.application", version.ref = "androidGradlePlugin" }
android-library = { id = "com.android.library", version.ref = "androidGradlePlugin" }

依赖可以用多种形式来声明,"com.mycompany:mylib:1.4", { module = "com.mycompany:other", version = "1.4" } 或者 { group = "com.mycompany", name = "alternate", version = "1.4" } 都可以
如果你不想用默认的 libs 目录名,可以这样来自定义名字:

dependencyResolutionManagement {
    defaultLibrariesExtensionName.set("projectLibs")
}

version catalog 是类型安全的,编译器会自动检查和自动补全。如果在某些场景下不可用,可以尝试使用不安全的 API:

val versionCatalog = extensions.getByType<VersionCatalogsExtension>().named("libs")
dependencies {
    versionCatalog.findLibrary("accompanist-systemuicontroller").ifPresent {
        implementation(it)
    }
}

如果想要在多个团队或者多个项目中共享一个 version catalog 文件,可以这样依赖本地文件:

dependencyResolutionManagement {
    versionCatalogs {
        create("libs") {
            from(files("../gradle/libs.versions.toml"))
        }
    }
}

或者更灵活一点,把 version catalog 以插件的形式使用:

plugins {
    `version-catalog`
    `maven-publish`
}

catalog {
    versionCatalog {
        library("my-lib", "com.mycompany:mylib:1.2")
    }
}

publishing {
    publications {
        create<MavenPublication>("maven") {
            from(components["versionCatalog"])
        }
    }
}

dependencyResolutionManagement {
    versionCatalogs {
        create("libs") {
            from("com.mycompany:catalog:1.0")
            version("accompanist", "0.28.0")
        }
    }
}

总之,我们最终期望的,都是一个类型安全的、中央化的、灵活解耦的依赖和版本管理,使用 Kotlin + version catalog 目前来说是一个比较好的方案

相关文章

  • Gradle

    Gradle是什么 Gradle是基于jvm的开源构建工具,使用脚本语言groovy或kotlin开发,是andr...

  • 自定义Gradle插件

    是什么 Gradle是一个开源的自动化构建工具,可以使用groovy或kotlin来编写Gradle构建脚本,具有...

  • Gradle概述

    Gradle是一个开源的构建自动化工具,专注于灵活性和性能。Gradle构建脚本使用Groovy或Kotlin D...

  • Android gradle学习

    gradle构建工具让工程有了无限可能和组合。 gradle核心是基于groovy脚本语言,groovy脚本基于j...

  • Android工程gradle顺序

    Android工程gradle顺序 Android项目,构建脚本是Gradle,基于Groovy语言,构建过程就是...

  • gradle基础总结

    前言 Gradle基于Groovy语言,采用DSL的构建工具。gradle脚本中可以包含Groovy的任何元素。 ...

  • Gradle教程

    Gradle教程 Gradle是一种构建工具,它抛弃了基于XML的构建脚本,取而代之的是采用一种基于Groovy的...

  • Gradle-构建脚本

    Gradle 构建配置脚本常识科普 构建语言 Gradle提供了一种领域特定语言,目前同时支持 Groovy 和 ...

  • Jenkins-打包应用程序

    0.Jenkins构建产物的几种方式 1.使用Pipeline脚本去构建这种方式的好处就是可以使用Groovy脚本...

  • Gradle 相关

    一、Groovy脚本 Groovy是一种动态语言,Groovy脚本基于Java且拓展了Java,都在Java虚拟机...

网友评论

      本文标题:是时候把构建脚本从 Groovy 迁移至 Kotlin 了

      本文链接:https://www.haomeiwen.com/subject/ghbssdtx.html