Gradle用户指南之初学者教程(三)

来源:互联网 发布:吾爱源码下载 编辑:程序博客网 时间:2024/05/29 09:09

写在前面的话:
博主最近在学习Android Studio相关的东西。Gradle相对于我这个从Eclipse转过来的Android开发者,也算是一个全新的事物。但它却承担着Android构建系统中相当重要的一环。本着与人方便,自己方便的精神,觉得有必要翻译一下《Gradle User Guide》中的Tutorials相关部分。由于英语水平相当有限,请大家多多指教。

文章地址:http://blog.csdn.net/mikulee/article/details/45478177
英文原文地址:http://gradle.org/docs/current/userguide/tutorial_using_tasks.html
请尊重相关知识版权,谢谢。

第六章. 构建脚本基础

6.1. Projects and tasks(工程和任务)

Gradle中的所有东西都以这两个概念为基础:projects 和 tasks.

每个Gradle构建都以一个或多个projects组合而成。一个project代表的意义依赖于你正在用Gradle处理什么。例如,一个project可能代表一个库(JAR)或网页应用(web application).它可能代表其他项目的库的ZIP压缩包发布版。一个project并不需要代表要构建的什么确切东西,它可能仅仅用来说明某个东西已经完成了,例如发布你的应用到工作或者生产环节去。如果你对这些概念性的东西还不够清楚,请不要紧张。Gradle的构建规则支持添加一个或多个project到底是什么的具体定义。

每个project都是有一个或多个tasks组成。一个task代表一个不可分割的构建工作。它可能编译一些calsses,创建JAR,生成Javadoc,或者发布一些文件到仓库里。

从现在开始,我们将把注意力集中在为一个project构建定义一些简单的tasks.后面的章节会深入学习处理多个projects的projects和tasks。

6.2. Hello world

当你用gradle命令运行一个Gradle构建的时候,gradle命令会在当前目录查找一个命名为build.gradle的文件。我们称呼build.gradle文件为构建脚本(build script),虽然严格来说,它是一个构建配置脚本。这个构建脚本定义了一个project及一些和它相关的的tasks.

为了验证这个,创建一个build.gradle文件,并添加下面的构建脚本。

例子 6.1. 你的第一个构建脚本
build.gradle

task hello {    doLast {        println 'Hello world!'    }}

在命令行shell中,进入到包含这个build.gradle的目录,运行gradle -q hello去执行这个构建脚本。

例子 6.2. 运行一个构建脚本
gradle -q hello的输出

> gradle -q helloHello world!

这里发生了什么?这个构建脚本定义了一个单独的命名为hello的任务,并添加了一个动作进去。当你运行gradle hello的时候,Gradle执行了这个hello任务,继而执行了你提供的动作。这个动作是一个包含一些执行Groovy代码的闭包。

如果你觉得这个看起来像Ant target,你是对的。Gradle task任务和Ant target是差不多的,但你会看到,它们(Gradle)更强大.我们使用了一个和Ant不一样的专业术语,因为我们觉得task这个词比target更加传神。不幸的是,这是一个和ant冲突的术语,例如Ant中调用自己的命令,例如javac或copy,tasks。所以当我们提到tasks时,我们要说的是Gradle tasks.如果我们要说 Ant tasks(Ant 命令)时,我们会明确的说 Ant task。

6.3. A shortcut task definition(定义任务的快捷方式)

这里有一个快速定义一个task的方法,非常简洁,例如要定义上面提到的hell task。
例子6.3.一个task定义快捷方式
build.gradle

task hell << {    println 'Hello world!'}

同样,我们定义了一个名称为hello的可执行任务,其中包含了一个单独的闭包。我们将会在整个用户指南中使用这种风格的task定义方式。

6.4. Build scripts are code(构建脚本是代码)

Gradle构建脚本给予你一个全功能的Groovy。作为引子,请看下面这2个示例:
例子6.4. 在Gradle任务中使用Groovy
build.gradle

