在Gradle Kotlin DSL中,无法识别buildscript中的ext。

88
这些天,我正在尝试编写一些代码来体验Spring 5中的响应式特性和Kotlin扩展,并且我还准备了一个gradle Kotlin DSL build.gradle.kt来配置gradle构建。
build.gradle.kt是从http://start.spring.io生成的Spring Boot模板代码转换而来。
但是在buildscript中的ext无法被Gradle检测到。
buildscript {
  ext { }
}

ext会导致Gradle构建错误。

为了使classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion")compile("org.jetbrains.kotlin:kotlin-stdlib-jre8:$kotlinVersion")中的变量生效,我以困难的方式添加了这些变量。

val kotlinVersion = "1.1.4"
val springBootVersion = "2.0.0.M3"

但是我必须在全局顶级位置声明它们,并在buildscript中复制它们。
代码:https://github.com/hantsy/spring-reactive-sample/blob/master/kotlin-gradle/build.gradle.kts 有没有一种优雅的方法使ext起作用?
更新:有一些不太好看的方法:
从Gradle Kotlin DSL示例https://github.com/gradle/kotlin-dsl/tree/master/samples/project-properties中,声明了gradel.properties中的属性。
kotlinVersion = 1.1.4 springBootVersion = 2.0.0.M3
并在build.gradle.kts中使用它。
buildScript{ val kotlinVersion by project
} val kotlinVersion by project //另一个在buildscript块之外声明的属性。
与上述类似,在buildScript块中声明它们:
buildScript{ extra["kotlinVersion"] = "1.1.4" extra["springBootVersion"] = "2.0.0.M3" val kotlinVersion: String by extra
} val kotlinVersion: String by extra //另一个在buildscript块之外声明的属性。

我怎样避免val kotlinVersion: String by extra的重复?

更新(2023-7-5):最新的Gradle支持使用libs.versions.toml文件在一个集中的位置声明依赖版本,它也可以被GitHub dependabot识别。详情请参见:https://docs.gradle.org/current/userguide/platforms.html


1
我不知道如何避免重复,但你可以将以下代码合并:extra["kotlinVersion"] = "1.1.4" val kotlinVersion: String by extra变成val kotlinVersion: String by extra("1.1.4") - Claus Holst
@ClausHolst 非常清晰明了的解释! - neu242
11个回答

55

使用Kotlin DSL时,ext已更改为extra,并且可以在buildscript下使用。

例如:

buildscript {
    // Define versions in a single place
    extra.apply{
        set("minSdkVersion", 26)
        set("targetSdkVersion", 27)
    }
}

2
如果我想向extras对象添加一个函数,应该如何操作? - Squeazer
4
你能否举个例子说明如何使用这个属性?仅仅使用 implementation("org.library:library:$myVersion") 是行不通的。 - Jorn
2
很遗憾,在buildscript中它对我不起作用。 - Sir Codesalot
2
读取额外属性:val myVersion: String by rootProject.extra implementation("org.library:library:$myVersion") - sylwano
2
这绝不比使用 Groovy 更容易,即使它能工作... - Chapz
显示剩余3条评论

33

可以在.gradle.kts文件中使用在.kt文件中定义的常量。

在项目的根文件夹中创建buildSrc文件夹。

创建buildSrc/build.gradle.kts文件,其中包含以下内容。

plugins {
    `kotlin-dsl`
}

repositories {
    mavenCentral()
}

创建文件 buildSrc/src/main/kotlin/Constants.kt,内容如下:

object Constants {
    const val kotlinVersion = "1.3.70"
    const val targetSdkVersion = 28
}

同步。现在,您可以像这样在各种.gradle.kts文件中引用创建的常量。

...
classpath(kotlin("gradle-plugin", version = Constants.kotlinVersion))
...

...
targetSdkVersion(Constants.targetSdkVersion)
...

这个功能非常完美,即使是多模块项目也可以无缝运行,并且不需要在构建脚本中编写丑陋的代码。太棒了! - Thorbear
1
@EmilKantis,buildSrc 的工作原理类似于 Gradle 插件,会自动应用于所有子项目,因此您要做的是创建一个 Gradle 插件。 :) - vaughandroid
1
我对此最大的问题是,旧版本Gradle文件中由 ext 定义的版本可以与例如 Android Studio 中的新版本库的 Lint 检查器配合使用,但这些常量文件不起作用,因此您不知道某些内容是否有更新的版本可用(如果您想知道)。 - Meetarp
但这不仅仅是关于依赖项的常量。那么模块之间的共享配置呢?以前我们可以在每个build.gradle中包含带有ext { android { ... } }config_module.gradle。现在该怎么做呢? - user924
@EugenePopovich,他们要求设置"com.android.application"或"com.android.library"以便可以看到"android"范围,这不是很好,因为以前我有一个通用的"common_config.gradle"适用于所有模块(无论是应用程序还是库)。 - user924
显示剩余4条评论

