Gradle Kotlin DSL:在唯一位置定义Kotlin版本

Gradle Kotlin DSL:在唯一位置定义Kotlin版本,gradle,kotlin,build.gradle,gradle-kotlin-dsl,Gradle,Kotlin,Build.gradle,Gradle Kotlin Dsl,为了描述Gradle构建脚本,我们可以通过build.Gradle.kts文件使用Kotlin。在依赖项和构建插件部分,全局定义要使用的Kotlin版本是一个常见问题(对于给定的情况,使用不同的版本是很少见的) 考虑以下代码(Gradle 4.3.1): 如您所见,kotlin版本(本例中为1.2.30)定义了两次:dependencyVersion和pluginVersion,这两个版本通常没有区别。由于DSL限制,无法从插件块外部访问插件,也无法从插件块内部访问依赖版本 如何将版本字符串“1

为了描述Gradle构建脚本,我们可以通过
build.Gradle.kts
文件使用Kotlin。在
依赖项
和构建
插件
部分,全局定义要使用的Kotlin版本是一个常见问题(对于给定的情况,使用不同的版本是很少见的)

考虑以下代码(Gradle 4.3.1):

如您所见,kotlin
版本(本例中为1.2.30)定义了两次:
dependencyVersion
pluginVersion
,这两个版本通常没有区别。由于DSL限制,无法从
插件
块外部访问
插件
,也无法从
插件
块内部访问
依赖版本


如何将版本字符串
“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
}

然后,变量
kotlinVersion
可以在
依赖项中使用,而无需进一步麻烦。

您可以从插件类中提取版本:

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
    的代码可用于整个脚本,包括
    插件
  • 使用系统属性时,您可以在
    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
  • (过时)
    settings.gradle.kts中包含(“buildSrc”)
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"
@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"
}
和a
Dependencies.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"
@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"
}
所以我可以在我的root
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)
                }
            }
        }
    }
}
import org.jetbrains.kotlin.gradle.tasks.kotlincomfile
插件{
kotlin(kotlin.jvmId)版本kotlin.version
kotlin(kotlin.kaptId)版本kotlin.version
id(Versions.id)version.version
id(MavenPublish.id)
}
组=组ID
版本=版本
存储库{
mavenCentral()
jcenter()
}
依赖关系{
实现(Kotlin.stdlibJdk8)
实现(Arrow.core)
实现(Arrow.syntax)
kapt(箭头,meta)
}
tasks.withType{
kotlinOptions.jvmTarget=Jvm.version
}
出版{
出版物{
创建(“mavenJava”){
@抑制(“不稳定使用”)
聚甲醛{
名称.集合(POM_名称)
说明.集合(POM_说明)
url.set(POM_url)
执照{
许可证{
名称.集合(POM_许可证_名称)
url.set(POM\u许可证\u url)
分发.设置(POM\U许可证\U区)
}
}
开发者{
显影剂{
id.set(POM\U开发者\U id)
name.set(POM\u开发者\u名称)
email.set(POM\u开发者\u电子邮件)
}
}
供应链管理{
连接.设置(POM\U SCM\U连接)
developerConnection.set(POM\u SCM\u DEV\u连接)
url.set(POM\u SCM\u url)
}
}
}
}
}
我对此很满意,但当涉及到自动增加
版本时,我可能会退回到
gradle.properties中维护它


编辑:
不再需要(并且允许)将
buildSrc
添加到
settings.gradle.kts
,相反,如果存在,它将自动拾取。

回答@s1m0nw1注释(注释太长): 不,您不能在buildSrc/build.gradle中使用buildSrc/src内容。我在编写基于android的插件时遇到了这个问题,我需要在buildsSrc中使用android gradle插件依赖项,但我也在project中声明了这个依赖项。所以我有两个不同的地方和两个版本要维护

我通过在buildSrc目录中创建gradle.properties文件解决了这个问题。 我在其中创建了prop
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()
道具的Util:

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")
} 

buildSrc
中定义常量时,我是否也可以在
buildSrc
本身的build.gradle.kts中使用它们?注意:kotlin版本常量是gradle kotlin DSL的一部分。使用示例:
实现(embeddedKotlin(“stdlib-jdk7”))
类路径(embeddedKotlin(“gradle插件”)
buildSrc确实是一个好地方,gradle正式支持这种方式。kotlin版本常量是gradle kotlin DSL的一部分。用法示例:
implementation(embeddedKotlin(“stdlib-jdk7”))
classpath(embeddedKotlin(“gradle插件”)
您可以从KotlinCompilerVersion.version获取版本。为此,我仍然必须在buildSrc/gradle.properties和rootPr中复制属性定义