gradle - 使用 Gradle Kotlin DSL 在复合包含构建中模拟多项目执行?

标签 gradle kotlin composite gradle-kotlin-dsl

我正在简化设置,我必须说明我的问题,但也包括了结构的复杂性。

使用 Gradle 的 Kotlin DSL 我有一个复合构建,其中根项目为空,并且两个包含的构建都是并行的多项目构建,具有不同的结构,这些结构利用“容器”项目(也称为空目录,没有build.gradle.kts 文件)用于组织目的。

.
├── app
│   ├── common
│   │   └── build.gradle.kts
│   ├── js
│   │   └── build.gradle.kts
│   ├── jvm
│   │   └── build.gradle.kts
│   ├── build.gradle.kts
│   └── settings.gradle.kts
├── library
│   ├── core
│   │   ├── common
│   │   │   └── build.gradle.kts
│   │   ├── js
│   │   │   └── build.gradle.kts
│   │   └── jvm
│   │       └── build.gradle.kts
│   ├── other-component
│   │   ├── common
│   │   │   └── build.gradle.kts
│   │   ├── js
│   │   │   └── build.gradle.kts
│   │   └── jvm
│   │       └── build.gradle.kts
│   ├── util
│   │   ├── util1
│   │   │   ├── common
│   │   │   │   └── build.gradle.kts
│   │   │   ├── js
│   │   │   │   └── build.gradle.kts
│   │   │   └── jvm
│   │   │       └── build.gradle.kts
│   │   └── util2
│   │       ├── common
│   │       │   └── build.gradle.kts
│   │       ├── js
│   │       │   └── build.gradle.kts
│   │       └── jvm
│   │           └── build.gradle.kts
│   ├── build.gradle.kts
│   └── settings.gradle.kts
├── build.gradle.kts
└── settings.gradle.kts

我的愿望是能够在 IDE (Intellij) 内的根复合项目中运行构建,并且它模仿多项目执行的行为,其中该项目下的所有内容依次执行任务。

在 Groovy 中,只需在复合项目中的includedBuilds*.tasks* 上使用扩展运算符即可将其连接起来,但在 Kotlin DSL 中,我们只能访问任务,这是一个单一的 TaskReference,无法访问获取任务集合(TaskCollection 或任务集合)或任务引用集合。

因此,在复合 build.gradle.kts 的 rootProject 中,我有:

tasks {
    val clean by getting {
        gradle.includedBuilds.forEach { this.dependsOn(it.task(":cleanAll")) }
    }

    val build by getting {
        gradle.includedBuilds.forEach { this.dependsOn(it.task(":buildAll")) }
    }
}

然后在其中一个包含的构建 build.gradle.kts 文件中,我尝试以两种不同的方式连接它们(很多,但这是两种方法):

// Variation 1
tasks {
    val buildAll : GradleBuild by creating {
        this.dependsOn(tasks.getByPath(":build"))
    }

    val cleanAll : Delete by creating {
        this.dependsOn(tasks.getByPath(":clean"))
    }
}

// Variation 2
tasks {
    val buildAll: GradleBuild by creating {
        subprojects.forEach {
            this.dependsOn(it.tasks.getByPath(":build"))
        }
    }

    val cleanAll: Delete by creating {
        subprojects.forEach {
            this.dependsOn(it.tasks.getByPath(":clean"))
        }
    }
}

// Variation 2.b
tasks {
    val buildAll: GradleBuild by creating {
        this.dependsOn(subprojects.mapNotNull(it.tasks.getByPath(":build")))
    }

    val cleanAll: Delete by creating {
        this.dependsOn(subprojects.mapNotNull(it.tasks.getByPath(":clean")))
    }
}

// I even used different ways to try and get the tasks such as it.tasks["root:library:build"], it.tasks[":library:build"], and it.tasks["library:build"] since I know that the included builds are executed in an isolated fashion.  None of these worked
// The result was when I used absolute paths, gradle spat back that these tasks didn't exist (I assumed because they were lifecycle tasks).

基本上,尝试上述变体仅构建并清理了所包含构建的根项目,而不是子项目。这是一个错误吗?

我不想求助于所包含构建的底层结构的知识来连接它。那将是不可持续的。我做错了什么?

最佳答案

我使用以下代码来实现此目的。首先,创建一个settings.gradle.kts在以编程方式搜索构建的根目录中包含:

rootDir.walk().filter {
    it != rootDir && !it.name.startsWith(".") && it.resolve("build.gradle.kts").isFile
}.forEach(::includeBuild)

然后创建一个build.gradle.kts根目录中的文件,“转发”所有形式 all<TASK> 的根任务调用至<INCLUDED_BUILD>:<TASK> :

tasks.addRule("Pattern: all<TASK>") {
    val taskName = this
    val taskPrefix = "all"

    if (startsWith(taskPrefix)) {
        task(taskName) {
            gradle.includedBuilds.forEach { build ->
                val buildTaskName = taskName.removePrefix(taskPrefix).decapitalize()
                dependsOn(build.task(":$buildTaskName"))
            }
        }
    }
}

这样,运行./gradlew allAssemble在根项目上将有效执行assemble所有包含的构建上的任务。

关于gradle - 使用 Gradle Kotlin DSL 在复合包含构建中模拟多项目执行?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51756055/

相关文章:

android - Gradle 构建生成的变量而不是字符串值

android - 在按钮上同时使用 setOnTouchListener 和 setOnClickListener

kotlin - java.lang.IllegalStateException : KoinApplication has not been started

crop - 在同一命令中进行 graphicsmagick 合成和裁剪

java - Java:如何将控制台输出用于条件语句

svn - 在Gradle中自动执行VM

android - 找不到 com.google.gms :google-services:4. 1.0

java - 如何使用 SpannableString 更改行间距?

c# - 复合 Web 客户端指南

iphone - 我可以在 Objective-C 中调用复合的 super 方法吗