Gradle学习系列之八——构建多个Project
在本系列的上篇文章中,我们讲到了Gradle的依赖管理,在本篇文章中,我们将讲到如何构建多个Project。
请通过以下方式下载本系列文章的Github示例代码:
git clone https://github.com/davenkin/gradle-learning.git
Gradle为每个build.gradle都会创建一个相应的Project领域对象,在编写Gradle脚本时,我们实际上是在操作诸如Project这样的Gradle领域对象。在多Project的项目中,我们会操作多个Project领域对象。Gradle提供了强大的多Project构建支持。
要创建多Project的Gradle项目,我们首先需要在根(Root)Project中加入名为settings.gradle的配置文件,该文件应该包含各个子Project的名称。比如,我们有一个根Project名为root-project,它包含有两个子Project,名字分别为sub-project1和sub-project2,此时对应的文件目录结构如下:
root-project/
sub-project1/
build.gradle
sub-project2/
build.gradle
build.gradle
settings.gradle
root-project本身也有自己的build.gradle文件,同时它还拥有settings.gradle文件位于和build.gradle相同的目录下。此外,两个子Project也拥有他们自己的build.gradle文件。
要将sub-project1和sub-project2加入到root-project的子Project中,我们需要在settings.gradle中加入:
include 'sub-project1', 'sub-project2'
接下来,我们来定义一个Task用于显示每个Project各自的名称。我们可以在每个build.gradle进行定义,但是这却是一种比较笨的方法,此时我们也完全没有享受到Gradle的多Project构建功能所带来的好处。在Gradle中,我们可以通过根Project的allprojects()方法将配置一次性地应用于所有的Project,当然也包括定义Task。比如,在root-project的build.gradle中,我们可以做以下定义:
allprojects {
apply plugin: 'idea' task allTask << {
println project.name
}
}
以上Gradle脚本将闭包中的代码应用在所有的Project中,包括root-project本身。我们首先将应用了idea Plugin用于生成IntelliJ工程,其次我们定义了名为allTask的Task,该Task应用于每个Project,作用是输出各个Project的名称。执行“gradle allTask”,命令行输出如下:
:allTask
root-project
:sub-project1:allTask
sub-project1
:sub-project2:allTask
sub-project2
我们看到,该allTask对于每个Project都执行了一次,在执行时输出了当前Project的名称。
除了allprojects()之外,Project还提供了subprojects()方法用于配置所有的子Project(不包含根Project)。比如,我们可以定义Task来只输出各个子Project的名字:
subprojects {
task subTask << {
println project.name
}
}
执行“gradle subTask”,命令行输出如下:
:sub-project1:subTask
sub-project1
:sub-project2:subTask
sub-project2
此时的输出中不再包含root-project的名字。
上文中已经提到,在Gradle脚本中,我们实际上是在操作一些领域对象,因此我们可以将groovy的所有语言特性用在Gradle的领域对象上,比如我们可以对Project进行过滤:
configure(allprojects.findAll { it.name.startsWith('sub') }) {
subTask << {
println 'this is a sub project'
}
}
在上面的代码中,我们先找到所有Project中名字以“sub”开头的Project,然后再对这些Project进行配置,在配置中,我们向这些Project的subTask中加入了一条额外的打印语句。
此时如果再执行“gradle subTask”,命令行输出如下:
:sub-project1:subTask
sub-project1
this is a sub project
:sub-project2:subTask
sub-project2
this is a sub project
到此为止,我们所有的Task定义工作都是在root-project中进行的,而sub-project1和sub-project2中的build.gradle文件依然什么都没有。事实上,我们可以将所有对子Project的配置均放在根Project中进行。在上面的例子中,我们通过allprojects()和subprojects()将所有的子Project都包含在了配置之内,其实我们还可以对单个Project进行单独配置。比如,在root-project的build.gradle中加入:
project(':sub-project1') {
task forProject1 << {
println 'for project 1'
}
}
以上脚本向sub-project1中加入了名为forProject1的Task,在执行“gradle forProject1”时,终端输出如下:
:sub-project1:forProject1
for project 1
这里有一个问题:我们是在root-project下执行的命令,因此照理说Gradle会认为forProject1是定义在所有的Project上,而此时只有sub-project1才拥有该Task,Gradle应该抛出异常指示在root-project和sub-project2上找不到该Task才对,为什么它还是执行成功了呢?原因在于:只有当一个Task没有在任何Project中定义时,Gradle才会将其当做异常。否则,Gradle会在所有拥有该Task的Project上执行该Task。
一旦有了多个Project,他们之间便会存在着依赖关系。Gradle的Project之间的依赖关系是基于Task的,而不是整个Project的。
现在,让我们来看一个Project依赖的例子。比如sub-project1中有taskA和taskB,taskA依赖于taskB:
task taskA << {
println 'this is taskA from project 1'
} task taskB << {
println 'this is taskB from project 1'
} taskA.dependsOn taskB
在执行“gradle taskA”时,终端输出:
:sub-project1:taskB
this is taskB from project 2
:sub-project1:taskA
this is taskA from project 1
这个很容易理解,两个Task都是属于sub-project1的。但是,让我们再向其中加入一些复杂性。我们在sub-project2中定义taskC和taskD,然后使taskA再依赖于taskC,又使taskB依赖于taskD:
//sub-project1:
taskA.dependsOn ':sub-project2:taskC'
taskB.dependsOn ':sub-project2:taskD' //sub-project2:
task taskC << {
println 'this is taskC from project 2'
} task taskD << {
println 'this is taskD from project 2'
}
此时再执行“gradle taskA”,终端输出如下:
:sub-project2:taskD
this is taskD from project 2
:sub-project1:taskB
this is taskB from project 1
:sub-project2:taskC
this is taskC from project 2
:sub-project1:taskA
this is taskA from project 1
分析一下:taskA依赖于taskB,而taskB又依赖于taskD,所以sub-project1的taskD首先得到了执行,然后再执行sub-project1的taskB。之后,又由于taskA依赖于taskC,故Gradle再次转向sub-project1执行taskC,最后才执行taskA。
在下一篇文章中,我们将讲到如何自定义Task类型。
Gradle学习系列之八——构建多个Project的更多相关文章
- Gradle学习系列之三——读懂Gradle语法
在本系列的上篇文章中,我们讲到了创建Task的多种方法,在本篇文章中,我们将学习如何读懂Gradle. 请通过以下方式下载本系列文章的Github示例代码: git clone https://git ...
- Gradle学习系列之一——Gradle快速入门
这是一个关于Gradle的学习系列,其中包含以下文章: Gradle快速入门 创建Task的多种方法 读懂Gradle语法 增量式构建 自定义Property 使用java Plugin 依赖管理 构 ...
- Gradle学习系列之一——Gradle快速入门(转)
这是一个关于Gradle的学习系列,其中包含以下文章: Gradle快速入门 创建Task的多种方法 读懂Gradle语法 增量式构建 自定义Property 使用java Plugin 依赖管理 构 ...
- Gradle学习系列之五——自定义Property
在本系列的上篇文章中,我们讲到了增量式构建,在本篇文章中,我们将讲到如何自定义Project的Property. 请通过以下方式下载本系列文章的Github示例代码: git clone https: ...
- Gradle学习系列(三)
上一篇我们已经学习了 Gradle 打包,那么这一节 就开始讲讲本章的第二版块:打包及使用Gradle过程中的常见错误问题. 有时候我们需要编辑一个开源项目之类的,希望把它导入了我们自己的IDE工具中 ...
- Gradle学习系列之七——依赖管理
在本系列的上篇文章中,我们讲到了如何使用java Plugin,在本篇文章中,我们将讲到Gradle的依赖管理. 请通过以下方式下载本系列文章的Github示例代码: git clone https: ...
- Gradle学习系列(一)
今天就开始学习Gradle构建了,听说很牛X.本篇内容就带领我初步窥探Gradle的世界. 1.什么是Gradle 相信之前都接触过用Ant或者Meavn进行项目的构建,两者各有千 ...
- Gradle学习系列之读懂Gradle语法
转载地址: http://www.cnblogs.com/CloudTeng/p/3418072.html Gradle是一种声明式的构建工具.在执行时,Gradle并不会一开始便顺序执行build. ...
- Dubbo学习系列之八(分布式事务之MQ方案)
自从小王玩起了微服务,发现微服务果然很强大,好处真是太多,心中暗喜,然而,却也遇到了分布式中最棘手的问题:分布式事务.小王遍访各路神仙,也无个完美开源解决方案,当然,也有些实际可行的手法,虽不算完美, ...
随机推荐
- JavaScript学习汇总
对于JavaScript,还是无法割舍,有心无力,时间总是匆匆,暂且都放在这里吧 javascript中this的使用 写的很不错的一偏文章,简单看了下,mark了吧 原文:http://davids ...
- javaweb 学习总结
http://www.cnblogs.com/xdp-gacl/category/574705.html 这个总结很好,以前看书没搞懂的,这里基本上都清楚了,赞一个,推荐. Servlet与普通Jav ...
- Pinterest 架构:两年内月 PV 从零到百亿【翻译】
原文地址 这篇文章,采用 Markdown 方式,写的还是比较实在的,要是有架构图就好了. Pinterest 是图片版的 Twitter,用户把自己感兴趣的东西用图钉(Pins)钉在钉板(PinBo ...
- spring整合activemq发送MQ消息[queue模式]实例
queue类型消息 pom依赖 <dependency> <groupId>junit</groupId> <artifactId>junit</ ...
- Windows下msysGit使用及相关配置
Windows下msysGit使用 目前我们git通过ssh进行通信,所以需要你也安装ssh以及将ssh key发给我,省得每次都需要输入用户名和密码 1.创建工程目录 windows下进入msysG ...
- webpack处理Img标签路径的几种情况
在使用webpack过程中遇到这个问题,各种搜索遇到此问题的还真不少,但都没有一个完整的说明. 后来研究下,图片除了路径替换还是就是图片做优化主是小于一定大小的通过转 base64 inline方式减 ...
- DB2中OLAP函数使用示例
下面的需求是将不仅获取查询的结果集,还要将结果集的SIZE返回.结果集的SIZE是无法通过CURSOR获取的. 通常聚合函数在二种情况下,使用默认分组即没有分组.可以直接使用,比如 selec ...
- centos 7.0 下触发器乱码的解决
[root@iZ62jhlmmZ ~]# uname -a Linux iZ62jhlmsymZ 3.10.0-123.13.2.el7.x86_64 #1 SMP Thu Dec 18 14:09: ...
- SD卡中FAT32文件格式快速入门(图文详细介绍)【转】
本文转自:http://blog.csdn.net/mjx91282041/article/details/8904705 说明: MBR :Master Boot Record ( 主引导记录) D ...
- ci配置smarty手记
需要用ci来写一个后台配置smarty,在网络上能够找到一些相关的文章.但是都是比较旧的内容,大部分是smary2.*的配置方法.按照这个配置后会出现一些错误.其实配置看smary官方会比较简单. 基 ...