正如奥利弗已经说过的,你需要将控制台输出到doFirst
or doLast
闭包,否则它将在定义任务时执行(期间配置阶段).
该异常是由于扩展属性和任务都添加到了范围中而引起的Project https://docs.gradle.org/current/javadoc/org/gradle/api/Project.html对象,但如果扩展属性和任务具有相同的名称(scalafmt
在这种情况下)存在,将访问扩展属性。正如错误消息告诉您的那样,您正在尝试访问shouldRunAfter
类型对象上的方法PluginExtension
,它不存在的地方。您需要确保访问该任务:
tasks['scalafmt'].shouldRunAfter build
Update
实际上,我认为你只需要解决两个具体问题,但你的基本 Gradle 结构已经有了一个解决方案。
首先,两者shouldRunAfter
and mustRunAfter
实际上并不导致任务被执行,它们仅定义顺序if这两个任务都被执行(由命令行或任务依赖性引起)。这就是任务的原因clean
, scalafmt
, shadowJar
乃至fizzbuzz
如果您调用,则不会执行gradle build
。所以,为了解决你的第一个问题,你可以让build
您显式调用的任务取决于它们:
build.dependsOn 'clean', 'scalafmt', 'shadowJar', 'fizzbuzz'
但是任务依赖关系总是在父任务之前运行,因此所有任务都将在父任务之前执行build
任务。这应该不是问题,因为build
任务只不过是收集所有必需的构建步骤的任务依赖关系。您还需要不仅定义任务依赖项之间的顺序,例如clean
和父任务build
,但主要是在现有的任务依赖关系之间,例如compileJava
。否则clean
可以追赶compileJava
,这将删除编译的文件。
另一种选择是定义一个新任务,该任务取决于您要执行的所有任务:
task fullBuild {
dependsOn 'clean', 'build', 'scalafmt', 'shadowJar', 'fizzbuzz'
}
这仍然需要定义任务和现有任务依赖项之间的顺序,例如
compileJava.mustRunAfter 'clean'
[...]
请注意,现在您必须致电gradle fullBuild
从命令行。如果你真的只需要打电话gradle build
通过命令行并仍然执行一些任务after实际上build
任务,你可以在你的任务中使用一个小技巧settings.gradle
file:
startParameter.with {
if (taskNames == ['build']) {
taskNames = ['clean', 'build', 'scalafmt', 'shadowJar', 'fizzbuzz']
}
}
这段代码检查您通过命令行输入的任务名称并替换它,如果它只包含build
任务。这样您就不必为任务顺序而烦恼,因为命令行任务是连续执行的。
然而,这不是一个干净的解决方案。一个好的解决方案将包括所有任务的任务依赖关系的定义really相互依赖以及通过命令行调用多个任务(您希望避免这种情况)。尤其是之间的硬连接clean
和build
任务绕过了 Gradle 平台的许多有用功能,例如增量构建。
关于更新中的第二点,错误的是fizzbuzz
任务首先运行。它根本没有运行。配置任务时会打印命令行输出。请移动println
打电话给doFirst
/ doLast
关闭:
task fizzbuzz {
doFirst {
println "Fizzbuzz!"
}
}