Gradle之恋(13)——多项目构建

楔子

为了可维护性和解耦,项目分层、分模块一直是追求的目标和开发策略。因此多项目就是构建工具的标配,而构建多项目的方便和性能也成为构建工具的重要卖点,gradle也不例外,提供了强有力的多项目构建能力。
Gradle

项目结构

我们知道gradle项目的根目录有两个重要的配置文件settings.gradle和build.gradle,前者用于配置项目结构,后者用于项目、任务以及依赖等的配置。使用gradle的init插件“gradle init -x wrapper”构建项目,结构如下

multi-project/
├── build.gradle
└── settings.gradle

settings.gradle内容如下

/*
* This settings file was generated by the Gradle 'init' task.
*
* The settings file is used to specify which projects to include in your build.
* In a single project build this file can be empty or even removed.
*
* Detailed information about configuring a multi-project build in Gradle can be found
* in the user guide at https://docs.gradle.org/3.3/userguide/multi_project_builds.html
*/

/*
// To declare projects as part of a multi-project build use the 'include' method
include 'shared'
include 'api'
include 'services:webservice'
*/

rootProject.name = 'multi-project'

我们可以看到rootProject.name是根项目的名称,可以使用include方法声明子项目,如果把注释删除

include 'shared'
include 'api'
include 'services:webservice'

rootProject.name = 'multi-project'

这样变成了多项目,使用projects任务查看结构如下

$ gradle -q projects

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

Root project 'multi-project'
+--- Project ':api'
+--- Project ':services'
| \--- Project ':services:webservice'
\--- Project ':shared'

根项目multi-project包含子项目api、services、shared,子项目services又包含子项目webservice。

就是是如此简单建立多项目,是不是简洁、方便、容易理解,哈哈….

任务执行

首先我们来查看下多项目下的任务做个感性任务,执行“gradle tasks –all”

.......
buildEnvironment - Displays all buildscript dependencies declared in root project 'multi-project'.
api:buildEnvironment - Displays all buildscript dependencies declared in project ':api'.
services:buildEnvironment - Displays all buildscript dependencies declared in project ':services'.
services:webservice:buildEnvironment - Displays all buildscript dependencies declared in project ':services:webservice'.
shared:buildEnvironment - Displays all buildscript dependencies declared in project ':shared'.
components - Displays the components produced by root project 'multi-project'. [incubating]
api:components - Displays the components produced by project ':api'. [incubating]
services:components - Displays the components produced by project ':services'. [incubating]
services:webservice:components - Displays the components produced by project ':services:webservice'. [incubating]
shared:components - Displays the components produced by project ':shared'. [incubating]
dependencies - Displays all dependencies declared in root project 'multi-project'.
api:dependencies - Displays all dependencies declared in project ':api'.
services:dependencies - Displays all dependencies declared in project ':services'.
services:webservice:dependencies - Displays all dependencies declared in project ':services:webservice'.
shared:dependencies - Displays all dependencies declared in project ':shared'.
.......

可以看到子项目与任务之间以“:”分隔,子项目与子项目也是以“:”分隔,实际上“:”是路径符,你可以理解为替代了“/”或“\”路径符,因此你可进入项目目录以相对路径执行任务,如

cd api/ && gradle tasks

这样会执行api以及其子项目的tasks任务(如果没有api需要创建这个目录,因为默认项目名就是目录名)。你也可以在根目录下使用绝对路径来执行,如

cd api/ && gradle :tasks

虽然在api项目下但执行的是根项目的tasks任务。

如果你是使用wrapper的方式,那么要逐一gradlew的路径,因为gradlew是在根项目下。

项目配置

对项目进行配置的前提是如何选择项目,常用的如

//包括根项目的所有项目
allprojects{

}
//不包括根项目的所有项目
subprojects{

}
//某个特定项目
project(':api'){

}
//过滤项目,除tropicalFish外的所有子项目
configure(subprojects.findAll {it.name != 'tropicalFish'}) {

}

当然还很多选择项目的方式,可参考dsl文档。我们来做个示例,配置如下

allprojects {
task hello {
doLast { task ->
println "$task.name - I'm $task.project.name"
}
}
}
subprojects {
task hello2 {
doLast { task ->
println "$task.name - I'm $task.project.name"
}
}
}
configure(subprojects.findAll {it.name != 'api'}) {
task hello3 {
doLast { task ->
println "$task.name - I'm $task.project.name"
}
}
}

打印任务“gradle tasks –all”,如下

.......
Other tasks
-----------
hello
api:hello
services:hello
services:webservice:hello
shared:hello
api:hello2
services:hello2
services:webservice:hello2
shared:hello2
services:hello3
services:webservice:hello3
shared:hello3
.......

可以得出所有项目都有任务hello,除了根项目都有hello2任务,除了根项目和api都有hello3任务。

在根项目下执行任务及输出

$ gradle -q hello
hello - I'm multi-project
hello - I'm api
hello - I'm services
hello - I'm shared
hello - I'm webservice


$ gradle -q :hello
hello - I'm multi-project

由此很容易对比出相对路径和绝对路径执行任务的不同,你看出来了吗?

总结

Gradle构建多项目就是如此简单便捷,一个settings.gradle即可搞定。每个项目都可以拥有自己的settings.gradle和build.gradle,但一般放在根目录下,集中便于管理。

下一篇我们针对web来构建一个多项目来创建一个demo。

翟前锋 wechat
欢迎订阅我的微信公众号:zhaiqianfeng!