task upper << {    String someString = 'mY_nAmE'    println "Original: " + someString     println "Upper case: " + someString.toUpperCase()}

gradle -q upper 输出:

> gradle -q upperOriginal: mY_nAmEUpper case: MY_NAME

例子6.5. 在Gradle任务中使用Groovy
build.gradle

task count << {    4.times { print "$it " }}

gradle -q count 输出:

> gradle -q count0 1 2 3 

6.5. Task dependencies(任务依赖)

你很可能已经想到,你可以声明一些可以依赖于其他任务的任务。
例子6.6. 声明一个依赖于其他task的task
build.gradle

task hello << {    println 'Hello world!'}task intro(dependsOn: hello) << {    println "I'm Gradle"}

gradle -q intro 输出:

> gradle -q introHello world!I'm Gradle

可以添加一个还没存在的task作为依赖:
例子6.7. 懒依赖-另外的task还没存在
build.gradle

task taskX(dependsOn: 'taskY') << {    println 'taskX'}task taskY << {    println 'taskY'}

gradle -q taskX 输出:

> gradle -q taskXtaskYtaskX

taskX对应taskY的依赖关系先于taskY的定义。这对应多重项目构建非常重要。更多任务依赖的讨论可以参考 为一个task添加多个依赖。
请注意,当你要关联一个未存在的task时,不可以使用快捷标记。(参看6.8小节)

6.6. Dynamic tasks(动态任务)

Groovy的能力远远大于定义一个单独的task.例如,你可以使用它来动态创建task。
例子6.8. 动态创建task
build.gradle

4.times { counter ->    task "task$counter" << {        println "I'm task number $counter"    }}

gradle -q task1 输出:

> gradle -q task1I'm task number 1

6.7. Mainipulating existing tasks (操作调整已经存在任务)

一旦任务被创建,任务就可以被API访问到。例如,你可以使用这个在运行时去动态给一个任务添加依赖。Ant是不允许这种行为的。
例子6.9. 通过API访问一个任务-添加一个依赖
build.gradle

4.times { counter ->    task "task$counter" << {        println "I'm task number $counter"    }}task0.dependsOn task2, task3

gradle -q task0 输出:

> gradle -q task0I'm task number 2I'm task number 3I'm task number 0

或者你可以为当前已经存在的任务添加其他行为。
例子6.10. 通过API访问一个任务-添加行为
build.gradle

task hello << {    println 'Hello Earth'}hello.doFirst {    println 'Hello Venus'}hello.doLast {    println 'Hello Mars'}hello << {    println 'Hello Jupiter'}

gradle -q task0 输出:

> gradle -q helloHello VenusHello EarthHello MarsHello Jupiter

对doFirst和doLast的调用可以执行多次。他们添加一个动作到任务动作列表的开始或结束位置。当任务被执行时,在动作动作列表中的动作会被按顺序的执行。操作符<<是doLast的同名词。

6.8. Shortcut notations(快捷标记符)

在上一个例子中,你可能早已注意到有一个方便的标记符号去访问一个已经存在的task。作为构建脚本的一个属性,在每个task中都可以使用这种快捷方式。
例子6.11. 用构建脚本属性的方式访问task
build.gradle

task hello << {    println 'Hello world!'}hello.doLast {    println "Greetings from the $hello.name task."}

gradle -q hello 输出:

> gradle -q helloHello world!Greetings from the hello task.

这功能使构建脚本代码可读性更加强,特别是当使用插件提供的任务时,就像一个编译任务。

6.9. Extra task properties(扩展任务属性)

你可以向任务添加自定义属性。添加一个名称为myProperty的属性,并设置 ext.myProperty一个初始值。从此以后,这个属性就可以像预先定义的task属性一样被读取。
例子6.12. 向任务添加一个扩展属性
build.gradle

task myTask {    ext.myProperty = "myValue"}task printTaskProperties << {    println myTask.myProperty}

