Contents
- Projects,plugins and tasks
- Hello world
- Build script are code
- Task dependencies
- Flexible task registration
- Manipulating existing tasks
- Using Ant Tasks
- Using methods
- Default tasks
- External dependencies for the build script
- Futher Reading
如何编写Gradle 构建脚本,这里使用了基本的例子解释Gradle 基本的功能 …
它能够帮助你理解基础概念 ..
特别是如果你从其他构建工具迁移到Gradle(例如Ant) 并且你想理解它们的不同以及优势 …
然而,为了从一个标准的项目构建开始,你不需要完全详细的理解这些概念 … 相反你能够进行快速的认识,可以从它开始 step-by-step samples .
Project,plugins and tasks
每一个Gradle 由一个或者多个项目组成 … 什么样的项目取决于你想要Gradle 用来干什么 … 举个例子,一个项目可能是库 或者 web 应用 ..
它可能呈现了为zip 发行文件(根据由其他项目生产的Jar 进行打包而成) … .
一个项目并没有必要一定要构建东西 .. 它可能代表一件可以完成的事情,例如部署你的应用到 阶段或者 生产环境 …
如果你现在看的有一点小小的模糊,混乱,请不要担心 ..
Gradle 的通过约定的构建支持 增加了更多具体的定义 - 决定一个项目到底是什么 …
Gradle 的工作能够在项目上是通过定义一个或者多个任务完成的 ..
一个任务呈现了构建执行的某一个工作的原子块 …
它可能编译某些类 或者创建一个JAR ,生成Javadoc 或者发布某些归档文件到Maven 仓库 ..
通常来说,任务通过应用插件的形式进行提供, 因此你不需要自己去定义它们 .. 仍然,为了给你一个思考,任务到底是什么? 我们将尝试在构建中的一个项目中定义某些简单的任务 ..
Hello world
你能够使用gradle 命令运行Gradle 构建 … gradle 命令在当前的目录中寻找一个叫做build.gradle 的文件 …
我们叫它为构建脚本,尽管严格的说法它是叫做 构建配置脚本,这个构建脚本将会定义一个项目以及它的任务 ..
首先创建一个build.gradle,并创建一个任务 …
tasks.register('hello') {doLast {println 'Hello world!'}}
在命令行环境下,迁移到包含这个脚本的目录并执行构建脚本 去执行任务 …
> gradle -q hello
-q 到底在做什么 ? 在我们的大多数示例中我们都使用了-q 命令行选项 .. 这压制了Gradle 的日志消息 .. 因此仅仅任务的消息将会展示 .. 让我们的输出更加的清晰 .. 你可以不使用此选项 … 查看 Logging 了解更多详情, 关于如何通过命令行选项影响Gradle 的输出 ..
Output of gradle -q hello> gradle -q helloHello world!
这里我们定义了一个任务并执行它 .. 通过gradle hello 命令,那么Gradle 将会执行hello 任务, 这将会执行我们提供的action … 这个action 是一个简单的闭包(其中包含了需要执行的代码) …
如果你任务这看起来类似于 Ant的 targets,你的感觉是正确的 … Gradle 的任务等价于 Ant 的 targets .. 但是正如你所见,它们是更好的 … 我们使用不同的技术 并认为 task 一词比target 表达的含义更加清楚 … 因此我们引入了和Ant的一些技术冲击 .. 因为Ant 调用任务将他们视为命令,例如 javac / copy ,任务 …
因此当我们在谈论任务时,我们总是描述的是Gradle 的任务,它们等价于Ant的Targets .
如果我们谈论Ant 任务(Ant commands),我们会显式的说明这是Ant 任务 …
Build scripts are code
Gradle 的构建脚本让你能够完全得到Groovy 和Kotlin 的支持 … 作为一个开胃菜,我们可以先看一看:
使用Groovy define Gradle 的 任务
tasks.register('upper') {doLast {String someString = 'mY_nAmE'println "Original: $someString"println "Upper case: ${someString.toUpperCase()}"}}
Output of gradle -q upper> gradle -q upperOriginal: mY_nAmEUpper case: MY_NAME
或者
tasks.register('count') {doLast {4.times { print "$it " }}}
Output of gradle -q count> gradle -q count0 1 2 3
任务依赖
你可能会想到,你能够定义任务依赖于那些任务
tasks.register('hello') {doLast {println 'Hello world!'}}tasks.register('intro') {dependsOn tasks.hellodoLast {println "I'm Gradle"}}
Output of gradle -q intro> gradle -q introHello world!I'm Gradle
懒依赖,其他任务可以不存在
tasks.register('taskX') {dependsOn 'taskY'doLast {println 'taskX'}}tasks.register('taskY') {doLast {println 'taskY'}}
Output of gradle -q taskX> gradle -q taskXtaskYtaskX
例如taskX的依赖是taskY,它们声明是随意的,任务依赖详情在这里 .
Flexible task registration
Groovy / kotlin 的能力不仅仅被用来定义任务做什么 .. 例如,你能够使用它去注册相同类型的多个任务(在循环中) …
4.times { counter ->tasks.register("task$counter") {doLast {println "I'm task number $counter"}}}
或者 kotlin
repeat(4) { counter ->tasks.register("task$counter") {doLast {println("I'm task number $counter")}}}
管理 / 操作存在的任务
4.times { counter ->tasks.register("task$counter") {doLast {println "I'm task number $counter"}}}tasks.named('task0') { dependsOn('task2', 'task3') }
一旦任务注册,它们能够通过API 进行访问,例如 你能够动态的增加依赖给任务 ..
在运行时,Ant 不允许类似这样的事情 …
Output of gradle -q task0> gradle -q task0I'm task number 2I'm task number 3I'm task number 0
或者你能够为存在的任务增加行为
tasks.register('hello') {doLast {println 'Hello Earth'}}tasks.named('hello') {doFirst {println 'Hello Venus'}}tasks.named('hello') {doLast {println 'Hello Mars'}}tasks.named('hello') {doLast {println 'Hello Jupiter'}}
> gradle -q helloHello VenusHello EarthHello MarsHello Jupiter
那么这个任务具有4个动作 …
doFirst / doLast 能够执行多次 … 它们增加动作到任务动作列表的前面或者结束 …
动作列表中的所有动作依次执行 …
使用Ant 任务
Ant 任务是Gradle中的一等公民 .. Gradle 提供了对Ant 任务优秀的集成(通过简单的依赖于Groovy) …
Groovy 附带了出色的 AntBuilder .
从Gradle 中使用Ant 任务是非常便利的并且比使用build.xml中的Ant 任务更强大 ..
Ant 也可以通过kotlin 进行使用, 例如学习如何执行Ant 任务并如何访问Ant 属性 …
Using AntBuilder to execute ant.loadfile target
tasks.register('loadfile') {doLast {def files = file('./antLoadfileResources').listFiles().sort()files.each { File file ->if (file.isFile()) {ant.loadfile(srcFile: file, property: file.name)println " *** $file.name ***"println "${ant.properties[file.name]}"}}}}
> gradle -q loadfile*** agile.manifesto.txt ***Individuals and interactions over processes and toolsWorking software over comprehensive documentationCustomer collaboration over contract negotiationResponding to change over following a plan*** gradle.manifesto.txt ***Make the impossible possible, make the possible easy and make the easy elegant.(inspired by Moshe Feldenkrais)
关于在gradle 构建脚本中大量使用 Ant,可以从这里查看 ..
Using methods
Gradle 可扩展您如何组织构建逻辑。
例如为刚才的例子抓取一个方法:
tasks.register('checksum') {doLast {fileList('./antLoadfileResources').each { File file ->ant.checksum(file: file, property: "cs_$file.name")println "$file.name Checksum: ${ant.properties["cs_$file.name"]}"}}}tasks.register('loadfile') {doLast {fileList('./antLoadfileResources').each { File file ->ant.loadfile(srcFile: file, property: file.name)println "I'm fond of $file.name"}}}File[] fileList(String dir) {file(dir).listFiles({file -> file.isFile() } as FileFilter).sort()}
输出同上 …
然后将会看到 这些方法几乎在当前多项目构建中的所有子项目中共享 …
如果你的构建逻辑变得很复杂,Gradle 提供了你其他非常方便的方式去组织它 …
查看另一篇文章了解 … Organizing Gradle Projects
默认任务
Gradle 允许你 定义一个或者多个默认任务(如果在构建时没有指定运行任务) …
defaultTasks 'clean' , 'run'tasks.register('celan') {doLast {println Cleaning!'}}tasks.register('run') {doLast {println 'Default Running!'}}tasks.register("other") {doLast {println "I'm not a default task!"}}
如果执行 gradle -q
那么将输出:
> gradle -q
Default Cleaning!
Default Running!
这完全等价于 gradle clean run , 在多项目构建中子项目能够有自己的指定的默认任务 ..
如果子项目没有指定默认任务, 那么将会使用父项目的默认任务(如果定义) ….
构建脚本的外部依赖
处理直接操作脚本类路径之外,建议应用自带类路径的插件 .. 对于自定义构建逻辑, 推荐使用自定义插件 …
如果你的构建脚本需要使用外部库,你能够将他们增加到脚本的类路径上 (在构建脚本中) …
通过buildscript() 方法配置构建脚本,传递一个闭包用来声明构建脚本类路径 …
声明构建脚本的类路径
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath group: 'commons-codec', name: 'commons-codec', version: '1.2'
}
}
这个方法将会配置一个代理对象,类型为 ScriptHandler, 你能够通过 classpath 配置增加类路径依赖 ..
这等价于在Java 编译类路径上声明的依赖相同方式 …
你能够使用任何依赖类型,除了项目依赖 …(因为类路径不一致) ..
当你在构建类路径上声明了依赖,你能够使用这些类到构建脚本中 …
例如:
import org.apache.commons.codec.binary.Base64
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath group: 'commons-codec', name: 'commons-codec', version: '1.2'
}
}
tasks.register('encode') {
doLast {
def byte[] encodedString = new Base64().encode('hello world\n'.getBytes())
println new String(encodedString)
}
}
导入apache的计算库进行使用 …
Output of gradle -q encode
> gradle -q encode
aGVsbG8gd29ybGQK
对于多项目构建,单个项目的buildscript项目上声明的依赖 .. 同样对它的所有子项目的buildscript 脚本有效 …
构建脚本依赖也可以抽象为一个Gradle plugins …
请考虑 Using Gradle Plugins[TODO] 了解gradle 的插件信息 …
每一个项目会自动包含一个 BuildEnvironmentReportTask 类型的 buildEnvironment 任务 … 它能够执行去报告构建脚本依赖解析情况 ..
