Contents

  • 认识项目结构
  • 通过名称执行任务
  • 通过全限定名称执行任务
  • 多项目构建以及测试

通常来说小型项目有一个构建文件和源文件树,除非它是一个大型的,单体应用 ..
消化和理解一个被拆分成更小的、相互依赖的模块的项目通常要容易得多。
相互依赖一词很重要, 不过,这也是为什么你通常希望通过一个单一的构建将这些模块联系在一起。
Gradle 同样支持多项目构建的场景 ..
了解多项目构建的创作的详细信息,考虑点击这里 ..

认识项目结构

我们可以通过gradle projects 命令打印出项目的总体结构 ..
例如:

  1. > gradle -q projects
  2. ------------------------------------------------------------
  3. Root project 'multiproject'
  4. ------------------------------------------------------------
  5. Root project 'multiproject'
  6. +--- Project ':api'
  7. +--- Project ':services'
  8. | +--- Project ':services:shared'
  9. | \--- Project ':services:webservice'
  10. \--- Project ':shared'
  11. To see a list of the tasks of a project, run gradle <project-path>:tasks
  12. For example, try running gradle :api:tasks

从用户的角度来说,多项目构建你仍然可以运行任务集合 ..
不同的是你也许想要控制那个项目的任务进行执行 …
以下的接口描述了两个选择 - 你如何在多项目构建中执行任务 …

通过名称执行任务

例如:

  1. gradle test

将会执行所有子项目中的测试任务,相对于当前工作空间(且拥有此任务)
如果你从根目录中运行,那么你将运行api,shared,services:shared 以及 services:webservice项目中的test任务 …
这里提到的项目说的是上面的demo .. 仅仅当在遍历任何子项目中没有发现这样的任务才会抱怨(才会有所提示) ..

有些任务选择器,例如help 或者 dependencies,将仅仅执行命令所在项目中的任务,而不会在所有子项目中执行 … 这些任务的主要意图是输出信息(如果它们合并来自所有项目的信息可能难以处理)

Gradle 会向下查询这个体系,从当前的目录开始,查询给定名称的任务并执行它们 …
有一件事非常重要:
Gradle 总是评估多项目构建中的每一个项目并且创建所有存在的任务对象 ..
然后,根据任务名称参数和当前目录,Gradle 过滤这一类任务并执行 …
因此在Gradle的cross project configuration,每一个项目在任何任务执行之前都会被评估 …
如果你使用Gradle wrapper,为了执行特定子项目的任务 - 如果从对应的子项目目录运行将不会工作,因为如果你不在项目的根目录中,你需要指定wrapper 脚本的路径 .
举个例子,如果你想要运行webservice子项目中的build 任务 并且你正在webservice子项目目录中,你需要 ../../gradlew build …
那么这样看起来非常奇怪 …, 因为它必须指定 gradlew 脚本路径 …

下一个部分展示了如何直接从项目的根目录实现相同的目录:

通过完全限定名称执行任务

你能够通过指定任务的完全限定名称进行执行 ,这样你就能够执行特定项目的任务 …

  1. gradle :services:webservice:build

将会执行webservice 子项目的构建 ..
这个任务的完全限定名称 类似于项目路径 加上 任务名称 ..
一个项目路径具有以下的模式:
它开始一个可选的分号(:),它代表着根项目 …
跟项目是唯一一个在路径上不需要名称进行指定的项目 ..
其余项目的路径是一个分号分割的项目名称序列 …
这里序列中的下一个项目是前一个项目的子项目 .. 你能够通过前面查看项目结构的命令查看项目的路径

  1. gradle projects

这种方式对任何一种任务都可执行,因此如果你想要知道在特殊的子项目中有那些任务,你可以通过 tasks 任务进行查看 …

  1. gradle :services:webservie:tasks

不管你使用那种方式执行任务,Gradle 将小心此目标依赖的任务子项目的构建 …
你不需要担心你项目相互项目依赖关系,如果你关心它是如何配置的,你能够在这里了解如何编写一个多项目构建中获得更多 …
作为一个构建用户那才是你实在需要了解多项目构建 …
你能够识别一个构建是否为一个多项目构建并且你能够查看它的结构 …
最终,你能够执行特定子项目中的任务 …

多项目构建以及测试

