混合 Groovy/Kotlin DSL 多项目构建,Kotlin 如何读取 ext 变量

asm*_*asm 6 java groovy gradle kotlin

我正在探索将基于 Groovy DSL 的构建文件转换为 Kotlin,并希望逐步完成此操作。但是,我不知道如何读取子项目ext顶层设置的变量。build.gradlebuild.gradle.kts

\n

我的实验存储库可以在这里找到

\n

它有这样的布局:

\n
.\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 README.md\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 build.gradle\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 gradle\n\xe2\x94\x82\xc2\xa0\xc2\xa0 \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 wrapper\n\xe2\x94\x82\xc2\xa0\xc2\xa0     \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 gradle-wrapper.jar\n\xe2\x94\x82\xc2\xa0\xc2\xa0     \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 gradle-wrapper.properties\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 gradlew\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 groovy\n\xe2\x94\x82\xc2\xa0\xc2\xa0 \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 build.gradle\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 kts\n\xe2\x94\x82\xc2\xa0\xc2\xa0 \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 build.gradle.kts\n\xe2\x94\x82\xc2\xa0\xc2\xa0 \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 src\n\xe2\x94\x82\xc2\xa0\xc2\xa0     \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 main\n\xe2\x94\x82\xc2\xa0\xc2\xa0         \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 java\n\xe2\x94\x82\xc2\xa0\xc2\xa0             \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 xyz\n\xe2\x94\x82\xc2\xa0\xc2\xa0                 \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 abc\n\xe2\x94\x82\xc2\xa0\xc2\xa0                     \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 def\n\xe2\x94\x82\xc2\xa0\xc2\xa0                         \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 Main.java\n\xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 settings.gradle\n
Run Code Online (Sandbox Code Playgroud)\n

顶层文件定义了一个ext包含公共库版本的变量,如下所示:

\n
plugins {\n    id("java")\n}\n\next.libraries = [ shared: "xyz.abc.def:art:1.2" ]\n
Run Code Online (Sandbox Code Playgroud)\n

有两个子项目,一个使用 Groovy DSL,一个使用 Kotlin DSL。他们都试图声明对libraries.shared.

\n
\xe2\x95\xb0\xe2\x94\x80\xe2\x9e\xa4  cat groovy/build.gradle \nplugins {\n    id("java")\n}\n\ndependencies {\n    implementation(libraries.shared)\n}\n\n\xe2\x95\xb0\xe2\x94\x80\xe2\x9e\xa4  cat kts/build.gradle.kts \nplugins {\n    id("java")\n}\n\ndependencies {\n    implementation(libraries.shared)\n}\n
Run Code Online (Sandbox Code Playgroud)\n

settings.gradle包括这两个项目。

\n
\xe2\x95\xb0\xe2\x94\x80\xe2\x9e\xa4  cat settings.gradle \ninclude "groovy"\ninclude "kts"\n
Run Code Online (Sandbox Code Playgroud)\n

当我运行时,./gradlew projects我收到此错误:

\n
  Line 6:     implementation(libraries.shared)\n                             ^ Unresolved reference: libraries\n
Run Code Online (Sandbox Code Playgroud)\n

当子项目的包含kts被注释掉时,它就会成功,并显示groovy子项目。

\n

我已经尝试了许多不同的方法来引用libraries,例如project.extraextra,但到目前为止还没有找到任何有效的方法。

\n

编辑:

\n

在深入研究 Gradle API 文档后,我想出了这个,它可以工作,但绝对是可怕的。

\n
.\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 README.md\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 build.gradle\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 gradle\n\xe2\x94\x82\xc2\xa0\xc2\xa0 \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 wrapper\n\xe2\x94\x82\xc2\xa0\xc2\xa0     \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 gradle-wrapper.jar\n\xe2\x94\x82\xc2\xa0\xc2\xa0     \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 gradle-wrapper.properties\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 gradlew\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 groovy\n\xe2\x94\x82\xc2\xa0\xc2\xa0 \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 build.gradle\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 kts\n\xe2\x94\x82\xc2\xa0\xc2\xa0 \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 build.gradle.kts\n\xe2\x94\x82\xc2\xa0\xc2\xa0 \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 src\n\xe2\x94\x82\xc2\xa0\xc2\xa0     \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 main\n\xe2\x94\x82\xc2\xa0\xc2\xa0         \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 java\n\xe2\x94\x82\xc2\xa0\xc2\xa0             \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 xyz\n\xe2\x94\x82\xc2\xa0\xc2\xa0                 \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 abc\n\xe2\x94\x82\xc2\xa0\xc2\xa0                     \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 def\n\xe2\x94\x82\xc2\xa0\xc2\xa0                         \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 Main.java\n\xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 settings.gradle\n
Run Code Online (Sandbox Code Playgroud)\n

tim*_*tes 5

您可以在 kotlin 脚本中使用它

plugins {
    java
}

val libraries: Map<String, String> by rootProject.extra

repositories {
    mavenCentral()
}

dependencies {
    implementation(libraries["shared"]!!)
}
Run Code Online (Sandbox Code Playgroud)

编辑

如果您使用的是 Gradle 的当前版本(撰写本文时为 7),您可以尝试新版本的目录功能——在撰写本文时该功能处于预览状态,因此可能会是一条崎岖的道路...

为此,您可以ext.libraries从根项目中删除您的项目,并将其替换为settings.gradle

enableFeaturePreview('VERSION_CATALOGS')

dependencyResolutionManagement {
    versionCatalogs {
        libs {
            alias('shared').to('com.bloidonia:ascii-image:1.1')
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

然后在 Groovy 和 Kotlin DSL 构建脚本中,您可以通过以下方式引用这些依赖项:

    implementation(libs.shared)
Run Code Online (Sandbox Code Playgroud)

编辑2——喝完咖啡后

啊,所以我认为这回答了杰夫在评论中的问题,并展示了另一种选择

是的,我们可以在根项目中向 ext 添加一个函数,如下所示:

ext.libraries = [ shared: "com.bloidonia:ascii-image:1.1" ]
ext.library = { String name ->
    ext.libraries."$name"
}
Run Code Online (Sandbox Code Playgroud)

然后在Kotlin项目中,我们可以这样做:

val library: groovy.lang.Closure<String> by rootProject.extra

dependencies {
    implementation(library("shared"))
}
Run Code Online (Sandbox Code Playgroud)