Chapter 6.基本构建脚本

来源:互联网 发布:淘宝宝贝上架时间表 编辑:程序博客网 时间:2024/06/01 14:51

项目与任务

Gradle中的一切都建立在两个基本的概念上:项目和任务。

每一个Gradle构建由一个或者多个 项目组成。 一个项目展现出什么取决于你使用Gradle做了些什么。例如,一个项目可能代表一个JAR库或一个web应用程序。 它可能代表了一种 从其他项目产生的jar组装起来的ZIP。 一个项目并不一定代表一样东西需要构建。 它可能代表一件事要做,比如分期或部署您的应用程序。不要着急如果它暂时看起来没有多大价值。Gradle的构建依赖约定支持添加了一个更具体的定义一个项目是什么。

每一个项目都由一个或多个 任务组成 。 一个任务代表了一些原子块 构建执行的工作。 这可能是编译一些类,创建一个JAR,生成Javadoc,或者发布一个文件到库中。

从现在开始,我们会看到在一个项目中定义一些任务在一个构建中。其他章节会讲述多个项目如何工作并且学习更多关于如何使用项目和任务。

Hello,World

当你运行一个Gradle构建时使用命令行操作。Gradle命令会在当前目录中寻找一个叫做build.gradle的文件。我们叫这个build.gradle文件为构建脚本,严格意义上来说,它是一个构建配置脚本。这个构建脚本定义了一个项目和它的任务。

试试这个,创建下面的build.gradle脚本。

例6.1 你的第一个构建脚本

task hello {
doLast{
prinltn ‘Hello world’
}
}

在命令行中,移动到包含文件的目录,并且执行这个脚本命令为: gradle -q hello:

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

gradle -q hello
Hello world!

-q 命令做了些什么?

在用户指引中大多数的例子运行时都有-q 命令选项。这个命令是去除Gradle的日志信息,所以在输出时就只有任务的结果。这个选择可以使用例输出的结果更为明显。如果你觉得没有必要使用这个命令可以不使用。Chapter18,logging有更详细的关于影响Gradle输出的命令行内容。

这儿发生了什么?这个构建脚本定义了一个单独的任务,叫做hello,并且在恩物中添加了一个动作。但你执行gradle hello时,Gradle执行了hello任务,并且执行了你所提供的动作,这个动作执行了一个简单的包含了一些Groovy代码的闭包。

如果你觉得这个看起来和Ant的target很类似,那么你就对了。Gradle tasks和Ant target的功能相同,只是它更强大。我们使用了一个和Ant不同的术语是因为我们认为task比起target更加有表现力。不幸地是这个介绍和Ant有一些冲突,Ant认为它是命令,就像javac 或者copy,tasks一样。所以当我们谈论tasks的时候,我们通常是说Gradle的tasks,和Ant中的target一样的含义。如果我们讨论Ant的task,我们会明确地指出是Ant task。

Task定义的简易方法

这里有一个快速的方法去定义一个task,用hello为例,语法会更加简洁。

例6.3 一个任务定义的简便方法

task hello << {
println ‘Hello world!’
}

再次,这种定义task的方法叫做hello,执行了一个单独的闭包。我们会使用这种定义方法在用户引导中。

构建脚本代码

build.gradle
task upper << {
String someString = ‘mY_nAmE’
println “Original:”+someString
println “Upper case:”+someString.toUpperCase()
}


gradle -q upper输出:
gradle -q upper
Original:mY_nAmE
Upper case:MY_NAME

或者
例6.5 使用Groovy语法
build.gradle

task count <<{
4.times{ print “$it”}
}


gradle -q count输出
gradle -q count
0 1 2 3

任务依赖

就像你可能猜测的一样,你可以定义任务依赖其他任务。
例6.6 声明task依赖其他task
build.gradle

task hello << {
println ‘Hello world!’
}
task intro(dependsOn: hello){
println “I’m Gradle”
}


gradle -q intro输出
gradle -q intro
Hello 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 taskX
taskX
taskY

taskX依赖taskY是在taskY定义之前的。这个特性对于多项目构建十分重要。task依赖在15.4“在任务中添加依赖”更为详细。

动态依赖

    Groovy的力量远远不止定义一个task。例如,你可以同样适用Groovy创建动态的task。

例6.8 动态创建task

4.times{ counter ->
task “taskcounter” << {  
              println “I’m task number
counter”
}
}


