【问题标题】:Mixed Groovy/Kotlin DSL multiproject build, How can Kotlin read ext variables混合 Groovy/Kotlin DSL 多项目构建,Kotlin 如何读取 ext 变量
【发布时间】:2022-01-12 17:28:33
【问题描述】:

我正在探索将我们基于 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")!!);

【问题讨论】:

    标签: java kotlin gradle groovy


    【解决方案1】:

    你可以在 kotlin 脚本中使用它

    plugins {
        java
    }
    
    val libraries: Map<String, String> by rootProject.extra
    
    repositories {
        mavenCentral()
    }
    
    dependencies {
        implementation(libraries["shared"]!!)
    }
    

    编辑

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

    为此,您可以从根项目中删除您的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 在 cmets 中的问题,并显示了另一种选择

    是的,我们可以像这样在根项目的 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"))
    }
    

    【讨论】:

    • 干净的答案。 :) 而不是libraries["shared"]!! 像我这样希望避免双重爆炸的人(!!)也可以使用libraries.getValue("shared")
    • 我喜欢。我希望有一个内置的 API,但这更明确地说明了这些来自哪里,我很感激。
    • 在项目顶层的build.gradle 中定义变量时是否有效(老实说,我不知道)?
    • @JeffScottBrown 在 Gradle 7 中添加了一些关于预览版目录功能的信息。如果您问的是原始问题,那么只要在 extra 中定义了值(ext in Groovy)在顶级脚本中,是的,这就是您可以从子模块中获得它的方式......我有一种感觉我不是 100% 理解这个问题:-(
    猜你喜欢
    • 2018-02-17
    • 1970-01-01
    • 1970-01-01
    • 2020-07-29
    • 1970-01-01
    • 1970-01-01
    • 2022-10-14
    • 2019-04-06
    • 1970-01-01
    相关资源
    最近更新 更多