【转】从零开始学习Gradle之二---如何使用Task

原文:http://www.blogjava.net/wldandan/archive/2012/07/05/382246.htmlhtml

上一篇文章中,咱们提到了Gradle的一些基本概念,如Project、Task以及Action,而且建立了咱们的第一个Task。此次咱们来看看Gradle中关于Project和Task的更多细节。java

1. Project和Task服务器

对于build.gradle配置文件,当运行Gradle <Task> 时,Gradle会为咱们建立一个Project的对象,来映射build.gradle中的内容。其中呢,对于不属于任何Task范畴的代码,Gradle会建立一个Script类的对象,来执行这些代码;对于Task的定义,Gradle会建立Task对象,并将它会做为project的属性存在(其实是经过getTaskName完成的)。ok,看一个简单的例子:闭包

新建文件basic/build.gradle,而后加入以下部分代码:gradle

println "the project name is $name"
task hello << {
    println "the current task name is $name"
    println "hello world"
}

当运行这个例子时,首先Gradle会建立一个Porject的对象,而后将它和build.gradle的内容映射起来。在这个例子中,project包括两部分:ui

1)可执行脚本定义spa

   按照以前提到的,可执行脚本的定义将直接被建立成对应的Script类的对象
   在这个例子中,Script对应的部分就是第一行println的部分,而后执行的结果就是打印出 "the project name is basic"。
   默认的,Project的名字是当前build.gradle所在目录的名字,在这个例子中,build.gradle放在basic目录下,所以,project的name也就是basic..net

2)Task定义设计

  在这个例子中,Gradle将建立一个Task的实例,将其和定义的task内容关联起来。另外,按照以前所说的,当Gradle运行时,咱们可使用访问project属性的方式去访问它。code

例如,这个例子中,咱们可使用project.hello来访问这个task。由于这个task hello已经成为project的一个属性,那么当咱们使用gradle properties(properties是gradle自带的一个Task,它能列出当前project级别的全部属性,可使用gradle tasks查看更多内建的Task)来获取project级别的属性列表时,也将会获得'hello'。

另外,有一点要注意的是,在这个例子中,task中使用的$name,并非Project的name,它是当前Task的name,由于它被使用在Task的scope里。

执行Gradle hello,输出的结果将是:

current project name is test
the current task name is hello
hello world

2. 定义属性

在Gradle中,咱们能够定义如下三种属性并使用它们:

1)System Properties

System Properties 实际是指的JVM的system properties。咱们知道,在运行java程序时,可使用-D来设置Java的系统变量,在Gradle中,你也能够作一样的事情。好比

gradle xxx -DmySystemProp=xxxx

同时,在build.gradle中,应该这样使用这个变量:

task printSysProps << {
  println System.properties['system']
}

2)Project Properties 

Project Properties是Gradle专门为Project定义的属性。它的最大优势在于当运行gradle的时候,咱们可使用-P来设置它的值。好比,

gradle xxx -PmyProjectProp=xxxxx

而在build.gradle中,能够这样使用这个变量: 

task printProps << {
    if (project.hasProperty('commandLineProjectProp')) {  
        println commandLineProjectProp
    }  
}

同时,当咱们执行gradle properties查看属性列表时,这个变量的名称以及值会显示在结果中。

3)Ext(ra) Properties

    另外,咱们还能够为Project或者Task定义Ext属性,也称动态属性,咱们必须使用关键字ext(对应ExtraPropertiesExtension的实例)去定义动态属性。从这点能够看出,Gradle已经为咱们设计了不少不一样的类,去作不一样的事情,咱们只须要遵循Convention,使用他们便可。若是忘记写ext关键字,gradle运行时则会提示:

"Dynamic properties are deprecated...."。这是由于之前版本的gradle定义动态属性时,不须要加ext关键字的。

对于Project和Task而言,动态属性定义的方式彻底同样,只是做用域不同。
当定义完成后,咱们就可使用project.prop 或者 task.prop来访问这些动态属性了。下面让咱们看一个例子: 

ext.projectProperties="ext projectProperties-value"
task printExtProps << {
  ext.taskProperties="ext.task.properties-value"
  if (project.hasProperty('projectProperties')){
    println "ext.projectProperties values is " + projectProperties  
  }
  if (printExtProps.hasProperty('taskProperties')){
    println "task has defined ext.taskProperties value is " + taskProperties  
  }
}

注意:,对于ext定义的动态属性,并不能经过外部的方式修改它的值,只能在build.gradle中去设置或者修改它的值。

同时,若是是为project定义的ext动态属性,也会显示在gradle properties的结果中。

3. Task依赖

当构建一个复杂的项目时,不一样task之间存在依赖是必然的。好比说,若是想运行'部署'的task,必然要先运行 编译、打包、检测服务器等task,只有当这被些被依赖的task执行完成后,才会部署。对于这种行为之间的依赖,Ant、Maven都提供了声明式的定义,很是简单。一样,使用Gradle定义task之间的依赖也是件很容易的事。

例如,定义以下两个Task,而且在"intro"里加上"dependendsOn"的关键字,以下所示:

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

执行 "gradle intro",结果将是:

Hello World
I'm Gradle

因而可知,当执行gradle intro时,intro依赖的task hello会先被执行。除此以外,dependensOn也支持定义多个task的依赖,使用[]括起来便可。例如

task A(dependensOn:['B','C','D']) <<{ xxx }

除了使用dependensOn跟字符串来定义依赖,咱们也可使用taskX.dependensOn taskY这种形式:

task taskX << {
    println 'taskX'
}
task taskY << {
    println 'taskY'
} 
taskX.dependsOn taskY

或者,也可使用闭包:

task taskX << {
    println 'taskX'
}
taskX.dependsOn {
    tasks.findAll { task -> task.name.startsWith('lib') }
}
task lib1 << {
    println 'lib1'
}

除了以前讲的task的部分,Gradle还为咱们提供了不少可用的API,更多的细节你们能够参考下Gradle的文档。这里我列出一个经常使用的方法onlyIf。在Gradle里,咱们可使用“OnlyIf()”来决定当前task是否须要被执行,例如:新建build.gradle,加入以下代码:

task hello << {
    println 'hello world'
} 
hello.onlyIf { !project.hasProperty('skipHello') }

当咱们直接执行"gradle hello"时,没有任何结果,当咱们执行"gradle hello -PskipHello=xxxx"时,会输出"hello world"。


4. 总结OK.今天对gradle的总结到此为止。整体而言,用DSL的代码而不是xml来定义构建的过程,仍是很fancy的。