Gradle-构建脚本
构建语言
Gradle提供了一种领域特定语言,目前同时支持 Groovy 和 Kotlin 。
在 Groovy 构建脚本中(.gradle) 你可以使用任何 Groovy 元素。
在 Kotlin 构建脚本中 (.gradle.kts) 你可以使用任何 Kotlin 元素。
项目(Project) 和 任务(Task)
Gradle 构建的一切都是基于 两个概念 :项目 和任务;
一个构建是由一个或多个项目组成的。项目的概念比较抽象,你可以创建一个 Project 用于生成一个 jar,也可以定义个项目用于生成 war 包,还可以定义一个项目用于发布上传你的 war等。
一个项目就是在你的业务范围内,被你抽象出来的一个独立的模块,你可以根据工程的实际情况抽象归类,最后这一个个的 项目组成了整个 Gradle 构建。
一个 项目又包含很多个任务,每个项目是由一个或多个任务组成的。任务就是一个操作,一个原子性的操作。比如打个 jar 包,复制一份文件,编译一次 java 代码等,这就是一个任务。
build.gradle & Project API
每个项目都有一个 build.gradle 文件,该文件是该项目的构建入口,可以在这这个文件里对该项目进行配置,比如配置版本,需要哪些插件,依赖哪些库等。
我们通过配置这个文件描述我们的构建,这其实就是一个配置脚本。
每一个脚本在执行的时候都会被关联到一个 Project 实例上。
在构建生命周期的初始化阶段,Gradle 会为每个项目创建一个 Project 实例,并根据 build.gradle的内容配置这个实例。
也就是说每个 build.gradle 的配置都会被配置到 Project 实例上。
实际上,build.gradle 中几乎所有的顶级属性和代码块都是 Project 类的 API,
下面通过访问 Project.name 属性验证一下。
在 build.gradle
println "name is $name"
println "project.name is ${project.name}"
执行 build 任务,你将会得到下面的输出,输出的值都是 项目的名字
第一条语句使用的是Project的顶级属性。
第二条语句使用的 project 属性 可以在脚本的任何地方访问,它代表的是当前脚本的Project对象。
只有在你定义了和Project的成员(方法,属性)同名的时候才需要使用 project ,其他时候直接使用 名称即可访问,例如第一条语句。
一个构建是由多个Project组成的,是通过项目树的形式表示的。
可以在项目树的根项目对所有的项目统一配置一些配置。例如,应用的插件,依赖的 Maven 中心库等。
为所有子项目配置仓库为 jcenter
subprojects{
repositories {
jcenter()
}
}
也可以为所有子项目配置 使用 Java 插件
subprojects{
apply plugin:'java'
repositories {
jcenter()
}
}
除了 subprojects 还有 allprojects ,从名字就可以看出来这不仅是对子项目的配置而是对所有项目的配置。
这两个配置其实是两个方法,接受一个闭包参数,对项目进行遍历,遍历的过程中调用我们自定义的闭包,所以我们可以在闭包里配置,打印,输出或者修改 Project 的属性。
Project 的属性
Project 对象的属性在 脚本全局都是可以使用的。
下面列出一些常用的属性,更全的属性可以在 Project API 中查询。
名字 | 类型 | 默认值 |
---|---|---|
project | Project | Project 实例 |
name | String | 项目名字 |
path | String | 项目的绝对路径 |
description | String | 项目描述 |
projectDir | File | 配置脚本所在的目录 |
buildDir | File | projectDir/build 输出目录 |
group | Object | 未指定 |
version | Object | 未指定 |
ant | AntBuilder | AntBuilder 实例 |
settings.gradle
这是一个设置文件,用于初始化以及项目树的配置。设置文件的默认名字就是 settings.gradle,放在根项目目录下。
关于构建生命周期和 settings.gradle 更详细的可以看我的这篇文章 构建生命周期
script API
当 Gradle 执行 Groovy 脚本(.gradle)时,会编译脚本到实现了 Script 的类中。
也就是说,Script 接口中的所有属性和方法都可以在脚本中使用。
当 Gradle 执行 Kotlin 脚本(.gradle.kts)时,会编译脚本到 KotlinBuildScript的子类中。
也就是 KotlinBuildScript 类中的所有属性和方法都可以在脚本中使用。
更详细的可以参考 KotlinSettingsScript 和 KotlinInitScript 类,分别用于设置脚本和init脚本。
脚本即代码
虽然我们在一个 Gradle 文件里写脚本,但是我们写的都是代码,这一点一定要非常的清楚。
我们写的确实是脚本,但不是简单的脚本。在脚本里可以定义 Class ,内部类,导入包,定义方法、常量、接口等。
不要把它当作简单的脚本,我们可以灵活的使用 Java ,Groovy ,Kotlin 和 Gradle.
例如 定义一个获取当前日期的方法
def buildTime(){
def date = new Date()
def formattedDate = date.format('yyyyMMdd')
return formattedDate
}
变量 & 额外的自定义属性
Gradle 支持两种变量 :局部变量和自定义属性
局部变量
局部变量使用 def 关键字声明,局部变量只能在声明的范围内可见。
def myName = '佛系编码'
额外的自定义属性
Gradle 领域模型中 所有的对象 都可以添加额外的自定义属性。
通过对象的 ext 属性实现对自定义属性的添加,访问,设置值的操作。
添加之后可以通过 ext 属性对自定义属性读取和设置,也可以同时添加多个自定义属性。
//为 project 添加一个 age 属性 并赋值 20
ext.age = 20
//为 project 添加两个属性
ext{
phone =110
address = '404'
}
task myTask {
//为 myTask 任务添加属性
ext.myProperty = "myValue"
}
task extra{
doLast{
println "project : age= ${project.ext.age},phone= ${project.ext.phone} , address = ${project.ext.address}"
println "myTask : ${myTask.myProperty}"
}
}
创建一个任务
task hello {
doLast {
println 'Hello world!'
}
}
这里的 task 看着像一个关键字,实际上是一个方法,这个方法的原型是 TaskContainer.create()
任务的创建就是使用这个方法给 Project 添加一个 Task 类型的属性;所以才能使用任务名字引用一些API,例如为任务添加额外的属性。
任务依赖和任务排序
一个任务可以依赖其他任务或者在其他任务执行后再执行。
Gradle 确保在执行任务时遵守所有任务依赖性和排序规则,以便在所有依赖项和任何 “必须运行” 的任务执行之后再执行任务。
Gradle 为我们提供了几个方法用来控制任务的依赖和排序,就是下面这几个
- Task.dependsOn(java.lang.Object[])
- Task.setDependsOn(java.lang.Iterable)
- Task.mustRunAfter(java.lang.Object[])
- Task.setMustRunAfter(java.lang.Iterable)
- Task.shouldRunAfter(java.lang.Object[])
- Task.setShouldRunAfter(java.lang.Iterable)
这些方法可以接收 任务,任务名字,路径等,具体参数可以在 Task文档 里查看
task hello {
doLast {
println 'Hello world!'
}
}
task taskX {
dependsOn hello
doLast{
println "I'm $name."
}
}
task taskY {
doFirst {
println "I'm $name."
}
}
如果 taskX 要依赖 taskY 的话,并不能直接引用,因为 taskY 是在 taskX 之后定义的。
task taskX {
dependsOn 'taskY'
doLast{
println "I'm $name."
}
}
默认任务
在没有指定执行任务的时候,可以在脚本中定义默认任务,使用 defaultTasks 方法
这个方法接收 字符串参数,传入任务的名称即可·
defaultTasks 'hello','taskY'
外部依赖
用添加外部依赖,必须添加依赖所在仓库。例如 jcenter,maven,google等
目前支持很多类型的仓库,基本上都在这里列出来,可以查看 仓库类型
添加 google 仓库
allprojects {
repositories {
mavenCentral()
google()
jcenter()
}
}
在 Android 的项目中,这都是放在根项目里的 allprojects 方法里,对所有项目统一配置
添加外部依赖
dependencies {
implementation 'io.reactivex.rxjava2:rxjava:2.1.2'
}
在 Android 中依赖的添加放在了各个module 中,按需添加,哪个模块需要在哪个模块的构建脚本里添加。
依赖属性分为三部分
- group: 这个属性用来标识一个组织、公司或者项目,可以用点号分隔,例如上面的 io.reactivex.rxjava2
- name: name属性唯一的描述了这个依赖,例如上面的 rxjava
- version: 一个库可以有很多个版本。例如上面的 2.1.2
其中 implementation 为配置项,配置也有很多种类型,下面贴出来一张来自 Google 的说明:详情可以查看这个 依赖项配置
最后是 DSL 的API 地址 https://docs.gradle.org/current/dsl/index.html
Gradle-构建脚本的更多相关文章
- Gradle构建脚本基础
Gradle构建脚本,内部是基于 Groovy 的 DSL(领域特点语言),而Maven是基于XML的,Groovy相比XML更加简洁.灵活和强大. Groovy 因为给 Java 开发人员提供了最大 ...
- 【Gradle】Gradle构建脚本基础
Gradle构建脚本基础 Settings文件 在Gradle中,定义了一个设置文件,用于初始化以及工程树的配置.设置文件的默认名为settings.gradle,放在根工程目录下. 设置文件大多数的 ...
- Android Studio Gradle构建脚本
Gradle是一种依赖管理工具,基于Groovy语言,面向Java应用为主,它抛弃了基于XML的各种繁琐配置,取而代之的是一种基于Groovy的内部领域特定(DSL)语言. 构建工具就是对你的项目进行 ...
- Android Gradle 学习笔记(四):Gradle 构建脚本
本节我们从整体的角度来介绍一下Gradle. 一.setting.gradle 在Gradle中,定义了一个设置文件,用于初始化以及工程树的配置.设置文件的默认的名字就是setting.gradle, ...
- 《Gradle权威指南》--Gradle构建脚本基础
No1: 设置文件默认名是setting.gradle,放在根目录下,大多数作用都是为了配置子工程 No2: 一个Project包含很多个Task.Task就是一个操作,一个原子性的操作.其实它是Pr ...
- Gradle:构建脚本概要
一.构建块 1.每一个构建块都包括三个基本构建块:project.task和property: 2.每一个构建块包括至少一个project,进而又包括一个或多个task: 3.project和task ...
- 【转载】Gradle学习 第六章:构建脚本基础
转载地址:http://ask.android-studio.org/?/article/11 6.1. Projects and tasks 项目和任务Everything in Gradle si ...
- gradle构建工具
在使用android studio开发android程序时,as就是基于gradle进行构建的,我们只需要通过run就可以编译.打包.安装,非常方便,但是究竟gradle是什么呢? 一.java构建 ...
- Gradle 1.12 翻译——第十三章 编写构建脚本
有关其它已翻译的章节请关注Github上的项目:https://github.com/msdx/gradledoc/tree/1.12,或訪问:http://gradledoc.qiniudn.com ...
- Gradle系列之构建脚本基础
原文发于微信公众号 jzman-blog,欢迎关注交流. 前面两篇文章分别介绍了 Gradle 基础知识以及 Groovy 相关基础知识,这也是学习 Gradle 所必需了解的,文章链接如下:: Gr ...
随机推荐
- scrapy的一个简单小项目
使用scrapy抓取目标url下所有的课程名和价格,并将数据保存为json格式url=http://www.tanzhouedu.com/mall/course/initAllCourse 观察网页并 ...
- Python的import机制
模块与包 在了解 import 之前,有两个概念必须提一下: 模块: 一个 .py 文件就是一个模块(module) 包: __init__.py 文件所在目录就是包(package) 当然,这只是极 ...
- Streams:深入理解Redis5.0新特性
概述 相较于Redis4.0,Redis5.0增加了很多新的特性,而streams是其中最重要的特性之一.streams是redis 的一种基本数据结构,它是一个新的强大的支持多播的可持久化的消息队列 ...
- Rust 入门 (四)
所有权是 rust 语言独有的特性,它保证了在没有垃圾回收机制下的内存安全,所以理解 rust 的所有权是很有必要的.接下来,我们来讨论所有权和它的几个特性:借用.切片和内存结构. 什么是所有权 Ru ...
- 【ASP.NET Core学习】Web API
这里介绍在ASP.NET Core中使用Web API创建 RESTful 服务,本文使用VSCode + NET Core3.0 创建简单Rest API 格式化输出 JSON Patch请求 Op ...
- 前端vue如何下载或者导出word文件和excel文件
前端用vue怎么接收并导出文件 window.location.href = "excel地址" 如果是 get 请求,那直接换成 window.open(url) 就行了 创建一 ...
- nginx集群架构
Linux集群从功能分类 高可用集群,高可用集群通常为俩台服务器,一台工作,另一台冗余,当提供服务器的服务器宕机时候,冗余服务器将接替宕机的服务器继续提供服务.实现高可用的集群开源软件有Heatbea ...
- Python 代码块
代码块 骏马金龙https://www.cnblogs.com/f-ck-need-u/p/9925021.html https://www.cnblogs.com/jin-xin/articles/ ...
- 转:轻松把玩HttpClient之封装HttpClient工具类(一)(现有网上分享中的最强大的工具类)
搜了一下网络上别人封装的HttpClient,大部分特别简单,有一些看起来比较高级,但是用起来都不怎么好用.调用关系不清楚,结构有点混乱.所以也就萌生了自己封装HttpClient工具类的想法.要做就 ...
- SDK版本管理
在编写API时,有些API被废弃.如何在使用者调用该API时就报出已经被废弃呢? 方法如下: 1.在OC中 在@interface里将要废弃的方法引用后边加上 __attribute__((depre ...