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

Mixed Groovy/Kotlin DSL multiproject build, How can Kotlin read ext variables

我正在探索将我们的 Groovy 基于 DSL 的构建文件转换为 Kotlin,并希望逐步执行此操作。但是,我无法弄清楚如何在子项目 build.gradle.kts.

中读取顶层 build.gradle 中设置的 ext 变量

我的实验库可用here

它有这样的布局:

.
├── README.md
├── build.gradle
├── gradle
│   └── wrapper
│       ├── gradle-wrapper.jar
│       └── gradle-wrapper.properties
├── gradlew
├── groovy
│   └── build.gradle
├── kts
│   ├── build.gradle.kts
│   └── src
│       └── main
│           └── java
│               └── xyz
│                   └── abc
│                       └── def
│                           └── Main.java
└── settings.gradle

顶层文件定义了一个 ext 变量,其中包含像这样的通用库版本:

plugins {
    id("java")
}

ext.libraries = [ shared: "xyz.abc.def:art:1.2" ]

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

的依赖
╰─➤  cat groovy/build.gradle 
plugins {
    id("java")
}

dependencies {
    implementation(libraries.shared)
}

╰─➤  cat kts/build.gradle.kts 
plugins {
    id("java")
}

dependencies {
    implementation(libraries.shared)
}

settings.gradle 包括两个项目。

╰─➤  cat settings.gradle 
include "groovy"
include "kts"

当我 运行 ./gradlew projects 我得到这个错误:

  Line 6:     implementation(libraries.shared)
                             ^ Unresolved reference: libraries

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

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

编辑:

在 Gradle API 文档中仔细研究后,我想到了这个,它有效但绝对可怕。

implementation((project.getParent()!!.extra.properties["libraries"]!! as HashMap<String, String>).get("shared")!!);

您可以在 kotlin 脚本中使用它

plugins {
    java
}

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

repositories {
    mavenCentral()
}

dependencies {
    implementation(libraries["shared"]!!)
}

编辑

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

为此,您可以从根项目中删除 ext.libraries,并在 settings.gradle

中用它替换
enableFeaturePreview('VERSION_CATALOGS')

dependencyResolutionManagement {
    versionCatalogs {
        libs {
            alias('shared').to('com.bloidonia:ascii-image:1.1')
        }
    }
}

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

    implementation(libs.shared)

编辑 2 -- 喝咖啡后

啊哈,所以我认为这回答了 Jeff 在评论中的问题,并显示了替代方案

是的,我们可以像这样在根项目中添加一个 ext 函数:

ext.libraries = [ shared: "com.bloidonia:ascii-image:1.1" ]
ext.library = { String name ->
    ext.libraries."$name"
}

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

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

dependencies {
    implementation(library("shared"))
}