2

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

使用 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).

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

我不想求助于需要了解包含的构建的底层结构来连接它。那将是不可持续的。我究竟做错了什么?

4

2 回答 2

1

我正在使用以下代码来实现这一点。首先,在根目录中创建一个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在所有包含的构建上执行任务。

于 2021-09-14T14:33:28.723 回答
0

好的,不知道发生了什么以及为什么其他方法不起作用,但我找到了一种有效的方法,并且不需要我制造依赖于生命周期任务的合成任务。

复合 rootproject build.gradle.kts 任务与原始问题中所述保持相同:

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-es 中的任务声明需要通过以下方式收集和依赖任务:

tasks {
    val buildAll: GradleBuild by creating {
        dependsOn(getTasksByName("build", true))
    }

    val cleanAll: Delete by creating {
        dependsOn(getTasksByName("clean", true))
    }
}

这将递归地收集任务。尽管我以前遍历所有子项目的技术也应该可以解决问题,因为子项目包含所有子项目,但由于某种原因它不起作用。这是虽然!希望这对其他人有所帮助。

于 2018-08-09T17:49:49.830 回答