💡
Gradle构建缓存可以帮助将多项目构建的构建时间减少多达90%. 在此处注册以参加我们的实时构建缓存培训课程,以了解如何进行.

除非碰巧是一个庞大的整体应用程序,否则只有最小的项目具有单个构建文件和源代码树. 消化和理解一个项目的过程通常要容易得多,该项目被分为多个较小的,相互依赖的模块. 但是,"相互依赖"一词很重要,这就是为什么您通常希望通过单个构建将模块链接在一起.

Gradle通过多项目构建来支持此方案.

Structure of a multi-project build

此类构建具有各种形状和大小,但它们确实具有一些共同的特征:

  • 项目根目录或master目录中的settings.gradle文件

  • 根目录或master目录中的build.gradle文件

  • 具有自己的*.gradle构建文件的*.gradle (某些多项目构建可能会省略子项目构建脚本)

settings.gradle文件告诉Gradle项目和子项目的结构. 幸运的是,您无需阅读此文件即可简单地了解项目结构,因为您可以运行命令gradle projects . 这是在Gradle示例中的Java 多项目构建中使用该命令的输出:

Example: Listing the projects in a build

gradle -q projects输出
> gradle -q projects

------------------------------------------------------------
Root project
------------------------------------------------------------

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

这告诉您multiproject具有三个直接子项目: apiservicesshared . 然后, services项目具有其自己的子级, sharedwebservice . 这些映射到目录结构,因此很容易找到它们. 例如,你可以找到在web服务 <root>/services/webservice .

默认情况下,Gradle使用其找到settings.gradle的目录名称作为根项目的名称. 这通常不会引起问题,因为所有开发人员在处理项目时都签出相同的目录名称. 在Continuous Integration服务器上,例如Jenkins,目录名称可能是自动生成的,并且与VCS中的名称不匹配. 因此,建议即使在单个项目构建中,也始终将根项目名称设置为可预测的名称. 您可以通过设置rootProject.name来配置根项目名称.

每个项目通常都会有自己的构建文件,但不一定是这种情况. 在上面的示例中, 服务项目只是其他子项目的容器或分组. 相应目录中没有构建文件. 但是, 项目的根项目确实有一个.

build.gradle通常用于在子项目之间共享通用配置,例如,通过对所有子项目应用相同的插件集和依赖项. 当最好将所有配置都放在一个位置时,它也可以用于配置单个子项目. 这意味着在发现特定子项目的配置方式时,应始终检查根构建文件.

要记住的另一件事是,构建文件可能不称为build.gradle . 许多项目将在子项目名称之后命名构建文件,例如上一个示例中的api.gradleservices.gradle . 这种方法在IDE中有很大帮助,因为很难确定要打开的二十种可能性中的哪个build.gradle文件. 这个小小的魔法是由settings.gradle文件处理的,但是作为构建用户,您不需要知道如何完成的细节. 只需浏览子项目目录,即可找到带有.gradle后缀的文件.

一旦知道哪些子项目可用,构建用户的关键问题就是如何在项目中执行任务.

Executing a multi-project build

From a user’s perspective, multi-project builds are still collections of tasks you can run. The difference is that you may want to control which project’s tasks get executed. You have two options here:

  • 转到与您感兴趣的子项目相对应的目录,然后像往常一样执行gradle <task> .

  • 使用任何目录中的合格任务名称,尽管通常是从根目录完成的. 例如: gradle :services:webservice:build将构建webservice子项目及其依赖的任何子项目.

第一种方法类似于单项目用例,但是在多项目构建的情况下,Gradle的工作方式略有不同. gradle test命令将在相对于当前工作目录具有该任务的任何子项目中执行test任务. 因此,如果从根项目目录运行命令,则将在apisharedservices:sharedservices:webservice中运行test . 如果从services项目目录运行命令,则仅在services:sharedservices:webservice中执行任务.

为了更好地控制执行的内容,请使用限定名称(提到的第二种方法). 这些路径与目录路径一样,但是使用":"代替" /"或" \". 如果路径以":"开头,则相对于根项目解析路径. 换句话说,前导":"代表根项目本身. 所有其他冒号都是路径分隔符.

这种方法适用于任何任务,因此,如果您想知道特定子项目中的tasks ,只需使用tasks任务即可,例如gradle :services:webservice:tasks .

无论您使用哪种技术来执行任务,Gradle都会负责构建目标依赖的任何子项目. 您不必自己担心项目间的依赖性. 如果您对如何配置感兴趣,可以稍后在用户手册中阅读有关编写多项目构建的信息.

最后一件事要注意. 使用Gradle包装器时,第一种方法效果不佳,因为如果不在项目根目录中,则必须指定包装器脚本的路径. 例如,如果您位于webservice子项目目录中,则必须运行../../gradlew build .

作为构建用户,这就是您真正需要了解的多项目构建的全部内容. 现在,您可以确定一个构建是否是一个多项目构建,并可以发现其结构. 最后,您可以在特定子项目中执行任务.