将构建配置从 Groovy 迁移到 KTS

2024-02-09 06:58
文章标签 配置 构建 迁移 groovy kts

本文主要是介绍将构建配置从 Groovy 迁移到 KTS,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

将构建配置从 Groovy 迁移到 KTS

icon.jpg

文章目录

  • 将构建配置从 Groovy 迁移到 KTS
    • 前言
    • Groovy和KTS对比
      • 优点:
      • 缺点和已知问题:
    • Android构建配置从Groovy迁移KTS
      • 准备工作
      • 脚本文件名
      • 一次迁移一个文件
      • 自定义Task
      • 使用 `plugins` 代码块
      • 依赖管理
      • 构建变体
        • 显式和隐式 `buildTypes`
        • 举例说明
      • 访问配置
        • gradle.properties
        • local.properties
        • 获取系统环境变量的值
      • 关于Ext
      • 修改生成apk名称和BuildConfig中添加apk支持的cpu架构
    • buildSrc
    • 参考文档

前言

作为Android开发习惯了面向对象编程,习惯了IDEA提供的各种辅助开发快捷功能。

那么带有陌生的常规语法的Groovy脚本对于我来说一向敬而远之。

Kotlin DSL的出现感觉是为了我们量身定做的,因为采用 Kotlin 编写的代码可读性更高,并且 Kotlin 提供了更好的编译时检查和 IDE 支持。


名词概念解释

  • Gradle: 自动化构建工具. 平行产品: Maven.

  • Groovy: 语言, 编译后变为JVM byte code, 兼容Java平台.

  • DSL: Domain Specific Language, 领域特定语言.

  • Groovy DSL: Gradle的API是Java的,Groovy DSL是在其之上的脚本语言. Groovy DS脚本文件后缀: .gradle.

  • KTS:是指 Kotlin 脚本,这是 Gradle 在构建配置文件中使用的一种 Kotlin 语言形式。Kotlin 脚本是可从命令行运行的 Kotlin 代码。

  • Kotlin DSL:主要是指 Android Gradle 插件 Kotlin DSL,有时也指底层 Gradle Kotlin DSL。

在讨论从 Groovy 迁移时,术语“KTS”和“Kotlin DSL”可以互换使用。换句话说,“将 Android 项目从 Groovy 转换为 KTS”与“将 Android 项目从 Groovy 转换为 Kotlin DSL”实际上是一个意思。

Groovy和KTS对比

类型KotlinGroovy
自动代码补全支持不支持
是否类型安全不是
源码导航支持不支持
重构自动关联手动修改

优点:

  • 可以使用Kotlin, 开发者可能对这个语言更熟悉更喜欢.
  • IDE支持更好, 自动补全提示, 重构,imports等.
  • 类型安全: Kotlin是静态类型.
  • 不用一次性迁移完: 两种语言的脚本可以共存, 也可以互相调用.

缺点和已知问题:

  • 目前,采用 KTS 的构建速度可能比采用 Groovy 慢(自测小demo耗时增加约40%(约8s))。

  • Project Structure 编辑器不会展开在 buildSrc 文件夹中定义的用于库名称或版本的常量。

  • KTS 文件目前在项目视图中不提供文本提示。

Android构建配置从Groovy迁移KTS

准备工作

  1. Groovy 字符串可以用单引号 'string' 或双引号 "string" 引用,而 Kotlin 需要双引号 "string"

  2. Groovy 允许在调用函数时省略括号,而 Kotlin 总是需要括号。

  3. Gradle Groovy DSL 允许在分配属性时省略 = 赋值运算符,而 Kotlin 始终需要赋值运算符。

所以在KTS中需要统一做到:

  • 使用双引号统一引号.

groovy-kts-diff1.png

  • 消除函数调用和属性赋值的歧义(分别使用括号和赋值运算符)。

groovy-kts-diff2.png

脚本文件名

Groovy DSL 脚本文件使用 .gradle 文件扩展名。

Kotlin DSL 脚本文件使用 .gradle.kts 文件扩展名。

一次迁移一个文件

由于您可以在项目中结合使用 Groovy build 文件和 KTS build 文件,因此将项目转换为 KTS 的一个简单方法是先选择一个简单的 build 文件(例如 settings.gradle),将其重命名为 settings.gradle.kts,然后将其内容转换为 KTS。之后,确保您的项目在迁移每个 build 文件之后仍然可以编译。

自定义Task

由于Koltin 是静态类型语言,Groovy是动态语言,前者是类型安全的,他们的性质区别很明显的体现在了 task 的创建和配置上。详情可以参考Gradle官方迁移教程

