项目与脚本文件html
当咱们执行gradle
命令的时候,Gradle会在你执行命令的目录下寻找一个名为build.gradle
的文件,这个文件就是Gradle的脚本文件,咱们全部的脚本、配置信息都写在这里面,而且一个目录下只能有一个脚本文件。java
脚本块android
一个build.gradle文件由若干个指定的脚本块组成,每个脚本块都表明着不一样的功能,Gradle内置了好几种脚本块供咱们使用,而且脚本块能够嵌套使用,详情能够查看官方文档,咱们来看一段脚本:网络
buildscript { repositories { jcenter() } dependencies { classpath 'com.android.tools.build:gradle:1.2.3' } } allprojects { repositories { jcenter() } }
buildscripte
脚本块指定脚本文件所使用的插件来源和远程仓库app
repositories
脚本块指定了所使用的远程仓库框架
dependencies
指定了相关的依赖关系maven
allprojects
脚本块为全部子项目指定配置信息。ide
在Gradle中,每个项目都会有个名为project
的实例与之对应,而以前咱们说过一个脚本文件就表明着一个项目,因此实际上咱们在脚本文件中编写的脚本最后都是委托给project
对象处理的,即project
和build.gradle
是一对一的关系。咱们能够在脚本文件中经过该实例访问项目脚本的属性、方法和任务,例如project.name
能够访问项目的名称、project.version
能够访问项目的版本名称、project.rootProject
能够访问该项目的父项目等,总之project
几乎包含了全部脚本的内容。测试
在编写脚本的时候,虽然在脚本中直接写属性名称是能够的,可是经过
project
引用属性名称可以让你的脚本更加清晰易懂,例如project.name
会比name
更容易让人知道这是一个项目的名称。gradle
在Gradle中,属性分为两种,一种是系统属性,它能够被JVM使用,而另外一种咱们姑且称之为项目属性,它用于项目的配置。
系统属性是能够直接被JVM所使用的,咱们能够用它来设置JVM的相关参数,下面按照读取属性的优先级由高到低的方式列出来全部定义方式:
经过命令行执行gradle -D name=value
方式定义系统属性,例如gradle -D org.gradle.java.home=/jdk
定义了Gradle运行时所依赖的Java路径。
在用户目录下建立gradle.properties
文件,而后以systemProp.name=value
方式定义系统属性,例如用户目录为/home/jerry
,那么咱们就在该目录下建立gradle.properties
文件,而且在文件内定义org.gradle.java.home=/jdk
,这样Gradle因此需的Java路径就被定义了。
在项目目录下建立gradle.properties
文件,而后以systemProp.name=value
方式定义系统属性,例如项目目录为/HelloGradle
,那么咱们就在该目录下建立gradle.properties
文件,而且在文件内定义org.gradle.java.home=/jdk
,这样Gradle因此需的Java路径就被定义了。
在开发项目的时候咱们常常会遇到各类项目属性的配置,例如项目名称、项目版本、打包路径、渠道名称等等,对于这些属性,Gradle为咱们提供了多种方式来定义,下面按照读取属性的优先级由高到低列出来全部定义方式:
经过project.ext.name=value
方式定义属性,例如project.ext.channel='360'
定义渠道名称为360。
经过命令行执行gradle -P name=value
方式定义属性,例如gradle -P channel=360
定义渠道名称为360。
在用户目录下建立gradle.properties
文件,而后以name=value
方式定义系统属性,例如用户目录为/home/jerry
,那么咱们就在该目录下建立gradle.properties
文件,而且在文件内定义channel=360
,这样就定义了渠道名为360。
在项目目录下建立gradle.properties
文件,而后以name=value
方式定义系统属性,例如项目目录为/HelloGradle
,那么咱们就在该目录下建立gradle.properties
文件,而且在文件内定义channel=360
,这样就定义了渠道名为360。
在脚本中读取属性十分容易,对于系统属性,咱们能够经过System.properties['name']
方式读取,对于项目属性则经过project.name
方式读取:
build.gradle:
println System.properties['org.gradle.java.home'] println project.channel
在构建项目的时候,咱们若是对整个构建过程进行分解的话,大概能够分解成编译代码、打包、生成文档等过程,Gradle用task来表明这些构建过程,每一个步骤对应一个task。若是把项目比喻成一个类,那么task就是类中的方法,咱们也能够认为task就是构建项目的原子操做,再细分下去就没有意义了。
Hello world
首先咱们来定义一个打印Hello world
的task,在build.gradle
中编写以下脚本:
build.gradle:
task Hello { doFirst { println 'Hello world' } }
而后咱们执行gradle -q Hello
命令,-q
参数用于过滤多余信息而已,并非必须的,执行命令后咱们会看到以下输出:
> gradle -q Hello Hello world
执行顺序
经过doFirst
和doLast
来控制task内部脚本的执行顺序
task MyTask { doLast { println 'Execute doLast A' } doFirst { println 'Execute doFirst A' } } MyTask.doFirst { println 'Execute doFrist B' } MyTask.doLast { println 'Execute doLast B' }
执行gradle -q MyTask
命令,咱们会看到以下输出:
> gradle -q MyTask Execute doFrist B Execute doFirst A Execute doLast A Execute doLast B
从执行结果,咱们能够看出MyTask的行为被咱们修改了,也就是说Gradle容许你在定义完task以后动态添加更多的行为,其中MyTask.doFirst {...}
新增的doFrist
会被添加到执行队列的头部,而MyTask.doLast {...}
新增的doLast
会被添加到执行队列的尾部,因此咱们会看到先打印Execute doFirst again
,最后打印Execute doLast again
。
若是咱们不关心脚本的执行顺序,咱们能够用<<
来快速定义task,<<
等价于doLast
,也就是说下面的两种定义方式是等价的:
task Task1 << { println 'Hello' }
task Task2 { doLast { println 'Hello' } }
动态定义
3.times { i -> task "MyTask$i" << { println "My task $i" } }
> 提示:这段代码是Groovy的语法,它的做用至关于Java的`for(int i = 0; i < 3; i++)`。
执行`gradle -q MyTask0 MyTask1 MyTask2`命令,咱们会看到以下输出: ~~~ > gradle -q MyTask0 MyTask1 MyTask2 My task 0 My task 1 My task 2 ~~~
task之间能够经过关键字dependsOn
指定依赖关系,好比负责打包的task A依赖于编译class文件的task B,这时候当咱们容许task A的时候,task B会被先执行,而后才执行task A。
单个依赖
首先咱们来看一个最简单的依赖关系,咱们称他为单个依赖,由于一个task的运行只依赖于另外一个依赖:
task task2 << { println 'Execute task2' } task task1(dependsOn: task2) << { println 'Execute task1' }
执行gradle -q task1
命令,咱们会看到以下输出:
> gradle -q task1 Execute task2 Execute task1
多个依赖
若是咱们想指定更多的依赖关系的话,能够用”[ ] “定义多个task,看以下脚本:
task task2 << { println 'Execute task2' } task task3 << { println 'Execute task3' } task task4 << { println 'Execute task4' } task task1(dependsOn: [task2, task3, task4]) << { println 'Execute task1' }
执行gradle -q task1
命令,咱们会看到以下输出:
> gradle -q task1 Execute task2 Execute task3 Execute task4 Execute task1
在定义task的时候,咱们能够经过关键字type
为task指定一种类型,task会根据不一样类型具备不一样的功能,而且Gradle内置了不少实用的task类型,好比Copy
类型让task具备拷贝文件的功能,task的类型指定有点像继承的关系:
task copyFile(type: Copy) { from '/home/xxx/' into '/home/yyy/' include 'file1.txt' rename 'file1.txt', 'file2.txt' }
执行gradle copyFile
命令,而后该task就会从/home/xxx/
目录下将file1.txt
文件复制到/home/yyy/
目录下,而且重命名为file2.txt
。更多的task类型能够查看Gradle的官方文档。
最后你能够经过gradle tasks
命令查看有多少的task可用,而且父项目能够直接操做子项目的task,反过来却不行
不少时候咱们的项目会依赖到一些第三方库,Gradle为咱们提供了3种方式配置依赖项。
1.依赖本地文件
假设咱们在项目的libs
目录下有个库叫作mylib.jar
,咱们能够经过如下方式让项目依赖这个库:
dependencies { compile files('libs/mylib.jar') }
经过上面的脚本,咱们的项目在编译的时候会自动依赖mylib.jar
库。
若是你的libs
下面有好几个文件须要依赖,能够经过如下方式让项目一次性依赖全部库文件:
dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) }
2.依赖网络库
咱们能够经过Gradle依赖网络上的第三方库,这些库通常都会保存在一个网络仓库中,例如maven
或jcenter
,使用网络上的库带来的好处就是咱们能够简单修改版本号就能够更新到最新版的库,而且也省去了咱们手动去复制文件。
想要依赖网络仓库里面的第三方库,咱们须要知道3个信息:group、name和version。
group:第三方库的组织名称。
name:第三方库的名称。
version:第三方库的版本。
如今假设咱们有一个第三方库在maven
仓库下,它的信息以下:
group: com.hjdzone.lib name: mylib version: 1.0.0
想要使用这个第三方库,咱们能够编写以下脚本:
repositories { mavenCentral() } dependencies { compile 'com.hjdzone.lib:mylib:1.0.0' }
严格上来讲Gradle只是一个构建框架,并无提供任何真正的构建功能,构建任务实际上是经过插件实现的,不一样的插件会根据不一样构建需求定义各类task供咱们使用,而且Gradle已经提供了大量的插件,大多数状况下咱们无需本身重写plugin,只须要简单地指定plugin就可使用了。其实在前面的例子中咱们就用到了名为java
的插件,接下来咱们就继续以以前的HelloGradle
项目为例,介绍插件的用法。
首先你必须在build.gradle
中声明使用java
插件:
apply plugin: 'java'
Gradle遵循约定优于配置
的原则,因此你的项目结构必须符合插件的要求才可以被插件所识别,例如java
插件要求咱们的代码必须放在src/main/java
目录下,资源文件必须放在src/main/resources
目录下,测试代码必须放在src/test/java
目录下,测试资源必须放在src/test/resources
目录下:
HelloGradle build.gradle src/main/java/Main.java src/main/resources/logo.png src/test/java/TestMain.java src/test/resources/logo.png
java
插件提供了各类脚本块用于配置项目,例如你能够经过插件提供的脚本块sourceSets
修改项目的结构:
sourceSets { main { java './java' resources './resources' } }
该脚本把代码目录指定到了./java
目录下,把资源文件目录指定到了./resources
目录下。
java
插件为咱们提供了一套完整的构建任务,咱们能够经过执行gradle tasks
命令查看可用的task:
参考:Gradle 快速入门