gradle -q printTaskProperties 输出:

> gradle -q printTaskPropertiesmyValue

扩展属性并不仅限于task.你可以获取更多扩展属性的相关内容,请参考扩展属性。

6.10. Using Ant Tasks(使用Ant任务)

Ant tasks在Gradle中是非常优秀的。Gradle中可以非常简单的使用Groovy来为Ant task提供非常优秀集成。Groovy封装了抽象的AntBuilder。在Gradle中使用Ant task相当方便,而且比在build.xml中使用Ant tasks更加强大有力。例如下面的示例,你可以学到怎么执行Ant tasks和怎么访问Ant属性。
例子6.13. 使用AntBuilder去执行ant.loadfile target
build.gradle

task loadfile << {    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 输出:

> 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)

你可以在你的构建脚本中使用Ant去做更多事情。你可以参考在Gradle中使用Ant。

6.11. Using methods(使用方法)

Gradle为你如何组织你的构建逻辑划分等级。组织构建逻辑的第一级便是上面的例子,提前一个方法。
例子6.14. 使用方法去组织你的构建逻辑
build.gradle

task checksum << {    fileList('../antLoadfileResources').each {File file ->        ant.checksum(file: file, property: "cs_$file.name")        println "$file.name Checksum: ${ant.properties["cs_$file.name"]}"    }}task loadfile << {    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 -q loadfile 输出:

> gradle -q loadfileI'm fond of agile.manifesto.txtI'm fond of gradle.manifesto.txt

迟点你将会看到在多重项目构建方面,子项目之间可以有很多共享的方法。如果你的构建逻辑变得更加复杂,Gradle可以提供给你其他非常方便的方法去组织构建逻辑。我们已经准备了整整一个章节去讨论它。可以参看组织构建逻辑。

6.12. Default tasks(默认任务)

Gradle允许你为你的构建定义一个或多个默认tasks。
例子6.15. 定义默认任务
build.gradle

defaultTasks 'clean', 'run'task clean << {    println 'Default Cleaning!'}task run << {    println 'Default Running!'}task other << {    println "I'm not a default task!"}

gradle -q 输出:

> gradle -qDefault Cleaning!Default Running!

这个等价于去允许gradle clean run。在多重项目构建中,每个子项目可以有自己指定的默认tasks.如果一个子项目没有指定默认task,父项目的默认task会被使用(假如父项目存在默认task)。

6.13. Configure by DAG(有向无环图的配置)

就如我们迟点详细说明的(参考构建的生命周期),Gradle有一个配置阶段和一个执行阶段。配置阶段完成后,Gradle了解到所有将会被执行到的tasks.Gradle会给你提供一个钩子,让你可以使用到这些信息。一个用例是去检查release task是否在这些即将被执行的任务之中。根据这个,你可以给一些变量赋予不同的值。
在下面这个例子中,distribution和release这2个tasks会有不同的版本值。
例子6.16. 选择不同的task,输出不同的结果
build.gradle

task distribution << {    println "We build the zip with version=$version"}task release(dependsOn: 'distribution') << {    println 'We release now'}gradle.taskGraph.whenReady {taskGraph ->    if (taskGraph.hasTask(release)) {        version = '1.0'    } else {        version = '1.0-SNAPSHOT'    }}

gradle -q distribution 输出:

> gradle -q distributionWe build the zip with version=1.0-SNAPSHOT

gradle -q release 输出:

> gradle -q releaseWe build the zip with version=1.0We release now

重要的事情是whenReady在release被执行前影响到了release task。即使release不是主task,也可以生效。

6.14. Where to next?(接下来怎么学习?)

在这个章节,我们简单的介绍了task。但对task的学习还没结束。如果你想更详细的学习task,请到这里学习:更多关于task的事情。

否则,继续第七章Java快速开始的教程和第八章依赖管理基础。

0 0
原创粉丝点击