// groovy
task clean(type: Delete) {delete rootProject.buildDir
}
// kotiln-dsl
tasks.register("clean", Delete::class) {delete(rootProject.buildDir)
}
val clean by tasks.creating(Delete::class) {delete(rootProject.buildDir)
}
open class GreetingTask : DefaultTask() {var msg: String? = null@TaskActionfun greet() {println("GreetingTask:$msg")}
}
val msg by tasks.creating(GreetingTask::class) {}
val testTask: Task by tasks.creating {doLast {println("testTask:Run")}
}
val testTask2: Task = task("test2") {doLast { println("Hello, World!") }
}
val testTask3: Task = tasks.create("test3") {doLast {println("testTask:Run")}
}

使用 plugins 代码块

如果您在build 文件中使用 plugins 代码块,IDE 将能够获知相关上下文信息,即使在构建失败时也是如此。IDE 可使用这些信息执行代码补全并提供其他实用建议,从而帮助您解决 KTS 文件中存在的问题。

在您的代码中,将命令式 apply plugin 替换为声明式 plugins 代码块。Groovy 中的以下代码…

apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-kapt'
apply plugin: 'androidx.navigation.safeargs.kotlin'

在 KTS 中变为以下代码:

plugins {id("com.android.application")id("kotlin-android")id("kotlin-kapt")id("androidx.navigation.safeargs.kotlin")}

如需详细了解 plugins 代码块,请参阅 Gradle 的迁移指南。

注意plugins 代码块仅解析 Gradle 插件门户中提供的插件或使用 pluginManagement 代码块指定的自定义存储库中提供的插件。如果插件来自插件门户中不存在的 buildScript 依赖项,那么这些插件在 Kotlin 中就必须使用 apply 才能应用。例如:

apply(plugin = "kotlin-android")
apply {from("${rootDir.path}/config.gradle")from("${rootDir.path}/version.gradle.kts")
}

如需了解详情,请参阅 Gradle 文档。

强烈建议您plugins {}优先使用块而不是apply()函数。

有两个关键的最佳实践可以更轻松地在 Kotlin DSL 的静态上下文中工作:

  • 使用plugins {}
  • 将本地构建逻辑放在构建的buildSrc目录中

该plugins {}块是关于保持您的构建脚本声明性,以便充分利用Kotlin DSL

使用buildSrc项目是关于将您的构建逻辑组织成共享的本地插件和约定,这些插件和约定易于测试并提供良好的 IDE 支持。

依赖管理

常见依赖

// groovy
implementation project(':library')
implementation 'com.xxxx:xxxx:8.8.1'// kotlin
implementation(project(":library"))
implementation("com.xxxx:xxx:8.8.1")

freeTree

// groovy
implementation fileTree(include: '*.jar', dir: 'libs')//kotlin
implementation(fileTree(mapOf("include" to listOf("*.jar"), "dir" to "libs")))

特别类型库依赖

//groovy
implementation(name: 'splibrary', ext: 'aar')//kotlin
implementation (group="",name="splibrary",ext = "aar")

构建变体

显式和隐式 buildTypes

在 Kotlin DSL 中,某些 buildTypes(如 debugrelease,)是隐式提供的。但是,其他 buildTypes 则必须手动创建。

例如,在 Groovy 中,您可能有 debugreleasestaging buildTypes

buildTypesdebug {...}release {...}staging {...}

在 KTS 中,仅 debugrelease buildTypes 是隐式提供的,而 staging 则必须由您手动创建:

buildTypesgetByName("debug") {...}getByName("release") {...}create("staging") {...}
举例说明

Grovvy编写:

