Gradle 支持多项目构建。

虽然一些小型项目和单体应用可能只包含一个构建文件和源代码树,但通常更常见的是项目被拆分成更小的、相互依赖的模块。“相互依赖”这个词至关重要,因为您通常希望通过单个构建将多个模块链接在一起。
Gradle 通过多项目构建来支持这种情况。这有时被称为多模块项目。Gradle 将模块称为子项目。
多项目构建由一个根项目和一个或多个子项目组成。
多项目结构
以下表示包含三个子项目多项目构建的结构

目录结构应如下所示
├── .gradle
│ └── ⋮
├── gradle
│ ├── libs.versions.toml
│ └── wrapper
├── gradlew
├── gradlew.bat
├── settings.gradle.kts (1)
├── sub-project-1
│ └── build.gradle.kts (2)
├── sub-project-2
│ └── build.gradle.kts (2)
└── sub-project-3
└── build.gradle.kts (2)
1 | settings.gradle.kts 文件应包含所有子项目。 |
2 | 每个子项目都应有自己的 build.gradle.kts 文件。 |
多项目标准
Gradle 社区对多项目构建结构有两个标准
-
使用 buildSrc 的多项目构建 - 其中
buildSrc
是 Gradle 项目根目录下的一个类似子项目的目录,包含所有构建逻辑。 -
组合构建 - 一种包含其他构建的构建,其中
build-logic
是 Gradle 项目根目录下的一个构建目录,包含可重用的构建逻辑。

