什么时候应该应用 dependsOn?
简而言之,Gradle 通过计算工作依赖关系图来工作。假如您要构建一个 JAR 文件:您要调用 jar 工作,而 Gradle 将确定构建 jar,它须要编译类、解决资源等……确定工作依赖项,也就是说还须要执行哪些其余工作,是通过查看 3 个不同的货色来实现的:
工作取决于依赖项。例如,assemble.dependsOn(jar) 示意如果运行 assemble,那么 jar 工作必须先执行
工作传递依赖关系,在这种状况下,咱们不是在议论工作,而是在议论“出版物”。例如,当你须要编译我的项目 A 时,你须要在 classpath 我的项目 B 上,这意味着运行 B 的一些工作。最初但并非最不重要的是,工作输出,也就是说,它须要什么来执行它的工作
看看上面的代码:[图片上传失败 …(image-afd61c-1648820700726)]
用与其余构建工具(如 Maven 或 Ant)雷同的形式思考是很迷人的,尤其是当您不习惯 Gradle 时。你在想“有一个工作,jar,它基本上将它在 classes/groovy/main 中找到的所有内容打包,所以如果我想在 jar 工作中增加更多内容,让咱们在 classes/groovy/main
中增加更多内容”.
因为不同的起因,这是谬误的,最显著的是:
当 docsFilesJar 工作将被执行时,它会向“classes”目录奉献更多文件,然而,等等,那些不是咱们放在那里的类,对吧?它只是一个罐子,资源。咱们不应该改用 resources/groovy/main 吗?或者是 classes/groovy/resources?要不然是啥?好吧,你不应该关怀,因为你不关怀 Java 编译工作将其输入放在哪里!
它毁坏了可缓存性:Gradle 有一个构建缓存,多个工作奉献于同一个输入目录是毁坏缓存的典型示例。事实上,它突破了各种最新的查看,也就是说,Gradle 可能了解它不须要在没有任何变动的状况下执行工作。
它对 Gradle 是不通明的:下面的代码在 doLast 块中执行一个正本。没有什么能通知 Gradle“类”有额定的输入。
设想另一个只须要类的工作。依据它执行的工夫,它可能蕴含也可能不蕴含它不关怀的 docsFileJar。这使得构建不可重现(请留神,这正是 Maven 构建不可信并且您须要运行洁净的起因,因为任何“指标”能够随时写入任何目录,因而无奈推断谁奉献了什么)。
它须要申明 jar 工作和 docsFileJar 工作之间的显式依赖关系,以确保如果咱们执行 jar,咱们的“docs jar”文件存在
它没有阐明为什么会有依赖关系:是因为你想订购货色,还是因为你须要依赖工作产生的工件?还有什么?
很容易遗记这些:因为您可能常常运行构建,您可能认为您的构建工作,因为 jar 是工作图的一部分,并且偶尔地,docsFileJar 会在之前执行
它会产生意外的额定工作:大多数状况下,dependsOn 会触发过多的工作。Gradle 是一个智能构建工具,它能够准确计算每个特定工作须要执行的内容。通过应用 dependsOn,你有点像应用锤子并强制它在图中整合一些不必要的货色。简而言之:你做的工作太多了。
很难解脱它们:当您看到 dependsOn 时,因为它没有阐明为什么须要它,因而在优化构建时通常很难解脱这种依赖关系
改用隐式依赖!
咱们的问题的答案实际上更容易推理:颠倒逻辑。与其想“我应该把这些货色放在哪里,以便被 jar 拾取”,不如想想“让咱们通知 jar 工作它也须要拾取我的资源”。
总而言之,这是对于正确申明您的工作输出。
与其修补另一个工作的输入(说真的,遗记这个!),每个工作都必须被认为是一个承受输出并产生输入的函数:它是隔离的。那么,咱们的 docsFileJar 的输出是什么?咱们要打包的资源。它的输入是什么?罐子自身。没有对于咱们应该把罐子放在哪里的问题,咱们让 Gradle 为咱们抉择了一个正当的中央。
那么 jar 工作自身的输出是什么?好吧,这是惯例输出加上咱们的 jar。它更容易推理,而且作为处分,它甚至更短!
因而,让咱们将下面的代码重写为:
您看得出来差异吗?咱们解脱了 docFilesJar 工作中的正本,咱们不想这样做。相同,咱们想要的是说“当你构建 jar 时,还要抉择这个 docsFileJar。这就是咱们通过 docsFileJar 通知咱们正在做的事件。Gradle 足够聪慧,晓得它什么时候须要执行 jar 工作,首先,它须要构建 docsFilesJar。
这样做有几个长处:
- 依赖变得隐含:如果咱们不想再蕴含 jar,咱们只需将其从输出标准中删除即可。
- 它不会净化其余工作的输入
- 能够独立于 jar 执行 docsFileJar
- 总而言之,这是为了将事物彼此隔离并升高意外毁坏构建的危险!
下面的代码能够工作,但它有一个毛病:即便咱们调用不须要的货色,docFilesJar 和 jar 工作也会被配置(实例化)。例如,假如您调用 gradle compileJava:没有理由在那里配置 jar 工作,因为咱们不会执行它们。
作为论断:
尽可能防止应用显式的 dependsOn
我偏向于说 dependsOn 惟一正当的用例是生命周期工作(生命周期工作是指标只是“组织构建”的工作,例如构建,组装,查看:他们本人不做任何事件,他们只是将一些家属绑定在一起)
如果您发现用例不是生命周期工作并且不能通过隐式工作依赖项来表白(例如申明输出而不是依赖项),则将其报告给 Gradle 团队