Gardle——深入
Groovy语法
Groovy是运行于JVM上的动态语言(在运行时不用指定变量类型,动态改变数据类型 )
${}
用于一般替代字串或者表达式
闭包
闭包是可以用作方法参数的代码块,象是方法指针,代码在某处被定义然后在其后的调用处执行。
定义闭包
{ [closureParameters -> ] statements }
调用
闭包对象.call(参数)
闭包对象(参数)
参数
{ int a, int b=2 -> a+b }
参数类型可选
参数可以设定默认值
用逗号分隔
隐含参数
当闭包没有显式定义参数列表时,有一个隐式的it
参数
闭包的简写
闭包作为闭包或方法的最后一个参数,可以将闭包从参数圆括号中提取出来接在最后
如果闭包是唯一的一个参数,则闭包或方法参数所在的圆括号也可以省略
对于有多个闭包参数的,只要是在参数声明最后的,均可以按提取省略
Gradle文件操作
确定文件的位置
Project.file(java.lang.Object)
方法
File configFile = file('src/config.xml')
文件集合
Project.files(java.lang.Object[])
方法
可以把集合,迭代变量,map和数组传递给files()方法。它们会被展开,并且内容会转换为 File 实例
FileCollection collection = files('src/file1.txt',
new File('src/file2.txt'),
['src/file3.txt', 'src/file4.txt'],
Paths.get('src', 'file5.txt'))
文件树
按照层次结构划分的文件集合
def myTree = fileTree(dir:'src', excludes:['**/ignore/**', '**/.data/**'])
task copy(type: Copy) {
from myTree
}
include 和 exclude 的含义:
org.gradle.api.tasks.util.PatternFilterable
接口定义的方法
- '*' 匹配任意数量的字符
- '?' 匹配任意一个字符
- '**' 匹配任意数量的目录或文件
task copyAllPdfReportsForArchiving(type: Copy) {
from "${buildDir}/reports"
include "**/*.pdf"
into "${buildDir}/toArchive"
}
Gradle 依赖管理
依赖管理包括两部分,对获取依赖的管理以及生成发布的管理
涉及内容:管理依赖传递,解决版本冲突,使用
多数项目都不是完全独立的,而是需要依赖其他的项目
Gradle从远程仓库,本地目录,或者多项目构建中的另外一个项目获取依赖
依赖类型
常见依赖类型
- 外部模块依赖
- 项目依赖
- 文件依赖
- Client module dependency (外部模块中的一种,修改部分数据)
外部依赖
外部依赖通过group,name,version三个属性标识
dependencies {
compile group: 'org.hibernate', name: 'hibernate-core', version: '3.6.7.Final'
}
快捷方式group:name:version
dependencies {
compile 'org.hibernate:hibernate-core:3.6.7.Final'
}
项目依赖
dependencies {
compile project(':shared')
}
文件依赖
dependencies {
runtime files('libs/a.jar', 'libs/b.jar')
runtime fileTree(dir: 'libs', include: '*.jar')
}
仓库Repositories
外部依赖是通过仓库来查找的
repositories {
mavenCentral()
jcenter()
maven {
url "http://repo.mycompany.com/maven2"
}
}
同时还可以利用Gradle把jar包上传到远程仓库(publication artifacts)
排除依赖传递
gradle dependencies
查看依赖
| | \--- com.android.support:recyclerview-v7:25.3.1 -> 25.4.0
| | +--- com.android.support:support-annotations:25.4.0
| | +--- com.android.support:support-compat:25.4.0
| | | \--- com.android.support:support-annotations:25.4.0
| | \--- com.android.support:support-core-ui:25.4.0
| | +--- com.android.support:support-annotations:25.4.0
| | \--- com.android.support:support-compat:25.4.0 (*)
25.3.1 -> 25.4.0是由于默认会优先版本高的依赖
(*)表示这个依赖被忽略了,这是因为已经有其他依赖传递了这个依赖
compile ('com.android.support:appcompat-v7:22.1.1@aar') {
transitive = true//传递相关的依赖
}
排除模块
dependencies {
compile('org.hibernate:hibernate:3.1') {
//排除某个传递的依赖
exclude module: 'cglib' /通过模块名称
exclude group: 'org.jmock' //通过组名
exclude group: 'org.unwanted', module: 'iAmBuggy' //通过组名和模块名称
}
}
Build生命周期
Gardle所有的构建任务,最终组成一个有向无循环图
在任何任务执行之前,都会先构造出一个完整的依赖图
构建阶段
一个Gradle构建有三个明显的阶段
- 初始化阶段(Initialization),通过
setting.gradle
决定哪些project参加构建,并创建相应的Project实例 - 配置阶段(Configuration),会去执行所有工程的
build.gradle
脚本 - 执行阶段(Execution),根据gradle命令传递过来的task名称,执行相应的任务集合
示例
settings.gradle 文件
println 'initialization phase 1'
build.gradle 文件
println 'configuration phase 2'
task configured {
println 'configuration phase 3'
}
task test {
doLast {
println 'execution phase 5'
}
}
task testBoth {
doFirst {
println `execution phase 6'
}
doLast {
println 'execution phase 7'
}
println 'configuration phase 4'
}
执行命令
gradle test testBoth
执行的顺序就是println字符串最后的数字
可以看到默认的输出是在配制阶段执行的,
对生命周期做出响应
可以实现相应的监听接口或者可以提供一个在收到通知时要执行的闭包
例如 ProjectEvaluationListener 等接口
向具有某个属性的项目添加任务
allprojects {
afterEvaluate { project ->
if (project.hasTests) {
println "Adding test task to $project"
project.task('test') {
doLast {
println "Running tests for $project"
}
}
}
}
}
Project.afterEvaluate()
方法是在project评估(evaluated)后执行的
插件plugin
Gradle的核心是一个框架,所有很有用的特性,例如编译Java代码的能力,都是通过plugin添加的
作用
- 提高复用,减少类似逻辑的配置过程
- 进行更高层次的模块化,加强可读性和组织能力
- 封装必要的逻辑
主要有两类插件,一种是脚本(script),一种是二进制(binary)插件
脚本插件添加进入构建脚本,用来更进一步配置构建,一般通过陈述的方式来控制构建
二进制脚本是实现Plugin接口的类,采用编程的方式来控制构建
使用插件
- Resolve插件,查找到对应版本的插件,添加到脚本的classpath中
- Apply插件,即执行插件
Plugin.apply(T)
Script插件
apply from: 'other.gradle'
这一类的插件都是自行解析的,来自本地的文件系统,或者远程
二进制插件
通过提供 plugin id
(一个全局唯一的标识符)应用插件
有核心插件(JavaPlugin
) 和社区插件之分,核心插件可以使用简称(例如java
)
通过 plugins DSL 使用插件
plugins {
id «plugin id» version «plugin version» [apply «false»]
}
该模块必须在构建脚本的起始位置,除非是存在buildscript {}
代码块,位于它的后
旧的使用插件的方式
apply plugin: 'java'
buildscript块
当构建脚本需要使用外部库时,通过buildscript
方法把已经发布的二进制插件的jar文件添加到脚本的classpath
总之,buildscript块是用来配置Gradle自己需要的仓库和依赖
buildscript {
repositories {
jcenter()
}
dependencies {
classpath "com.jfrog.bintray.gradle:gradle-bintray-plugin:0.4.1"
}
}
apply plugin: "com.jfrog.bintray"
java插件
内部包含的task:
-
compileJava
task that compiles all the Java source files under src/main/java -
compileTestJava
task for source files under src/test/java -
test
task that runs the tests from src/test/java -
jar
task that packages the main compiled classes and resources from src/main/resources into a single JAR named<project>-<version>.jar
-
javadoc
task that generates Javadoc for the main classes
举例:添加JNI编译任务,将so文件打包
String LibPath = "src/main/c++"
task buildJNILib(type: Exec){
workingDir "$LibPath"
commandLine "./buildJNI.sh"
}
clean {
delete fileTree("$LibPath") {include "**/*.so", "**/*.o"}
}
//add so file to the jar as a resource
processResources {
dependsOn buildJNILib
from ("$LibPath"){
include "*.so"
}
}