Gradle入门
Table of Contents
Gradle在语法上是基于Groovy语言的,在项目管理上是基于Ant和Maven概念的项目自动化建构工具
Groovy 是一种基于JVM的敏捷开发语言 可以简单的理解为强类型语言java的弱类型版本
环境
- Gradle 运行依赖JVM,也就是java运行的环境。所以要安装jdk和jre
- 到Gradle官网现在Gradle的压缩包
- 下载压缩包后,解压,然后配置环境变量
MacOS 下配置。在 ~/.bash_profile 中添加如下代码
#gradle 注意gradle-2.14.1是自己解压的路径 export GRADLE_HOME=${HOME}/gradle-2.14.1 PATH=${PATH}:${GRADLE_HOME}/bin export PATH
命令行输入 gradle -v 查看是否安装成功
$ gradle -v ------------------------------------------------------------ Gradle 2.14.1 ------------------------------------------------------------ Build time: 2016-07-18 06:38:37 UTC Revision: d9e2113d9fb05a5caabba61798bdb8dfdca83719 Groovy: 2.4.4 Ant: Apache Ant(TM) version 1.9.6 compiled on June 29 2015 JVM: 1.8.0_111 (Oracle Corporation 25.111-b14) OS: Mac OS X 10.12.2 x86_64
hello world
创建一个 test_gralde 文件夹。然后在文件夹里面创建一个 build.gradle 文件。在build.gradle中添加如下代码:
task helloworld{ doLast{ println'Hello World!' } } #后者等同于下面的代码, task helloworld2 <<{ println "Hello World!" }
- 这个构建脚本定义一个 任务 Task ,任务名字叫 helloworld
- 任务helloworld添加了一个 动作 Action
- 这是一段Groovy语言实现的闭包, doLast 就意味着在 Task执行完毕之后 要 回调doLast的这部分闭包 的代码实现
- 第二个方法中的 << 表示向 helloworld中加入执行代码
- 语法部分,基本是Groovy语法,加上一些DSL的约定
文件名不要乱起,因为执行gradle命令的时候,会默认加当前目录下的build.gradle脚本文件 当然可以通过 -b 参数指定想要加载执行的文件
执行流程
Gradle是一种 声明式 的 构建工具 。在执行时,Gradle并不会一开始便顺序执行build.gradle文件中的内容,而是分为两个阶段:
- 第一个阶段是配置阶段:Gradle将读取所有build.gradle文件的所有内容来配置Project和Task等,比如
- 设置Project和Task的Property
- 处理Task之间的依赖关系
- ……
- 第二个阶段才是实际的执行阶段
和Maven一样,Gradle只是提供了构建项目的一个框架,真正起作用的是Plugin Gradle在默认情况下提供了许多常用的Plugin,其中包括有构建Java项目的Plugin,还有Android等 与Maven不同的是,Gradle不提供内建的项目生命周期管理,只是java Plugin向Project中添加了许多Task,这些Task依次执行,营造了一种如同Maven般项目构建周期
现在来看一个基本结构的Android多Moudule(也就是gradle中的多Project Multi-Projects Build)的基本项目结构:
├── app #Android App目录 │ ├── app.iml │ ├── build #构建输出目录 │ ├── build.gradle #构建脚本 │ ├── libs #so相关库 │ ├── proguard-rules.pro #proguard混淆配置 │ └── src #源代码,资源等 ├── module #Android 另外一个module目录 │ ├── module.iml │ ├── build #构建输出目录 │ ├── build.gradle #构建脚本 │ ├── libs #so相关库 │ ├── proguard-rules.pro #proguard混淆配置 │ └── src #源代码,资源等 ├── build │ └── intermediates ├── build.gradle #工程构建文件 ├── gradle │ └── wrapper ├── gradle.properties #gradle的配置 ├── gradlew #gradle wrapper linux shell脚本 ├── gradlew.bat ├── LibSqlite.iml ├── local.properties #配置Androod SDK位置文件 └── settings.gradle #工程配置
如果抽象成Gradle多Project的样子:
├── app │ ├── build.gradle #构建脚本 ├── module │ ├── build.gradle #构建脚本 ├── build.gradle #工程构建文件 ├── gradle │ └── wrapper #先不去管它 ├── gradle.properties #gradle的配置 ├── gradlew #gradle wrapper linux shell脚本 ├── gradlew.bat └── settings.gradle #工程配置
- Gradle为每个项目都创建了一个 build.gradle 文件,Gradle提供了强大的多Project构建支持。
- 要创建多Project的Gradle项目,需要在 根Project 中加入名为 settings.gradle 的配置文件
- 该文件应该包含各个子Project的名称
- Gradle中的Project可以简单的映射为Maven中的module
- 在最外层的build.gradle。一般干得活是: 配置其他子Project的
- 比如:为子Project添加一些属性
配置语法
Gradle提供了一整套DSL,所以在很多时候写的代码似乎已经脱离了groovy 但是在底层依然是执行的groovy所以很多语法还是Groovy的语法规则
看一个androidStudio中app下的build.gradle的配置:
apply plugin: 'com.android.application' android { compileSdkVersion 25 buildToolsVersion "25.0.0" defaultConfig { applicationId "me.febsky.demo" minSdkVersion 15 targetSdkVersion 25 versionCode 1 versionName "1.0" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" } buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } } dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) compile 'com.android.support:appcompat-v7:25.1.0' }
- apply plugin: 'com.android.application' 这里的apply是一个函数,实际上调用的是 apply(plugin: 'com.android.application')
- plugin: 'com.android.application' 表示的是一个map类型,实际上应该是 [plugin: 'com.android.application']
1. 方法调用,圆括号可以省略 2. 如果方法参数是个Map,方括号可以省略
闭包
上面的dependencies实际上也是个方法调用,调用的是Project的dependcies方法,但是参数也是一个函数。所以还能写成这样:
#所以代码还能写成这样 dependencies (){ compile fileTree(dir: 'libs', include: ['*.jar']) compile 'com.android.support:appcompat-v7:25.1.0' }
如果闭包是方法的最后一个参数,那么闭包可以放在圆括号外面
Getter 和 Setter
Groovy动态的为每一个字段都会自动生成getter和setter,并且可以通过像访问字段本身一样调用getter和setter
println project.version // Groovy println(project.getVersion()) // Groovy
Project, Task, Action
Gradle的 Project之间的依赖关系 是基于 Task 的,而不是整个Project的
- Project: build.gradle脚本的全部作用,其实就是配置一个Project实例
- build.gradle 中可以隐式的操纵Project实例,比如,apply插件、声明依赖、定义Task等
- apply、dependencies、task等实际上是Project的方法,参数是一个代码块
- 如果需要,也可以显示的操纵Project实例
- 比如:project.ext.myProp = 'myValue'
- build.gradle 中可以隐式的操纵Project实例,比如,apply插件、声明依赖、定义Task等
- Task: 被组织成了一个 有向无环图
- 要么是由不同的Plugin引入的,要么是自己在build.gradle文件中直接创建的
- Gradle保证Task按照 依赖顺序 执行,并且每个Task 最多只被执行一次
Gradle在默认情况下提供了几个常用的Task,比如查看Project的Properties、显示当前Project中定义的所有Task等 可以通过一下命令行查看Project中所有的Task:$ gradle tasks 可以看到,Gradle默认提供了dependencies、projects和properties等Task dependencies用于显示Project的依赖信息,projects用于显示所有Project,包括根Project和子Project,而properties则用于显示一个Project所包含的所有Property
自定义Task
可以自定义一个Task:
task myTask { doFirst { println 'hello' } doLast { println 'world' } }
也显示声明一个Task的类型:
#2 Test文件夹下建一个src目录,建一个dst目录,src目录下建立一个文件,命名为test.txt task copyFile(type: Copy){ from "src" into "dst" }
也可以定义成一段脚本:
#1 task helloWorld << { println "Hello World" }
如果task声明在根Project的build.gradle中的allprojects()方法中,那么这个Task会应用于所有的Project
Task的依赖关系
task taskA << { println 'this is taskA from project 1' } task taskB << { println 'this is taskB from project 1' } taskA.dependsOn taskB
这样如果执行taskA的话,就会先执行taskB
如果是Muliti-Project的模式,依赖关系要带着所属的Project 如taskA.dependsOn ':other-project:taskC' 其中taskC位于和taskA不同的Project中,other-project就是为另外一个项目的名字
GradleWrapper
Wrapper其实就是对Gradle的一层包装,便于在团队开发过程中 统一Gradle构建的版本
提交到git上,然后别人可以下载下来,这样大家都可以使用统一的Gradle版本进行构建,避免因为Gradle版本不统一带来的不必要的问题
生成wrapper
gradle内置了生成wrapper的task,可以命令行执行:
$ gradle wrapper
生成后的目录结构如下:
├── gradle │ └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew └── gradlew.bat
- gradlew 和 gradlew.bat 分别是Linux和Window下的 可执行脚本 :他们的用法和gradle原生命令是一样的
- gradle-wrapper.jar 是 具体业务逻辑实现的jar包 :gradlew最终还是使用 java执行 的这个 jar包 来执行相关gradle操作。
- gradle-wrapper.properties 是 配置文件 :用于配置使用哪个版本的gradle等
gradle-wrapper.properties配置文件
#Sat Jan 21 14:02:40 CST 2017 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists distributionUrl=https\://services.gradle.org/distributions/gradle-2.14.1-bin.zip
- distributionBase: 下载的gradle压缩包解压后存储的主目录
- distributionPath: 相对于distributionBase的解压后的gradle压缩包的路径
- zipStoreBase: 同distributionBase,只不过是存放zip压缩包的
- zipStorePath: 同distributionPath,只不过是存放zip压缩包的
- distributionUrl: gradle发行版压缩包的下载地址,也就是你现在这个项目将要依赖的gradle的版本
生成wrapper时候可以通过指定参数的方式来指定gradle-wrapper.properties内容。