Gradle Kotlin DSL:在独特的地方定义 Kotlin 版本

问题描述 投票:0回答:8

为了描述 Gradle 构建脚本,我们可以通过

build.gradle.kts
文件使用 Kotlin。全局定义要使用的 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 限制,无法从
pluginVersion
块外部访问
plugins
或从
dependencyVersion
块内访问
plugins

如何将版本字符串

"1.2.30"
提取到一个地方?

gradle kotlin build.gradle gradle-kotlin-dsl
8个回答
37
投票

在 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
    

34
投票

我刚刚偶然发现在我的

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://[email protected]/${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 = "[email protected]"

还有一个

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
,相反,如果存在,它将自动被拾取。


8
投票

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

import org.jetbrains.kotlin.gradle.plugin.KotlinPluginWrapper

plugins {
    kotlin("jvm") version "1.2.0"
}

val kotlinVersion = plugins.getPlugin(KotlinPluginWrapper::class.java).kotlinPluginVersion

3
投票

一旦您为 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}")

2
投票

有一种解决方法可用,它搜索为 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
中使用变量
dependencies
,而无需再遇到任何麻烦。


2
投票

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

2
投票

简单快速的解决方法:

buildscript 部分将值设置为 system property:

buildscript {   
   val version = "X.X.X"
   System.setProperty("version", version)
}

plugins 部分获取此属性:

plugins {
    val version = System.getProperty("version")
}

0
投票

Plugins 是一个特殊的块,您无法从 gradle.properties 访问变量,但您可以在 settings.gradle.kts:

中指定该版本
// build.gradle.kts
plugins {
    id("io.freefair.lombok")
}


// settings.gradle.kts
pluginManagement {
    val lombokVersion: String by settings
    
    plugins {
        id("io.freefair.lombok") version lombokVersion
    }
}


// gradle.properties
lombokVersion=8.10
© www.soinside.com 2019 - 2024. All rights reserved.