1. 使用 buildSrc
的多项目构建
多项目构建允许您组织包含许多模块的项目,连接这些模块之间的依赖关系,并轻松地在它们之间共享通用的构建逻辑。
例如,一个包含多个模块(名为 mobile-app
、web-app
、api
、lib
和 documentation
)的构建可以组织成如下结构
.
├── gradle
├── gradlew
├── settings.gradle.kts
├── buildSrc
│ ├── build.gradle.kts
│ └── src/main/kotlin/shared-build-conventions.gradle.kts
├── mobile-app
│ └── build.gradle.kts
├── web-app
│ └── build.gradle.kts
├── api
│ └── build.gradle.kts
├── lib
│ └── build.gradle.kts
└── documentation
└── build.gradle.kts
模块之间将存在依赖关系,例如 web-app
和 mobile-app
依赖于 lib
。这意味着为了使 Gradle 构建 web-app
或 mobile-app
,它必须首先构建 lib
。
在此示例中,根 settings 文件如下所示
include("mobile-app", "web-app", "api", "lib", "documentation")
include("mobile-app", "web-app", "api", "lib", "documentation")
子项目(模块)包含的顺序无关紧要。 |
buildSrc
目录会被 Gradle 自动识别。它是定义和维护共享配置或命令式构建逻辑(例如自定义 task 或插件)的好地方。
如果在 buildSrc
下找到 build.gradle(.kts)
文件,则 buildSrc
会自动作为特殊子项目包含在您的构建中。
如果将 java
插件应用于 buildSrc
项目,则来自 buildSrc/src/main/java
的编译代码将放入根构建脚本的类路径中,使其可用于构建中的任何子项目(web-app
、mobile-app
、lib
等)。
查阅如何声明子项目之间的依赖关系以了解更多信息。
2. 组合构建
组合构建,也称为包含构建,最适合在构建之间(而不是子项目之间)共享逻辑或隔离对共享构建逻辑的访问(即,约定插件)。
让我们以之前的示例为例。buildSrc
中的逻辑已转换为包含插件的项目,可以独立于根项目构建进行发布和开发。
插件已移至其自己的名为 build-logic
的构建中,其中包含构建脚本和 settings 文件
.
├── gradle
├── gradlew
├── settings.gradle.kts
├── build-logic
│ ├── settings.gradle.kts
│ └── conventions
│ ├── build.gradle.kts
│ └── src/main/kotlin/shared-build-conventions.gradle.kts
├── mobile-app
│ └── build.gradle.kts
├── web-app
│ └── build.gradle.kts
├── api
│ └── build.gradle.kts
├── lib
│ └── build.gradle.kts
└── documentation
└── build.gradle.kts
build-logic 位于根项目的子目录中这一事实无关紧要。如果需要,该文件夹可以位于根项目之外。 |
根 settings 文件包含整个 build-logic
构建
pluginManagement {
includeBuild("build-logic")
}
include("mobile-app", "web-app", "api", "lib", "documentation")
查阅如何使用 includeBuild
创建组合构建以了解更多信息。
多项目路径
项目路径具有以下模式:它以可选的冒号开头,表示根项目。
根项目 :
是路径中唯一未按名称指定的项目。
项目路径的其余部分是以冒号分隔的项目名称序列,其中下一个项目是上一个项目的子项目
:sub-project-1
运行 gradle projects
时,您可以看到项目路径
------------------------------------------------------------
Root project 'project'
------------------------------------------------------------
Root project 'project'
+--- Project ':sub-project-1'
\--- Project ':sub-project-2'
项目路径通常反映文件系统布局,但也存在例外。最值得注意的是组合构建。
识别项目结构
您可以使用 gradle projects
命令来识别项目结构。
例如,让我们使用具有以下结构的多项目构建
$ gradle -q projects
Projects:
------------------------------------------------------------
Root project 'multiproject'
------------------------------------------------------------
Root project 'multiproject'
+--- Project ':api'
+--- Project ':services'
| +--- Project ':services:shared'
| \--- Project ':services:webservice'
\--- Project ':shared'
To see a list of the tasks of a project, run gradle <project-path>:tasks
For example, try running gradle :api:tasks
多项目构建是您可以运行的任务集合。不同之处在于,您可能想要控制哪些项目的任务被执行。
以下部分将介绍在多项目构建中执行任务的两个选项。
按名称执行任务
命令 gradle test
将在相对于当前工作目录的任何具有该任务的子项目中执行 test
任务。
如果您从根项目目录运行该命令,您将在 api、shared、services:shared 和 services:webservice 中运行 test
。
如果您从 services 项目目录运行该命令,您将仅在 services:shared 和 services:webservice 中执行该任务。
Gradle 行为背后的基本规则是执行层次结构中具有此名称的所有任务。并且,如果在任何遍历的子项目中未找到此类任务,则发出抱怨。
某些任务选择器(如 help 或 dependencies )将仅在调用它们的项目上运行任务,而不会在所有子项目上运行,以减少屏幕上打印的信息量。 |
按完全限定名称执行任务
您可以使用任务的完全限定名称在特定的子项目中执行特定的任务。例如:gradle :services:webservice:build
将运行 webservice 子项目的 build
任务。
任务的完全限定名称是其项目路径加上任务名称。
此方法适用于任何任务,因此如果您想知道特定子项目中有哪些任务,请使用 tasks
任务,例如 gradle :services:webservice:tasks
。
多项目构建和测试
build
任务通常用于编译、测试和检查单个项目。
在多项目构建中,您可能经常希望在各种项目中执行所有这些任务。buildNeeded
和 buildDependents
任务可以帮助您实现这一点。
在此示例中,:services:person-service
项目同时依赖于 :api
和 :shared
项目。:api
项目也依赖于 :shared
项目。
假设您正在处理单个项目 :api
项目,您一直在进行更改,但自执行 clean
以来尚未构建整个项目。您想要构建任何必要的支持 JAR,但仅对您已更改的项目部分执行代码质量和单元测试。
build
任务可以做到这一点
$ gradle :api:build
> 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
BUILD SUCCESSFUL in 0s
如果您刚刚从版本控制系统获得了最新版本的源代码,其中包括 :api
依赖的其他项目中的更改,您可能希望构建您依赖的所有项目并对其进行测试。
buildNeeded
任务构建并测试 testRuntime
配置的项目依赖项中的所有项目
$ gradle :api:buildNeeded
> 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 :shared:assemble
> Task :shared:compileTestJava
> Task :shared:processTestResources
> Task :shared:testClasses
> Task :shared:test
> Task :shared:check
> Task :shared:build
> Task :shared:buildNeeded
> Task :api:buildNeeded
BUILD SUCCESSFUL in 0s
您可能想要重构其他项目中使用的 :api
项目的某些部分。如果您进行这些更改,则仅测试 :api
项目是不够的。您必须测试所有依赖于 :api
项目的项目。
buildDependents
任务测试所有在 testRuntime 配置中对指定项目具有项目依赖关系的项目
$ 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
来构建和测试所有项目。
查阅构建结构章节以了解更多信息。
下一步: 了解 Gradle 构建生命周期 >>