gradle的buildSrc文件夹的目的是什么?

45
在gradle中,使用一个顶层的buildSrc文件与仅使用典型的Java项目布局(src/main/java)相比有何用途?
如果我有以下布局:
src
   main
      java
或者
buildSrc
    src
       main
          java

做这样的事情会有什么不同之处(或原因)?在多模块项目中是否更有用?即使对于多模块项目,我也不能像这样做吗?

proj1
  src


proj2
  src

那么只需在与 proj1proj2 同级别的位置拥有一个顶层 build.gradle 文件即可,该文件定义了所有项目共用的设置吗?

2个回答

73

buildSrc是一个独立的构建项目,其目的是构建任何任务、插件或其他类,并打算在主要构建的构建脚本中使用,但不需要在构建之间共享。(*)这些类不能作为主要构建的一部分进行构建,因为它们必须存在于主要构建的构建脚本甚至编译/评估之前,而Gradle在执行任何工作(配置与执行阶段)之前编译/评估所有构建脚本。

与将所有构建代码放入构建脚本相比,buildSrc可以让您以更像常规代码的方式开发构建代码,如类,可以测试、导入到IDE等。即使对于更复杂的构建,这也是保持构建脚本简单和DRY的一种方法。

在多项目构建中,buildSrc更常见,因为更大的构建更可能实现自己的自定义任务和插件。

随着时间的推移,buildSrc将成长为在单个Gradle调用中执行多个依赖构建的更通用能力。

(*)在构建之间共享类是可能的,但更加复杂。特别是,您需要将类发布到存储库中,并且使用构建必须明确从那里导入它们,类似于在构建之间共享生产库时的操作。


Peter,你能帮我解决这个问题吗:https://stackoverflow.com/questions/64742632/could-not-get-unknown-property-privatedata-for-object-of-type-org-gradle-api-i - MHSaffari

11
在gradle中,使用buildSrc文件作为顶层的目的是什么,与典型的java项目布局(src/main/java)相比有何不同?
你可以绝对这样做。在gradle中,它被称为composite build,但你必须告诉Gradle去include该文件夹中的任何构建。顶级buildSrc文件夹的一个unique property是,gradle会自动将其视为一个已包含的构建。
请注意,即使buildSrc被视为复合构建,当你运行gradle.getIncludedBuilds()时,它也不会出现在包含的构建列表中。我认为原因是因为该列表是为你手动包含在settings.gradle中的构建而保留的。
为了将{{src/main/java}}包含在组合构建中,您必须使用--include-build标志运行gradle脚本,然后是src/main/java的路径。这是一个不寻常的包含构建位置,但gradle不会抱怨。
并且只需在与proj1和proj2相同级别的顶层build.gradle中定义跨项目的通用设置?
您可以在与proj1proj2子项目相同级别的位置拥有顶层build.gradle。这通常是大多数多项目项目的结构。
正如另一个答案所强调的那样,buildSrc项目的目的是创建自定义插件或任务,旨在在构建中不同的项目之间共享这并不意味着您不能在顶层的build.gradle中创建这些自定义任务和插件。您可以这样做,但问题是您将无法在任何子项目中使用它。 请记住,在Java/Groovy中导入某些内容需要该内容存在于正确的Java/Groovy文件(或模块对于Java 9+)。由于您的build.gradle只是一个脚本,因此从中简单导入插件或任务是不合适的。 正如我已经指出的,并且这是来自Gradle文档的,拥有buildSrc目录的原因之一是:

发现该目录后,Gradle会自动编译和测试此代码,并将其放入构建脚本的类路径中

如您所见,buildSrc作为构建过程的扩展,可以向所有项目的构建脚本添加附加功能。

还有几点需要注意:

  • buildSrc/build.gradle中声明的任何dependencies都可被项目中其它构建脚本看到。
  • buildSrc/build.gradle中的buildscript块只能被buildSrc/build.gradle看到,其它地方无法访问。
  • buildSrc中定义的任何插件类都可以在项目中的任何构建脚本中使用,不需要在META-INF/gradle-plugins中声明。
  • 在主build.gradle或任何子项目中定义的依赖项在buildSrc中不可见。如果您记得该文件夹被视为包含的构建(即外部构建),那么它不能看到包含它的项目的类路径就是有道理的。

3
另一个有用的事实:当从 buildSrc 导入类到构建文件时,请注意导入是在 buildscript 部分之后解析的。这意味着您不能在 buildscript 部分中使用已导入的类。但是,您可以通过完全限定的名称来使用它们。 - Dmytro

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接