productFlavors {demo {dimension "app"}full {dimension "app"multiDexEnabled true}}buildTypes {release {signingConfig signingConfigs.signConfigminifyEnabled truedebuggable falseproguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'}debug {minifyEnabled falsedebuggable true}}
signingConfigs {release {storeFile file("myreleasekey.keystore")storePassword "password"keyAlias "MyReleaseKey"keyPassword "password"}debug {...}}

kotlin-KTL编写:

productFlavors {create("demo") {dimension = "app"}create("full") {dimension = "app"multiDexEnabled = true}
}buildTypes {getByName("release") {signingConfig = signingConfigs.getByName("release")isMinifyEnabled = trueisDebuggable = falseproguardFiles(getDefaultProguardFile("proguard-android.txtt"), "proguard-rules.pro")}getByName("debug") {isMinifyEnabled = falseisDebuggable = true}}signingConfigs {create("release") {storeFile = file("myreleasekey.keystore")storePassword = "password"keyAlias = "MyReleaseKey"keyPassword = "password"}getByName("debug") {...}}

访问配置

gradle.properties

我们通常会把签名信息、版本信息等配置写在gradle.properties中,在kotlin-dsl中我们可以通过一下方式访问:

  1. rootProject.extra.properties
  2. project.extra.properties
  3. rootProject.properties
  4. properties
  5. System.getProperties()

System.getProperties()使用的限制比较多

  • 参数名必须按照systemProp.xxx格式(例如:systemProp.kotlinVersion=1.3.72);
  • 与当前执行的task有关(> Configure project :buildSrc> Configure project :的结果不同,后者无法获取的gradle.properties中的数据);
local.properties

获取工程的local.properties文件

gradleLocalProperties(rootDir)

gradleLocalProperties(projectDir)

获取系统环境变量的值

val JAVA_HOME:String = System.getenv("JAVA_HOME") ?: "default_value"

关于Ext

Google 官方推荐的一个 Gradle 配置最佳实践是在项目最外层 build.gradle 文件的ext代码块中定义项目范围的属性,然后在所有模块间共享这些属性,比如我们通常会这样存放依赖的版本号。

// build.gradleext {compileSdkVersion = 28buildToolsVersion = "28.0.3"supportLibVersion = "28.0.0"...
}

但是由于缺乏IDE的辅助(跳转查看、全局重构等都不支持),实际使用体验欠佳。

KTL中用extra来代替Groovy中的ext

// The extra object can be used for custom properties and makes them available to all
// modules in the project.
// The following are only a few examples of the types of properties you can define.
extra["compileSdkVersion"] = 28
// You can also create properties to specify versions for dependencies.
// Having consistent versions between modules can avoid conflicts with behavior.
extra["supportLibVersion"] = "28.0.0"
android {// Use the following syntax to access properties you defined at the project level:// rootProject.extra["property_name"]compileSdkVersion(rootProject.extra["sdkVersion"])// Alternatively, you can access properties using a type safe delegate:val sdkVersion: Int by rootProject.extra...compileSdkVersion(sdkVersion)
}
...
dependencies {implementation("com.android.support:appcompat-v7:${rootProject.ext.supportLibVersion}")...
}

build.gralde中的ext数据是可以在build.gradle.kts中使用extra进行访问的。

修改生成apk名称和BuildConfig中添加apk支持的cpu架构

val abiCodes = mapOf("armeabi-v7a" to 1, "x86" to 2, "x86_64" to 3)
android.applicationVariants.all {val buildType = this.buildType.nameval variant = thisoutputs.all {val name =this.filters.find { it.filterType == com.android.build.api.variant.FilterConfiguration.FilterType.ABI.name }?.identifierval baseAbiCode = abiCodes[name]if (baseAbiCode != null) {//写入cpu架构信息variant.buildConfigField("String", "CUP_ABI", "\"${name}\"")}if (this is com.android.build.gradle.internal.api.ApkVariantOutputImpl) {//修改apk名称if (buildType == "release") {this.outputFileName = "KotlinDSL_${name}_${buildType}.apk"} else if (buildType == "debug") {this.outputFileName = "KotlinDSL_V${variant.versionName}_${name}_${buildType}.apk"}}}
}

buildSrc

我们在使用Groovy语言构建的时候,往往会抽取一个version_config.gradle来作为全局的变量控制,而ext扩展函数则是必须要使用到的,而在我们的Gradle Kotlin DSL中,如果想要使用全局控制,则需要建议使用buildSrc

复杂的构建逻辑通常很适合作为自定义任务或二进制插件进行封装。自定义任务和插件实现不应存在于构建脚本中。buildSrc则不需要在多个独立项目之间共享代码,就可以非常方便地使用该代码了。

buildSrc被视为构建目录。编译器发现目录后,Gradle会自动编译并测试此代码,并将其放入构建脚本的类路径中。

  1. 先创建buildSrc目录;
  2. 在该目录下创建build.gradle.kts文件;
  3. 创建一个buildSrc/src/main/koltin目录;
  4. 在该目录下创建Dependencies.kt文件作为版本管理类;

需要注意的是buildSrcbuild.gradle.kts

plugins {`kotlin-dsl`
}
repositories {jcenter()
}

或者

apply {plugin("kotlin")
}
buildscript {repositories {gradlePluginPortal()}dependencies {classpath(kotlin("gradle-plugin", "1.3.72"))}
}
//dependencies {
//    implementation(gradleKotlinDsl())
//    implementation(kotlin("stdlib", "1.3.72"))
//}
repositories {gradlePluginPortal()
}

不同版本之间buildSrc下的build.gradle文件执行顺序:

gradle-wrapper.properties:5.6.4

com.android.tools.build:gradle:3.2.0

  1. BuildSrc:build.gradle
  2. setting.gradle
  3. Project:build.gradle
  4. Moudle:build.gradle

gradle-wrapper.properties:6.5

com.android.tools.build:gradle:4.1.1

  1. setting.gradle
  2. BuildSrc:build.gradle
  3. Project:build.gradle
  4. Moudle:build.gradle

所以在非buildSrc目录下的build.gradle.kts文件中我们使用Dependencies.kt需要注意其加载顺序。

参考文档

Android官网-将构建配置从 Groovy 迁移到 KTS

Migrating build logic from Groovy to Kotlin

GitHub:kotlin-dsl-samples

GitHub:kotlin-dsl-samples/samples/hello-android

Kotlin DSL: Gradle scripts in Android made easy

buildSrc官方文档

Gradle’s Kotlin DSL BuildSrc

文章到这里就全部讲述完啦,若有其他需要交流的可以留言哦~!~!

想阅读作者的更多文章,可以查看我 个人博客 和公共号:
振兴书城

这篇关于将构建配置从 Groovy 迁移到 KTS的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/693457

相关文章

MySQL 迁移至 Doris 最佳实践方案(最新整理)

《MySQL迁移至Doris最佳实践方案(最新整理)》本文将深入剖析三种经过实践验证的MySQL迁移至Doris的最佳方案,涵盖全量迁移、增量同步、混合迁移以及基于CDC(ChangeData... 目录一、China编程JDBC Catalog 联邦查询方案(适合跨库实时查询)1. 方案概述2. 环境要求3.

nginx 负载均衡配置及如何解决重复登录问题

《nginx负载均衡配置及如何解决重复登录问题》文章详解Nginx源码安装与Docker部署,介绍四层/七层代理区别及负载均衡策略,通过ip_hash解决重复登录问题,对nginx负载均衡配置及如何... 目录一:源码安装:1.配置编译参数2.编译3.编译安装 二,四层代理和七层代理区别1.二者混合使用举例

Java JDK1.8 安装和环境配置教程详解

《JavaJDK1.8安装和环境配置教程详解》文章简要介绍了JDK1.8的安装流程,包括官网下载对应系统版本、安装时选择非系统盘路径、配置JAVA_HOME、CLASSPATH和Path环境变量,... 目录1.下载JDK2.安装JDK3.配置环境变量4.检验JDK官网下载地址:Java Downloads

Linux下进程的CPU配置与线程绑定过程

《Linux下进程的CPU配置与线程绑定过程》本文介绍Linux系统中基于进程和线程的CPU配置方法,通过taskset命令和pthread库调整亲和力,将进程/线程绑定到特定CPU核心以优化资源分配... 目录1 基于进程的CPU配置1.1 对CPU亲和力的配置1.2 绑定进程到指定CPU核上运行2 基于

Spring Boot spring-boot-maven-plugin 参数配置详解(最新推荐)

《SpringBootspring-boot-maven-plugin参数配置详解(最新推荐)》文章介绍了SpringBootMaven插件的5个核心目标(repackage、run、start... 目录一 spring-boot-maven-plugin 插件的5个Goals二 应用场景1 重新打包应用

Java中读取YAML文件配置信息常见问题及解决方法

《Java中读取YAML文件配置信息常见问题及解决方法》:本文主要介绍Java中读取YAML文件配置信息常见问题及解决方法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要... 目录1 使用Spring Boot的@ConfigurationProperties2. 使用@Valu

Jenkins分布式集群配置方式

《Jenkins分布式集群配置方式》:本文主要介绍Jenkins分布式集群配置方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录1.安装jenkins2.配置集群总结Jenkins是一个开源项目,它提供了一个容易使用的持续集成系统,并且提供了大量的plugin满

SpringBoot线程池配置使用示例详解

《SpringBoot线程池配置使用示例详解》SpringBoot集成@Async注解,支持线程池参数配置(核心数、队列容量、拒绝策略等)及生命周期管理,结合监控与任务装饰器,提升异步处理效率与系统... 目录一、核心特性二、添加依赖三、参数详解四、配置线程池五、应用实践代码说明拒绝策略(Rejected

使用Docker构建Python Flask程序的详细教程

《使用Docker构建PythonFlask程序的详细教程》在当今的软件开发领域,容器化技术正变得越来越流行,而Docker无疑是其中的佼佼者,本文我们就来聊聊如何使用Docker构建一个简单的Py... 目录引言一、准备工作二、创建 Flask 应用程序三、创建 dockerfile四、构建 Docker

SQL Server配置管理器无法打开的四种解决方法

《SQLServer配置管理器无法打开的四种解决方法》本文总结了SQLServer配置管理器无法打开的四种解决方法,文中通过图文示例介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的... 目录方法一:桌面图标进入方法二:运行窗口进入检查版本号对照表php方法三:查找文件路径方法四:检查 S