【问题标题】:How to append a Gradle Task without using `dependsOn`?如何在不使用“dependsOn”的情况下附加 Gradle 任务?
【发布时间】:2026-01-08 13:10:02
【问题描述】:

我正在使用 Gradle 构建一个涉及本机库的 Java 项目。我有一个任务jniHeaders 定义:

jniHeaders.dependsOn classes

所以当我输入gradle jniHeaders 时,它将编译Java 类并生成JNI 标头。到目前为止一切顺利。

但我觉得输入gradle jniHeaders 不是很自然。在 99% 的情况下,如果您成功编译 Java 类,您也希望生成 JNI 标头。如果我可以 gradle classes 一步编译 Java 类并生成 JNI 头文件,那就太好了。

换句话说,我想将任务jniHeaders添加到任务classes的末尾,但前提是classes已成功完成并且确实做了一些工作。

classes.doLast 浮现在脑海中,但我无法告诉它执行另一个任务。 classes.finalizedBy jniHeaders 在一定程度上起作用,但不管classes 的结果如何,都会生成 JNI 标头。我想我可以添加一些 Groovy 逻辑来获得我想要的确切行为,但我也怀疑一定有更简单的方法。

有人有什么建议吗?

【问题讨论】:

  • 是不是只是调用一个看似随意的任务的概念让你烦恼?我可能很想定义另一个任务allTheThings(或其他任何东西!),它只依赖于classesjniHeaders。这似乎比必须添加精品构建逻辑简单得多:)

标签: java gradle groovy java-native-interface


【解决方案1】:

将构建建模为任务图的全部意义在于有一个简单而强大的执行模型。我建议你创建一个函数compileJNIHeaders() 并将它放在Gradle 可以访问它的地方(build.gradle 本身以及buildSrc/src/main/groovy),这样你就可以轻松地开发和测试它。

这个函数可以在最合适的步骤中执行:

  • classes.doFirst(如果标头用于您自己的代码)
  • classes.doLast(如果标头用于依赖项目)
  • 放入一个任务 compileJNIHeaders,它是您用来将项目打包成部署格式的任务的依赖项

【讨论】:

  • 谢谢。我太忙于操作依赖图,忘记了最简单的模块化方法。
【解决方案2】:

您的问题分为两部分:

  1. 在java类编译成功后添加任务jniHeaders执行。
  2. 仅在完成任何工作后才执行jniHeaders 任务。

由于classes 任务是processResourcescompileJava 的集合(参见java plugin doc),我认为最好挂钩到compileJava 任务。正如您发现的那样,这可以通过finalizedBy 完成。此外,如果没有完成任何工作,您需要跳过该任务,例如通过将onlyIf 语句添加到您的jniHeaders 任务。

例子:

task jniHeaders {
    onlyIf { !sourceSets.main.allJava.empty }
    doLast {
        println "GENERATE JNI HEADERS for $project.name"
    }
}
compileJava.finalizedBy jniHeaders

【讨论】:

  • 谢谢。但是我尝试了您的代码,但它并没有真正按预期工作。即使compileJava 失败,jniHeader 仍然会被执行,因为大概allJava 不为空! (我没有从干净的构建目录开始)无论如何,我采用了@Raffaele 的解决方案。谢谢你的建议。
最近更新 更多