Gradle Kotlin DSL:在唯一位置定义 Kotlin 版本
Gradle Kotlin DSL: Define Kotlin version in unique place
为了描述 Gradle 构建脚本,我们可以通过 build.gradle.kts
文件使用 Kotlin。全局定义要使用的 the Kotlin 版本是一个常见的问题,无论是在 dependencies
还是在构建 plugin
部分(有不同的情况并不常见给定案例使用的版本)。
考虑以下代码 (Gradle 4.3.1):
plugins {
var pluginVersion = "1.2.30"
kotlin("jvm").version(kotlinVersion)
// more
}
var dependencyVersion = "1.2.30"
dependencies {
compile(kotlin("stdlib", kotlinVersion))
compile(kotlin("reflect", kotlinVersion))
testCompile(kotlin("test", kotlinVersion))
// more
}
如您所见,kotlin version
(本例中为 1.2.30)定义了 两次:dependencyVersion
和 pluginVersion
,这通常 没有区别 。由于 DSL 限制,无法从 plugins
块外部访问 pluginVersion
或从 plugins
块内访问 dependencyVersion
。
如何将版本字符串 "1.2.30"
提取到一个地方?
有一种可用的解决方法,即搜索为 kotlin 插件 定义的版本并将其分配给外部变量。以下证明了这一点:
val kotlinVersion: String? by extra {
buildscript.configurations["classpath"]
.resolvedConfiguration.firstLevelModuleDependencies
.find { it.moduleName == "kotlin-gradle-plugin" }?.moduleVersion
}
plugins {
kotlin("jvm").version("1.2.30")
//more
}
然后可以在 dependencies
中使用变量 kotlinVersion
,而不会出现更多问题。
您可以从插件中提取版本class:
import org.jetbrains.kotlin.gradle.plugin.KotlinPluginWrapper
plugins {
kotlin("jvm") version "1.2.0"
}
val kotlinVersion = plugins.getPlugin(KotlinPluginWrapper::class.java).kotlinPluginVersion
在 Gradle 的更高版本中,您不再需要指定 kotlin(stdlib|reflect|test)
依赖项的版本,Kotlin 插件会自动为您配置它们。
对于将依赖提取到一个地方,主要有两种模式:
- 定义要在
buildSrc/src/main/kotlin/
内的对象中共享的常量,并在构建脚本中使用该对象,来自 buildSrc
的代码可用于整个脚本,包括 plugins
块
使用系统属性,您可以在gradle.properties
中定义一个系统属性,方法是在其名称前加上systemProp.
,您可以访问系统通过 System.getProperties()
的属性,例如:
// build.gradle.kts
plugins {
val kotlinVersion by System.getProperties()
println("Kotlin version is $kotlinVersion")
}
// gradle.properties
systemProp.kotlinVersion=1.2.20
我刚刚偶然发现在我的 build.gradle.kts
.
中使用 Kotlin 类
我必须:
- 创建一个名为
buildSrc
的模块,其根部包含 src/main/kotlin
和 build.gradle.kts
。
- (过时)
include("buildSrc")
在 settings.gradle.kts
buildSrc/build.gradle.kts
非常小:
plugins {
`kotlin-dsl`
}
repositories {
jcenter()
}
在 buildSrc/src/main/kotlin
我添加了一个 Config.kt
const val GROUP_ID = "my-company"
const val VERSION = "0.1.0-SNAPSHOT"
const val POM_NAME = "my-library-name"
const val POM_DESCRIPTION = "A library doing stuff."
const val POM_URL = "https://github.com/${GROUP_ID}/${POM_NAME}/"
const val POM_SCM_URL = POM_URL
const val POM_SCM_CONNECTION = "scm:git:git://github.com/${GROUP_ID}/${POM_NAME}.git"
const val POM_SCM_DEV_CONNECTION = "scm:git:ssh://git@github.com/${GROUP_ID}/${POM_NAME}.git"
const val POM_LICENCE_NAME = "The Apache Software License, Version 2.0"
const val POM_LICENCE_URL = "http://www.apache.org/licenses/LICENSE-2.0.txt"
const val POM_LICENCE_DIST = "repo"
const val POM_DEVELOPER_ID = "me"
const val POM_DEVELOPER_NAME = "meeee"
const val POM_DEVELOPER_EMAIL = "me@foo.com"
还有一个Dependencies.kt
@file:Suppress("MemberVisibilityCanBePrivate")
object Jvm {
const val version = "1.8"
}
object Kotlin {
const val version = "1.3.50"
const val stdlibJdk8 = "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$version"
const val jvmId = "jvm"
const val kaptId = "kapt"
}
object MavenPublish {
const val id = "maven-publish"
}
object Arrow {
const val version = "0.10.1"
const val core = "io.arrow-kt:arrow-core:$version"
const val syntax = "io.arrow-kt:arrow-syntax:$version"
const val optics = "io.arrow-kt:arrow-optics:$version"
const val fx = "io.arrow-kt:arrow-fx:$version"
const val meta = "io.arrow-kt:arrow-meta:$version"
}
object Versions {
const val version = "0.27.0"
const val versions = "com.github.ben-manes:gradle-versions-plugin:$version"
const val id = "com.github.ben-manes.versions"
}
所以我可以在我的根 build.gradle.kts
中使用它,比如
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
plugins {
kotlin(Kotlin.jvmId) version Kotlin.version
kotlin(Kotlin.kaptId) version Kotlin.version
id(Versions.id) version Versions.version
id(MavenPublish.id)
}
group = GROUP_ID
version = VERSION
repositories {
mavenCentral()
jcenter()
}
dependencies {
implementation(Kotlin.stdlibJdk8)
implementation(Arrow.core)
implementation(Arrow.syntax)
kapt(Arrow.meta)
}
tasks.withType<KotlinCompile> {
kotlinOptions.jvmTarget = Jvm.version
}
publishing {
publications {
create<MavenPublication>("mavenJava") {
@Suppress("UnstableApiUsage")
pom {
name.set(POM_NAME)
description.set(POM_DESCRIPTION)
url.set(POM_URL)
licenses {
license {
name.set(POM_LICENCE_NAME)
url.set(POM_LICENCE_URL)
distribution.set(POM_LICENCE_DIST)
}
}
developers {
developer {
id.set(POM_DEVELOPER_ID)
name.set(POM_DEVELOPER_NAME)
email.set(POM_DEVELOPER_EMAIL)
}
}
scm {
connection.set(POM_SCM_CONNECTION)
developerConnection.set(POM_SCM_DEV_CONNECTION)
url.set(POM_SCM_URL)
}
}
}
}
}
我对此很满意,但是当它归结为自动增加 version
时,我可能会退回到 gradle.properties
.
中维护它
编辑:
不再需要(并且允许)将 buildSrc
添加到 settings.gradle.kts
,如果存在,它将自动被拾取。
@s1m0nw1 评论的回答(评论太长):
不,你不能在 buildSrc/build.gradle 中使用 buildSrc/src 东西。我在编写基于 android 的插件时遇到了这个问题,我在 buildsSrc 中需要 android gradle 插件依赖,但我也在项目中声明了这个依赖。所以我有两个不同的地方和两个版本要维护。
我通过在 buildSrc 目录中创建 gradle.properties 文件解决了这个问题。
我在其中创建了道具 androidGradlePluginVersion=3.6.0-rc02
buildSrc/build.gradle:
val androidGradlePluginVersion: String by project
dependencies {
implementation("com.android.tools.build:gradle:$androidGradlePluginVersion")
buildSrc/src/.../Versions.kt:
var ANDROID_PLUGIN = loadAndroidGradlePluginVersion()
道具的用途:
val GRADLE_PROPERTIES = "buildSrc/gradle.properties"
val ANDROID_PLUGIN_VERSION_PROP = "androidGradlePluginVersion"
fun loadAndroidGradlePluginVersion(): String {
Properties().apply { load(FileInputStream(GRADLE_PROPERTIES)) }.let {
return it.getProperty(ANDROID_PLUGIN_VERSION_PROP)
}
error("Provide $ANDROID_PLUGIN_VERSION_PROP in $GRADLE_PROPERTIES")
}
一旦您为 Kotlin 插件定义了一个版本,所有其他 Kotlin 库将使用相同的版本,并且不需要特定的版本集。
所以只有需要设置版本的地方是定义插件的类路径时,例如:
buildscript {
repositories {
google()
mavenCentral()
gradlePluginPortal()
}
dependencies {
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.5.31")
}
}
如果您随后需要该版本用于某些其他目的(例如在 resolutionStrategy
中或仅供参考),您可以从 org.jetbrains.kotlin.config.KotlinCompilerVersion.VERSION
获取它
例如:
println("Kotlin version used is ${org.jetbrains.kotlin.config.KotlinCompilerVersion.VERSION}")
为了描述 Gradle 构建脚本,我们可以通过 build.gradle.kts
文件使用 Kotlin。全局定义要使用的 the Kotlin 版本是一个常见的问题,无论是在 dependencies
还是在构建 plugin
部分(有不同的情况并不常见给定案例使用的版本)。
考虑以下代码 (Gradle 4.3.1):
plugins {
var pluginVersion = "1.2.30"
kotlin("jvm").version(kotlinVersion)
// more
}
var dependencyVersion = "1.2.30"
dependencies {
compile(kotlin("stdlib", kotlinVersion))
compile(kotlin("reflect", kotlinVersion))
testCompile(kotlin("test", kotlinVersion))
// more
}
如您所见,kotlin version
(本例中为 1.2.30)定义了 两次:dependencyVersion
和 pluginVersion
,这通常 没有区别 。由于 DSL 限制,无法从 plugins
块外部访问 pluginVersion
或从 plugins
块内访问 dependencyVersion
。
如何将版本字符串 "1.2.30"
提取到一个地方?
有一种可用的解决方法,即搜索为 kotlin 插件 定义的版本并将其分配给外部变量。以下证明了这一点:
val kotlinVersion: String? by extra {
buildscript.configurations["classpath"]
.resolvedConfiguration.firstLevelModuleDependencies
.find { it.moduleName == "kotlin-gradle-plugin" }?.moduleVersion
}
plugins {
kotlin("jvm").version("1.2.30")
//more
}
然后可以在 dependencies
中使用变量 kotlinVersion
,而不会出现更多问题。
您可以从插件中提取版本class:
import org.jetbrains.kotlin.gradle.plugin.KotlinPluginWrapper
plugins {
kotlin("jvm") version "1.2.0"
}
val kotlinVersion = plugins.getPlugin(KotlinPluginWrapper::class.java).kotlinPluginVersion
在 Gradle 的更高版本中,您不再需要指定 kotlin(stdlib|reflect|test)
依赖项的版本,Kotlin 插件会自动为您配置它们。
对于将依赖提取到一个地方,主要有两种模式:
- 定义要在
buildSrc/src/main/kotlin/
内的对象中共享的常量,并在构建脚本中使用该对象,来自buildSrc
的代码可用于整个脚本,包括plugins
块 使用系统属性,您可以在
gradle.properties
中定义一个系统属性,方法是在其名称前加上systemProp.
,您可以访问系统通过System.getProperties()
的属性,例如:// build.gradle.kts plugins { val kotlinVersion by System.getProperties() println("Kotlin version is $kotlinVersion") } // gradle.properties systemProp.kotlinVersion=1.2.20
我刚刚偶然发现在我的 build.gradle.kts
.
我必须:
- 创建一个名为
buildSrc
的模块,其根部包含src/main/kotlin
和build.gradle.kts
。 - (过时)
include("buildSrc")
在settings.gradle.kts
buildSrc/build.gradle.kts
非常小:
plugins {
`kotlin-dsl`
}
repositories {
jcenter()
}
在 buildSrc/src/main/kotlin
我添加了一个 Config.kt
const val GROUP_ID = "my-company"
const val VERSION = "0.1.0-SNAPSHOT"
const val POM_NAME = "my-library-name"
const val POM_DESCRIPTION = "A library doing stuff."
const val POM_URL = "https://github.com/${GROUP_ID}/${POM_NAME}/"
const val POM_SCM_URL = POM_URL
const val POM_SCM_CONNECTION = "scm:git:git://github.com/${GROUP_ID}/${POM_NAME}.git"
const val POM_SCM_DEV_CONNECTION = "scm:git:ssh://git@github.com/${GROUP_ID}/${POM_NAME}.git"
const val POM_LICENCE_NAME = "The Apache Software License, Version 2.0"
const val POM_LICENCE_URL = "http://www.apache.org/licenses/LICENSE-2.0.txt"
const val POM_LICENCE_DIST = "repo"
const val POM_DEVELOPER_ID = "me"
const val POM_DEVELOPER_NAME = "meeee"
const val POM_DEVELOPER_EMAIL = "me@foo.com"
还有一个Dependencies.kt
@file:Suppress("MemberVisibilityCanBePrivate")
object Jvm {
const val version = "1.8"
}
object Kotlin {
const val version = "1.3.50"
const val stdlibJdk8 = "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$version"
const val jvmId = "jvm"
const val kaptId = "kapt"
}
object MavenPublish {
const val id = "maven-publish"
}
object Arrow {
const val version = "0.10.1"
const val core = "io.arrow-kt:arrow-core:$version"
const val syntax = "io.arrow-kt:arrow-syntax:$version"
const val optics = "io.arrow-kt:arrow-optics:$version"
const val fx = "io.arrow-kt:arrow-fx:$version"
const val meta = "io.arrow-kt:arrow-meta:$version"
}
object Versions {
const val version = "0.27.0"
const val versions = "com.github.ben-manes:gradle-versions-plugin:$version"
const val id = "com.github.ben-manes.versions"
}
所以我可以在我的根 build.gradle.kts
中使用它,比如
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
plugins {
kotlin(Kotlin.jvmId) version Kotlin.version
kotlin(Kotlin.kaptId) version Kotlin.version
id(Versions.id) version Versions.version
id(MavenPublish.id)
}
group = GROUP_ID
version = VERSION
repositories {
mavenCentral()
jcenter()
}
dependencies {
implementation(Kotlin.stdlibJdk8)
implementation(Arrow.core)
implementation(Arrow.syntax)
kapt(Arrow.meta)
}
tasks.withType<KotlinCompile> {
kotlinOptions.jvmTarget = Jvm.version
}
publishing {
publications {
create<MavenPublication>("mavenJava") {
@Suppress("UnstableApiUsage")
pom {
name.set(POM_NAME)
description.set(POM_DESCRIPTION)
url.set(POM_URL)
licenses {
license {
name.set(POM_LICENCE_NAME)
url.set(POM_LICENCE_URL)
distribution.set(POM_LICENCE_DIST)
}
}
developers {
developer {
id.set(POM_DEVELOPER_ID)
name.set(POM_DEVELOPER_NAME)
email.set(POM_DEVELOPER_EMAIL)
}
}
scm {
connection.set(POM_SCM_CONNECTION)
developerConnection.set(POM_SCM_DEV_CONNECTION)
url.set(POM_SCM_URL)
}
}
}
}
}
我对此很满意,但是当它归结为自动增加 version
时,我可能会退回到 gradle.properties
.
编辑:
不再需要(并且允许)将 buildSrc
添加到 settings.gradle.kts
,如果存在,它将自动被拾取。
@s1m0nw1 评论的回答(评论太长): 不,你不能在 buildSrc/build.gradle 中使用 buildSrc/src 东西。我在编写基于 android 的插件时遇到了这个问题,我在 buildsSrc 中需要 android gradle 插件依赖,但我也在项目中声明了这个依赖。所以我有两个不同的地方和两个版本要维护。
我通过在 buildSrc 目录中创建 gradle.properties 文件解决了这个问题。
我在其中创建了道具 androidGradlePluginVersion=3.6.0-rc02
buildSrc/build.gradle:
val androidGradlePluginVersion: String by project
dependencies {
implementation("com.android.tools.build:gradle:$androidGradlePluginVersion")
buildSrc/src/.../Versions.kt:
var ANDROID_PLUGIN = loadAndroidGradlePluginVersion()
道具的用途:
val GRADLE_PROPERTIES = "buildSrc/gradle.properties"
val ANDROID_PLUGIN_VERSION_PROP = "androidGradlePluginVersion"
fun loadAndroidGradlePluginVersion(): String {
Properties().apply { load(FileInputStream(GRADLE_PROPERTIES)) }.let {
return it.getProperty(ANDROID_PLUGIN_VERSION_PROP)
}
error("Provide $ANDROID_PLUGIN_VERSION_PROP in $GRADLE_PROPERTIES")
}
一旦您为 Kotlin 插件定义了一个版本,所有其他 Kotlin 库将使用相同的版本,并且不需要特定的版本集。
所以只有需要设置版本的地方是定义插件的类路径时,例如:
buildscript {
repositories {
google()
mavenCentral()
gradlePluginPortal()
}
dependencies {
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.5.31")
}
}
如果您随后需要该版本用于某些其他目的(例如在 resolutionStrategy
中或仅供参考),您可以从 org.jetbrains.kotlin.config.KotlinCompilerVersion.VERSION
例如:
println("Kotlin version used is ${org.jetbrains.kotlin.config.KotlinCompilerVersion.VERSION}")