1 背景
在开始Gradle之前请务必保证自己已经初步了解了Groovy脚本,特别是闭包规则,如果还不了解Groovy则可以先看《Groovy脚本基础全攻略》这一篇博客速成一下Groovy基础,然后再看此文即可。关于Gradle速成干货基础详情也请参考Gradle官方网站,不好意思我太Low了。
Gradle核心是基于Groovy的领域特定语言(DSL,具体概念参见《Groovy脚本基础全攻略》),具有非常好的扩展性,所以不管是简单的独立项目还是大型的多项目构建它都能高效的提高构建任务,尤其对多项目支持是非常牛逼的;Gradle还提供了局部构建功能,譬如构建一个单独子项目时它会构建这个子项目依赖的所有子项目;当然了他对远程仓库和本地库的支持也很到位;哎呀,总之后面你就明白他的牛逼之处了。
既然Gradle核心是Groovy,Groovy本质又是Java,所以很明显可以发现Gradle环境必须依赖JDK与Groovy库,具体如下:
- JDK版本必须是JDK6以上;
- 因为Gradle自带Groovy库, 所以已安装的Groovy会被Gradle忽略;
具体Gradle环境配置好了以后如下图:
2 Gradle DSL基础
Gradle的实质是配置脚本,执行一种类型的配置脚本时就会创建一个关联的对象,譬如执行Build script脚本就会创建一个Project对象,这个对象其实就是Gradle的代理对象。下面给出来各种类型Gradle对应的对象类型:
脚本类型 | 关联对象类型 |
---|---|
Build script | Project |
Init script | Gradle |
Settings script | Settings |
Gradle的三种主要对象解释如下:
- Project对象:每个build.gradle会转换成一个Project对象。
- Gradle对象:构建初始化时创建,整个构建执行过程中只有这么一个对象,一般很少去修改这个默认配置脚本。
- Settings对象:每个settings.gradle会转换成一个Settings对象。
可以看见,当我们编写指定类型Gradle脚本时我们可以直接使用关联对象的属性和方法;当然了,每个脚本也都实现了Script接口,也就是说我们也可以直接使用Script接口的属性与方法。
2-1 构建脚本Build script(Project)
在Gradle中每个待编译的工程都是一个Project(每个工程的build.gradle对应一个Project对象),每个Project在构建的时候都包含一系列Task,这些Task中很多又是Gradle的插件默认支持的。
PS:所谓的我们编写Gradle脚本,实质大多数时候都是在编写构建脚本Build script,所以说Project和Script对象的属性和方法等API非常重要。
每一个Project对象和build.gradle一一对应,一个项目在构建时都具备如下流程:
- 为当前项目创建一个Settings类型的实例。
- 如果当前项目存在settings.gradle文件,则通过该文件配置刚才创建的Settings实例。
- 通过Settings实例的配置创建项目层级结构的Project对象实例。
- 最后通过上面创建的项目层级结构Project对象实例去执行每个Project对应的build.gradle脚本。
2-2 初始化脚本Init script(Gradle)和设置脚本Settings script(Settings)
Gradle对象:
初始化脚本Init script(Gradle)类似于Gradle的其他类型脚本,这种脚本在构建开始之前运行,主要的用途是为接下来的Build script做一些准备工作。我们如果需要编写初始化脚本Init script,则可以把它按规则放置在USER_HOME/.gradle/相关目录下。譬如:
初始化脚本的Gradle对象代表了Gradle的调运,我们可以通过调用Project对象的getGradle()方法获得Gradle实例对象。
Settings对象:
在对工程进行配置(譬如多项目树构建)时Settings实例与settings.gradle文件一一对应,它用来进行一些项目设置的配置。这个文件一般放置在工程的根目录。譬如:
2-3 Build生命周期
Gradle的构建脚本生命周期具备三大步,如下:
可以看见,生命周期其实和上面构建脚本Build script的执行流程是可以关联上的。有了这个流程图我们接下里详细看下每个过程。
settings.gradle文件:
除了构建脚本文件,Gradle还定义了一个约定名称的设置文件(默认为settings.gradle)。该文件在初始化阶段被执行,对于多项目构建必须保证在根目录下有settings.gradle文件,对于单项目构建设置文件是可选的,不过建议还是写上。
如下是单项目构建的一个例子:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
//settings.gradle println 'This is executed during the initialization phase.' //build.gradle println 'This is executed during the configuration phase.' task configured { println 'This is also executed during the configuration phase.' } task test << { println 'This is executed during the execution phase.' } task testBoth { doFirst { println 'This is executed first during the execution phase.' } doLast { println 'This is executed last during the execution phase.' } println 'This is executed during the configuration phase as well.' } |
运行构建结果:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
> gradle test testBoth This is executed during the initialization phase. This is executed during the configuration phase. This is also executed during the configuration phase. This is executed during the configuration phase as well. :test This is executed during the execution phase. :testBoth This is executed first during the execution phase. This is executed last during the execution phase. BUILD SUCCESSFUL Total time: 1 secs |
Gradle多项目构建:
多项目构建总是需要指定一个树根,树中的每一个节点代表一个项目,每一个Project对象都指定有一个表示在树中位置的路径;在设置文件中我们还可以使用一套方法来自定义构建项目树。
1 2 |
//分层布局的多项目构建settings.gradle文件 include 'project1', 'project2:child', 'project3:child1' |
上面例子中把project的路径作为了include方法的参数,譬如上面的’project3:child1’参数就指定了物理路径的project3/child1(project3/child1是相对于多项目根路径的相对路径),这也同时意味着会创建’project3’和’project3:child1’两个project。
1 2 |
//平面布局的多项目构建settings.gradle文件 includeFlat 'project3', 'project4' |
上面例子中includeFlat方法接受目录名作为参数,但是特别注意,这些项目目录必须是根目录的兄弟目录。
当然了,设置文件中创建的多项目树其实是由项目描述符来描述的,我们可以在设置文件中随时修改这些描述符。如下:
1 2 3 4 |
//settings.gradle rootProject.name = 'main' project(':projectA').projectDir = new File(settingsDir, '../my-project-a') project(':projectA').buildFileName = 'projectA.gradle' |
可以看见,如上例子通过描述符更改名称和项目目录,并且建立了一个项目的文件。
Gradle构建初始化Initialization:
在初始化阶段如果我们在根路径下直接指明settings.gradle文件和相关配置则构建初始化就会直接按照我们的设置去构建项目,如果我们没指明settings.gradle文件则Gradle会以一定的规则去寻找settings.gradle文件,然后依据寻找结果的不同去决定如何构建项目。
3 Gradle构建基础
通过上一章可以知道,每一个Gradle构建都是由一个或多个project构成,每一个project都是由一个或多个tasks构成,每个task的实质其实是一些更加细化的构建(譬如编译class、创建jar文件等)。
任务task基础:
如下例子我们先来直观感受一下task的概念,具体细节后面会探讨: