Gradle 支持多项目构建。

等级基础 9

虽然一些小型项目和整体应用程序可能包含单个构建文件和源代码树,但更常见的情况是项目被分割成更小的、相互依赖的模块。 “相互依赖”这个词至关重要,因为您通常希望通过单个构建将许多模块链接在一起。

Gradle 通过多项目构建支持这种场景。这有时被称为多模块项目。 Gradle 将模块称为子项目。

多项目构建由一个根项目和一个或多个子项目组成。

多项目结构

以下表示包含两个子项目的多项目构建的结构:

多项目结构

目录结构应如下所示:

├── .gradle
│   └── ⋮
├── gradle
│   ├── libs.version.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 社区对于多项目构建结构有两个标准:

  1. 使用 buildSrc 进行多项目构建- 其中buildSrc是 Gradle 项目根目录中包含所有构建逻辑的类似子项目的目录。

  2. 复合构建- 包含其他构建的构建,其中build-logic包含可重用构建逻辑的 Gradle 项目根目录中的构建目录。

多项目标准

1. 多项目构建使用buildSrc

多项目构建允许您组织具有许多模块的项目,连接这些模块之间的依赖关系,并轻松地在它们之间共享通用的构建逻辑。

例如,一个包含许多名为mobile-appweb-appapilib、的模块的构建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-appmobile-appdependent on lib。这意味着为了让 Gradle 构建web-appmobile-app,它必须lib首先构建。

在此示例中,根设置文件将如下所示:

设置.gradle.kts
include("mobile-app", "web-app", "api", "lib", "documentation")
子项目(模块)的包含顺序并不重要。

buildSrcGradle 会自动识别该目录。它是定义和维护共享配置或命令式构建逻辑(例如自定义任务或插件)的好地方。

buildSrc如果build.gradle(.kts)buildSrc.

如果java插件应用于buildSrc项目,则编译后的代码buildSrc/src/main/java将放入根构建脚本的类路径中,使其可用于构建中的任何子项目( web-appmobile-app、等...​)。lib

请参阅如何声明子项目之间的依赖关系以了解更多信息。

2. 复合构建

复合构建,也称为包含构建,最适合在构建(而不是子项目)之间共享逻辑或隔离对共享构建逻辑(即约定插件)的访问。

让我们以前面的例子为例。其中的逻辑buildSrc已转变为包含插件的项目,并且可以独立于根项目构建进行发布和工作。

该插件被移动到它自己的构建中,build-logic使用构建脚本和设置文件调用:

.
├── 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位于根项目的子目录中 的事实是无关紧要的。如果需要,该文件夹可以位于根项目之外。

根设置文件包括整个build-logic 构建

设置.gradle.kts
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
------------------------------------------------------------
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

如果从项目根目录运行该命令,您将testapisharedservices:sharedservices:webservice中运行。

如果从services项目目录运行命令,则只会执行services:sharedservices:webservice中的任务。

Gradle 行为背后的基本规则是使用名称执行层次结构中的所有任务如果在遍历的任何子项目中都没有找到这样的任务,则进行抱怨。

某些任务选择器(例如helpdependencies)只会在调用它们的项目上运行任务,而不是在所有子项目上运行,以减少屏幕上打印的信息量。

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

您可以使用任务的完全限定名称来执行特定子项目中的特定任务。例如:gradle :services:webservice:build将运行webservicebuild子项目的任务。

任务的完全限定名称是其项目路径加上任务名称。

这种方法适用于任何任务,因此如果您想知道特定子项目中有哪些任务,请使用任务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来构建和测试所有项目。

请参阅构建构建章节以了解更多信息。