注意这一句话很重要:
Java插件的 build 任务通常被用来编译,测试并且执行代码风格的检查(如果使用了CodeQuality插件).
在多项目构建中你通常想要执行所有这样的任务(跨越项目范围),buildNeeded 以及
buildDependents 任务能够帮助你解决这个问题 ..
在这个例子中,:services:person-service项目依赖于:api 以及 :shared 项目..
:api 项目同样依赖于 :shared 项目 ..

假设你工作在单个项目上,目前在 :api 项目上, 你能够已经做出了一些改变,但自从执行清理后还没有构建整个项目,你想要构建任何它所依赖的Jar,但是你仅仅在你改变的项目中执行代码质量和单元测试 …
那么 build 任务能够做这样的事情:

  1. Output of gradle :api:build
  2. > gradle :api:build
  3. > Task :shared:compileJava
  4. > Task :shared:processResources
  5. > Task :shared:classes
  6. > Task :shared:jar
  7. > Task :api:compileJava
  8. > Task :api:processResources
  9. > Task :api:classes
  10. > Task :api:jar
  11. > Task :api:assemble
  12. > Task :api:compileTestJava
  13. > Task :api:processTestResources
  14. > Task :api:testClasses
  15. > Task :api:test
  16. > Task :api:check
  17. > Task :api:build

上面的结果你能够发现,仅仅只有:api 项目执行了单元测试和检查 …
你将从版本控制系统中获取最新的源文件(它包括来自:api 项目所依赖项目的改变),你可能想要此项目所依赖的所有项目,同样测试也需要,那么 buildNeeded 任务能够测试当前项目的testRuntime 配置上的所有项目依赖 …

  1. Output of gradle :api:buildNeeded
  2. > gradle :api:buildNeeded
  3. > Task :shared:compileJava
  4. > Task :shared:processResources
  5. > Task :shared:classes
  6. > Task :shared:jar
  7. > Task :api:compileJava
  8. > Task :api:processResources
  9. > Task :api:classes
  10. > Task :api:jar
  11. > Task :api:assemble
  12. > Task :api:compileTestJava
  13. > Task :api:processTestResources
  14. > Task :api:testClasses
  15. > Task :api:test
  16. > Task :api:check
  17. > Task :api:build
  18. > Task :shared:assemble
  19. > Task :shared:compileTestJava
  20. > Task :shared:processTestResources
  21. > Task :shared:testClasses
  22. > Task :shared:test
  23. > Task :shared:check
  24. > Task :shared:build
  25. > Task :shared:buildNeeded
  26. > Task :api:buildNeeded
  27. BUILD SUCCESSFUL in 0s

我们能够发现:api项目所以来的其他项目也进行了构建 … 包括测试和检查 …
当然你可能想要重构在其他项目中被使用的:api项目的一部分,如果你有这一类型的改变,你可能不仅仅只满足:api项目的测试,你可能还需要测试所有依赖于:api 项目的所有项目,
那么buildDependents 任务能够测试所有依赖于此项目的所有项目(在 testRuntime 配置上)

Output of gradle :api:buildDependents
> gradle :api:buildDependents
> Task :shared:compileJava
> Task :shared:processResources
> Task :shared:classes
> Task :shared:jar
> Task :api:compileJava
> Task :api:processResources
> Task :api:classes
> Task :api:jar
> Task :api:assemble
> Task :api:compileTestJava
> Task :api:processTestResources
> Task :api:testClasses
> Task :api:test
> Task :api:check
> Task :api:build
> Task :services:person-service:compileJava
> Task :services:person-service:processResources
> Task :services:person-service:classes
> Task :services:person-service:jar
> Task :services:person-service:assemble
> Task :services:person-service:compileTestJava
> Task :services:person-service:processTestResources
> Task :services:person-service:testClasses
> Task :services:person-service:test
> Task :services:person-service:check
> Task :services:person-service:build
> Task :services:person-service:buildDependents
> Task :api:buildDependents

BUILD SUCCESSFUL in 0s

最终,你可能想要构建并测试所有项目 …
在根项目中运行的任何任务将会导致所有项目的中相同任务被执行 …
因此你只需要使用 gradle build 构建并测试项目 ..
这里为什么只需要build 任务就可以构建并测试项目了呢 ??
回答:
前面说过, build项目作为项目测试以及和代码风格的依赖任务 … hook