将构建配置从 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

相关文章

mybatis映射器配置小结

《mybatis映射器配置小结》本文详解MyBatis映射器配置,重点讲解字段映射的三种解决方案(别名、自动驼峰映射、resultMap),文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定... 目录select中字段的映射问题使用SQL语句中的别名功能使用mapUnderscoreToCame

Linux下MySQL数据库定时备份脚本与Crontab配置教学

《Linux下MySQL数据库定时备份脚本与Crontab配置教学》在生产环境中,数据库是核心资产之一,定期备份数据库可以有效防止意外数据丢失,本文将分享一份MySQL定时备份脚本,并讲解如何通过cr... 目录备份脚本详解脚本功能说明授权与可执行权限使用 Crontab 定时执行编辑 Crontab添加定

Java使用jar命令配置服务器端口的完整指南

《Java使用jar命令配置服务器端口的完整指南》本文将详细介绍如何使用java-jar命令启动应用,并重点讲解如何配置服务器端口,同时提供一个实用的Web工具来简化这一过程,希望对大家有所帮助... 目录1. Java Jar文件简介1.1 什么是Jar文件1.2 创建可执行Jar文件2. 使用java

SpringBoot 多环境开发实战(从配置、管理与控制)

《SpringBoot多环境开发实战(从配置、管理与控制)》本文详解SpringBoot多环境配置,涵盖单文件YAML、多文件模式、MavenProfile分组及激活策略,通过优先级控制灵活切换环境... 目录一、多环境开发基础(单文件 YAML 版)(一)配置原理与优势(二)实操示例二、多环境开发多文件版

Vite 打包目录结构自定义配置小结

《Vite打包目录结构自定义配置小结》在Vite工程开发中,默认打包后的dist目录资源常集中在asset目录下,不利于资源管理,本文基于Rollup配置原理,本文就来介绍一下通过Vite配置自定义... 目录一、实现原理二、具体配置步骤1. 基础配置文件2. 配置说明(1)js 资源分离(2)非 JS 资

MySQL8 密码强度评估与配置详解

《MySQL8密码强度评估与配置详解》MySQL8默认启用密码强度插件,实施MEDIUM策略(长度8、含数字/字母/特殊字符),支持动态调整与配置文件设置,推荐使用STRONG策略并定期更新密码以提... 目录一、mysql 8 密码强度评估机制1.核心插件:validate_password2.密码策略级

ShardingProxy读写分离之原理、配置与实践过程

《ShardingProxy读写分离之原理、配置与实践过程》ShardingProxy是ApacheShardingSphere的数据库中间件,通过三层架构实现读写分离,解决高并发场景下数据库性能瓶... 目录一、ShardingProxy技术定位与读写分离核心价值1.1 技术定位1.2 读写分离核心价值二

Three.js构建一个 3D 商品展示空间完整实战项目

《Three.js构建一个3D商品展示空间完整实战项目》Three.js是一个强大的JavaScript库,专用于在Web浏览器中创建3D图形,:本文主要介绍Three.js构建一个3D商品展... 目录引言项目核心技术1. 项目架构与资源组织2. 多模型切换、交互热点绑定3. 移动端适配与帧率优化4. 可

QT Creator配置Kit的实现示例

《QTCreator配置Kit的实现示例》本文主要介绍了使用Qt5.12.12与VS2022时,因MSVC编译器版本不匹配及WindowsSDK缺失导致配置错误的问题解决,感兴趣的可以了解一下... 目录0、背景:qt5.12.12+vs2022一、症状:二、原因:(可以跳过,直奔后面的解决方法)三、解决方

SpringBoot路径映射配置的实现步骤

《SpringBoot路径映射配置的实现步骤》本文介绍了如何在SpringBoot项目中配置路径映射,使得除static目录外的资源可被访问,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一... 目录SpringBoot路径映射补:springboot 配置虚拟路径映射 @RequestMapp