gradle -q task1输出
gradle -a task1
I’m task number 1

操控存在的任务

一旦任务被创建他们就可以通过API被访问。例如,你可以适用这个特性动态地在任务执行时添加依赖。Ant则不允许这样的特性存在。

例6.9通过API访问任务———添加一个依赖
build.gradle

4.times{ counter ->
task “taskcounter” <<{  
              println “I’m task number
counter”
}
}
task0.dependsOn task2,task3


gradle -q task0输出
gradle -a task0
I’m task number 2
I’m task number 3
I’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 hello输出
gradle -q hello
Hello Venus
Hello Earth
Hello Mars
Hello Jupiter

调用doFirst和doLast可以多次执行。他们添加一个行动任务的开始或结束的行动列表。当任务执行时,动作列表中执行的动作。<<操作符只是doLast别名。

快捷符号

你可能注意到在之前的例子中,有一些符号是方面访问已经存在的任务中。每一个任务在脚本中都可以作为一个有效的属性:

例6.11在构建脚本中像访问属性一样访问任务
build.gradle

task hello << {
println ‘Hello world!’
}
hello.doLast{
println “Greetings from the $hello.name task.”
}


gradle -q hello输出
gradle -q hello
Hello world!
Greetings from the hello task.

这使得代码非常可读,特别是当使用提供的任务插件时,如编译任务。

  • 额外的任务属性
    你可以在任务中添加你自定义的属性。添加一个属性myProperty,使用ext.myProperty等于一个确定值。利用这个方法,属性可以被读取并且设置像一个预先确定的任务属性。

例6.12 在任务中添加一个额外的属性
build.gradle

task myTask {
ext.myProperty = “myValue”
}

task printTaskProperties << {
println myTask.myProperty
}

gradle -q printlnTaskProperties
gradle -q printTaskProperties
myValue

额外的属性在任务中没有限制,你可以在13.4.2“额外的属性”中学习到更详细的内容。

使用Ant tasks

Ant tasks 在Gradle中是一等公民。Gradle提供了杰出的集成方式给Ant task通过简单的依靠Groovy。Groovy跟随精彩的AntBuilder。在Gradle中使用Ant task比在build.xml文件中使用要更方便和功能更强大。在下面的例子中你可以看到:

例6.13使用AntBuilder去执行ant.loagfile目标
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 tools
Working software over comprehensive documentation
Customer collaboration over contract negotiation
Responding 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做的更多。你可以在17.using from Gradle 中找到更多。

使用方法

Gradle深层次在你如何组织你的构建逻辑。第一级组织构建的逻辑上面的示例中,是提取方法。例6.14 使用方法组织你的构建逻辑builg.gradle 

task checksum << {
fileList(‘../antLoadfileResources’).each {File file ->
ant.checksum(file: file, property: “cs_file.name)printlnfile.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 loadfile
I’m fond of agile.manifesto.txt
I’m fond of gradle.manifesto.txt

至此你会看到这样的方法可以在多重项目中共享。如果你的构建逻辑变得更简单,Gradle提供了你其他非常方便的方法迁移组织它。可以查看Chapter 60,Organizing Builg Logic。

默认的任务

Gradle允许你定义一个或者多个默认任务在你的构建中。

例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 -q
Default Cleaning!
Default Running!

这个相当于运行 gradle clean run 命令。在一个多重任务构建中每一个子项目可以有它自己的单独的默认任务。如果一个子项目没有特殊的默认子项目,那么子项目可以使用副项目定义的默认的任务。

由DAG配置(定向非循环图)

在接下来我们会仔细讲到的内容Chapter56.The Build Lifecycle。Gradle有一个配置阶段和执行阶段。在配置阶段之后,Gradle知道所有的任务将要被执行。Gradle提供你一个钩子去确保这个信息。一个用户用例可以被检查如果发布的任务是要执行的任务之一。依赖这个,你可以安排不同的值给一些变量。在接下来的例子中,分布和发布任务的执行结果在不同版本变量的值。

例6.16 不同的构建的结果取决于选择的任务
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 distribution
We build the zip with version=1.0-SNAPSHOT

gradle -q release 输出
gradle -q release
We build the zip with version=1.0
We release now

重要的是whenReady影响发布任务在执行发布的任务之前。即使这不是主要任务(即发布任务,任务传递到gradle命令)。

0 0
原创粉丝点击