22
在我的工作中,我发现使用allprojects中的ext而不是buildscript对我很有帮助。所以,在您的顶级build.gradle.kts中,请使用以下代码:
allprojects {
  ext {
    set("supportLibraryVersion", "26.0.1")
  }
}

然后你可以在像这样的模块的build.gradle.kts文件中使用它:

val supportLibraryVersion = ext.get("supportLibraryVersion") as String

11
或稍微简洁一些:val supportLibraryVersion: String? by ext 意思是:将 supportLibraryVersion 声明为一个可空的字符串类型,并通过扩展属性委托实现。 - PaulNUK
2
这甚至不能编译。 - IgorGanapolsky
1
错误且不美观,应该是https://github.com/google/iosched/tree/main/buildSrc/src/main/java。 - user924
1
@user924 哦,是的,为了拥有常量而添加一个额外的Gradle模块,导致一切都变慢了。 - Nino DELCEY
@NinoDELCEY 这是官方的 Google 方式,至少看起来很正常。 - user924
显示剩余4条评论

21

对我来说,这些答案都不够清晰明了。所以这是我的解释:

/build.gradle.kts

buildscript {
    extra.apply {
        set("compose_version", "1.0.3")
    }
    ...
}

/app/build.gradle.kts:

val composeVersion = rootProject.extra["compose_version"]
implementation("androidx.compose.ui:ui:$composeVersion")
implementation("androidx.compose.material:material:$composeVersion")

16

有一个在 Kotlin 中可以使用的新可能性:

object DependencyVersions {
    const val JETTY_VERSION = "9.4.12.v20180830"
}

dependencies{
    implementation("org.eclipse.jetty:jettyserver:${DependencyVersions.JETTY_VERSION}")
}

在这里,DependencyVersions是我选择的名称。您可以选择另一个名称,例如“ MyProjectVariables”。这是避免使用extra或ext属性的一种方式。


我认为使用伴生对象会更符合 Kotlin 的惯用风格。 - Matt Kerr
4
完全不需要,如果你需要一个单例,应该使用 object - Joffrey
1
你能在子项目中引用它吗? - Thorbear

6

kotlin-gradle-dsl 中的全局属性:
https://stackoverflow.com/a/53594357/3557894


Kotlin 版本嵌入了 kotlin-gradle-dsl。
您可以使用嵌入版本依赖项,如下所示:

implementation(embeddedKotlin("stdlib-jdk7"))

classpath(embeddedKotlin("gradle-plugin"))

1
新增的方式是添加到插件:kotlin(“jvm”) 和依赖项:implementation(kotlin("stdlib-jdk8") - Matt Kerr

4
val junitVersion by extra("4.13.2")
testImplementation("junit:junit:$junitVersion")

3
在 Kotlin 中,实现这一点的方式是使用 by extraext 块。
使用 by extra
val kotlinVersion = "95" by extra
val kotlinCompiler = true by extra

使用ext扩展:
ext {
    set("kotlinVersion", "95")
    set("kotlinCompiler", true)
}

2

顺便说一下,从最新的代码风格开始将不起作用,只有一些零散的部分。但是,如果有人需要在.kts文件系统中处理相同的内容,可以添加一个plugins块。

/build.gradle.kts:

buildscript {
    extra.apply {
        set("compose_ui_version", "1.2.0")
    }
}// Top-level build file where you can add configuration options common to all sub-projects/modules.

plugins {
    id("com.android.application") version "7.4.0" apply false
    id("com.android.library") version "7.4.0" apply false
    id("org.jetbrains.kotlin.android") version "1.7.0" apply false
}

/app/build.gradle.kts:

dependencies {
    val composeUiVersion = rootProject.extra["compose_ui_version"]
    implementation("androidx.compose.ui:ui:$composeUiVersion")
    implementation("androidx.compose.ui:ui-tooling-preview:$composeUiVersion")
    androidTestImplementation ("androidx.compose.ui:ui-test-junit4:$composeUiVersion")
    debugImplementation ("androidx.compose.ui:ui-tooling:$composeUiVersion")
    debugImplementation ("androidx.compose.ui:ui-test-manifest:$composeUiVersion")
}

1

设置为这样:

val kotlinVersion by extra("1.1.4")

使用方法如下:

val kotlinVersion: String by rootProject.extra

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接