`

[2/3]gradle脚本运行环境分析(gradle的语义模型)

阅读更多
转自:http://www.cnblogs.com/chenjie0949/p/4757702.html

引言:通过上一篇的论述,我们知道gradle脚本是如假包换的groovy代码,但是这个groovy代码是运行在他的上下文环境里面的,学名叫语义模型。这一篇我们就来看看他的语义模型到底是什么,如何使用。

gradle下载安装
gradle的下载安装并没有什么出乎意料的东西,进入他的官网(http://gradle.org/),下载gradle压缩包,解压,配置bin路径到Path即可。

我安装在c盘下,进入目录C:\gradle-2.4\docs\userguide,打开userguide.pdf文件,这个就是gradle的向导帮助文档。



gradle 语义模型
gradle使用project和task来实现构建的操作,project对应工程,task对应具体的任务,例如编译,压缩,生成帮助文档。我们从userguide.pdf的chap 6中截取一个hello world的Demo来说明,以便有个初步的印象。

创建一个空文件夹Demo,进入,再创建一个build.gradle文件,并写入如下的代码:
task hello {
    println "hello world"
}

在命令行中输入 gradle -q hello (-q 参数用于删除冗余的输出),会得到hello world的输出。这一段脚本通过调用project类的task方法,添加了一个新的task在project的task map中,其主键是“hello”,后面跟着一个闭包,里面的代码用于配置这个task的一些属性,相当于初始化这个task,这在下面action的例子中表现最明显。需要注意的是这里的task是关键字,并不是调用某一个方法,在解析的过程中,gradle还需要根据这个关键字进行转化才能生成标准的groovy代码。

在gradle中,project和build.gradle文件是一一对应的,通过这个文件可以配置project的各种属性。project的初始化流程如下:

(1)首先创建一个Settings的实例。(对应 org.gradle.api.initialization 下的 Interface Settings )

(2)如果当前目录有settings.gradle,那么用这个文件来配置Settings实例。

(3)用Settings实例来创建Project的层次关系。

(4)最后,如果项目中存在build.gradle就通过它来执行每个Project。项目中,项目分别依次横向执行,以此子项目一定在父项目之后执行。这个规则可以通过调用evaluationdependsonchildren()或加入一个明确的依赖usingevaluationdependson(String)。

从初始化流程来看,项目之间的层次和依赖关系是通过settings.gradle来配置的,而project的具体任务执行是通过build.gradle来配置的。在build.gradle中可以添加系统提供的task和自定义的task,例如上例就是自定义的task。Project还可以通过添加插件来添加能支持的task。task是由action组成,action可以理解成真正的执行功能的代码块,可以调用doFirst,doLast,leftShift和<<添加action。我们举一个既有配置代码,又有action的例子,看下面的代码:

action的例子
task hello {
    println "hello world"//初始化
}<<{
    println "hello world action"
}
 
task hello1 {
    println "hello world1"//初始化
}<<{
    println "hello world1 action"
}


我们用上一个例子中运行task的方法调用hello1,即输入:gradle hello1,输出为:
# gradle  hello1
hello world
hello world1
:hello1
hello world1 action

BUILD SUCCESSFUL

Total time: 2.086 secs

可以看出初始化的代码是一定执行的,而Task hello的Action代码,要用gradle指定task才能执行。

从上面的两个例子,我们有了一个最初的印象,gradle构建从上到下的机构顺序应该是project---》task---》action。

  每一个Project都通过一个TaskContainer来添加和管理他的task,这是一个task的容器,可以通过调用project的getTasks()方法来获得,不过一般来说大家都通过task关键字来生成task,范例如下:
task myTask1
  
task myTask2 {
    println "myTask2"
}
 
task myType3 << {
    println "myTask2 -- action"
}
task myTask4("dependsOn": myType3)
 
task myTask5("dependsOn": myType3) {
    println "myTask5 -- action" 
}


当然可以直接用project里面的task()方法,使代码更加groovy一点:
task nTask1
 
task nTask2,{
    println "nTask1"
}
 
task nTask3,{
    println "nTask3"
}<<{
    println "nTask3 -- action"
}
 
task nTask4,{
    dependsOn(nTask3)
}


一旦task被创建,就可以用它的名字来引用它。
task nTask3,{
    println "nTask3"
}<<{
    println "nTask3 -- action"
}
 
task nTask4,{
    dependsOn(nTask3)
}
 
nTask4 << {
    println "nTask4 -- action"
}


执行结果:
nTask3 -- action
nTask3
:nTask3 UP-TO-DATE
:nTask4
nTask4 -- action

BUILD SUCCESSFUL

Total time: 2.927 secs

上面说Task中具体的执行步骤是通过Action来完成的,Action的结构十分简单,只有一个方法

void execute(T t)

Action在Task中排列成一个队列,依次执行。增加Action有4个方法,上面已经提过,看下面的例子:
task nTask4 {
    println "this is config"//配置这个task
}
nTask4 << {
    println "nTask4 -- add action by <<" //通过 <<来增加action
}
nTask4.leftShift {
    println "nTask4 -- add action by leftShift "//通过leftShift方法来增加action,等同 <<
}
nTask4.doFirst {
    println "nTask4 -- doFirst" //在action队列的最前面插入一个Action
}
 
nTask4.doLast {
    println "nTask4 -- doLast" //在action队列的最最后插入一个Action
}


输出结果为:
# gradle nTask4
this is config
:nTask4
nTask4 -- doFirst
nTask4 -- add action by <<
nTask4 -- add action by leftShift
nTask4 -- doLast

BUILD SUCCESSFUL

Total time: 2.935 secs


结果一目了然,doFirst最先执行,<<和leftShift的调用时序决定先后顺序,而doLast在最后。能这样做的数据结构,当然是队列,事实也确实如此,在Task接口中,用的是List,而在抽象类AbstractTask中用ArrayList实现的。

Project和Task的属性设置和依赖关系可以参考这篇博客:http://www.blogjava.net/wldandan/archive/2012/07/05/382246.html。

增加一个例子作说明

//project 自带属性
println Project.DEFAULT_BUILD_DIR_NAME
println DEFAULT_BUILD_DIR_NAME
  
//本地属性
String msg = "hello world"
  
//extension 属性
ext{//用 ext 关键字
    projectProperties = "ext projectProperties-value"
}
//直接调用方法
project.getExtensions().create("mMsg", Msg)
 
task hello (){
    println msg //初始化
}<<{
    println "ext properties :"+projectProperties
    projectProperties = "chang the extension propertise"
    println "ext properties :"+projectProperties
//  println project.property(projectProperties)  //无法执行
    println project.property("projectProperties")
    println mMsg.des
}
 
class Msg {
    String des = "this is a msg"
    int id = 10
}


输出结果为:
# gradle hello
build
build
hello world
:hello
ext properties :ext projectProperties-value
ext properties :chang the extension propertise
chang the extension propertise
this is a msg

BUILD SUCCESSFUL

Total time: 3.028 secs

通过上面的例子说明了动态增加属性的方式。由此可以见,一个Project增加属性和Task都是可行的。当某一类Task需要集体带入的话(比如整个android的编译过程),一个个通过task方法加入就过于麻烦了,解决方案也很简单,我把Project的实例给这一类Tasks的管理类(比如XXManager,在gradle中叫XXPlugin,或者直接叫 java,android),由这个管理类自己添加需要的task,举个例子:
apply plugin: DateAndTimePlugin
 
dateAndTime {
   timeFormat = 'HH:mm:ss.SSS'
   dateFormat = 'MM/dd/yyyy'
}
 
class DateAndTimePlugin implements Plugin<Project> {
   void apply(Project project) {
       project.extensions.create("dateAndTime", DateAndTimePluginExtension)
       project.task('showTime') << {
           println "Current time is " + new Date().format(project.dateAndTime.timeFormat)
       }
       project.tasks.create('showDate') << {
           println "Current date is " + new Date().format(project.dateAndTime.dateFormat)
       }
   }
}
 
class DateAndTimePluginExtension {
   String timeFormat = "MM/dd/yyyyHH:mm:ss.SSS"
   String dateFormat = "yyyy-MM-dd"
}


Task已经加入,我们直接使用就可以了,输出结果为:
# gradle showTime showDate
:showTime
Current time is 15:52:15.841
:showDate
Current date is 09/01/2015

BUILD SUCCESSFUL

Total time: 2.132 secs

参考:

负责task转换的类:org.gradle.groovy.scripts.internal.TaskDefinitionScriptTransformer.java

http://www.gradle.org/docs/current/javadoc/org/gradle/api/Project.html

http://www.gradle.org/docs/current/javadoc/org/gradle/api/Task.html
分享到:
评论

相关推荐

    Android Studio gradle系列之gradle-3.3-all.zip

    Android Studio运行项目时出现 Download https://services.gradle.org/distributions/gradle-3.3-all.zip 21 s 147 ms 是因为这个文件处在外网服务器,下载很慢所以连接总是中断,因此可以自行下载,然后 打开C盘...

    gradle-4.1-all.zip离线包下载 极速 android studio2.3 3.0编译必备

    3.进入一堆乱码的文件夹,比如bzyivzo6n839fup2jbap0tjew 4.不要删除里面的.lck和.part等文件,直接拷贝下载的gra dle-3.3-all.zip文件到该目录 5.重启android studio即可。(官方下载地址:...

    gradle-6.7-all.7z

    gradle-6.7-all.zip https://code.aliyun.com/kar/gradle-all-zip/raw/master/gradle-6.7-all.zip gradle-6.6.1-all.zip https://code.aliyun.com/kar/gradle-all-zip/raw/master/gradle-6.6.1-all.zip gradle-6.6-...

    gradle-4.1-all压缩资源包系列.zip

    使用说明 1,官网下载地址...2,更多版本gradle*.zip资源包参见https://editor.csdn.net/md/?articleId=107882711,如有需要可当做工具收藏。这里坚持并且免积分下载,如有需要积分可以博客下留言邮箱

    gradle-7.0-all压缩资源包系列.zip

    使用说明 ...2,更多版本gradle*.zip资源包参见https://blog.csdn.net/liuxingyuzaixian/article/details/107882711,如有需要可当做工具收藏。这里坚持并且免积分下载,如有需要积分可以博客下留言邮箱

    gradle-5.4.1-all压缩资源包系列.zip

    使用说明 1,官网下载地址...2,更多版本gradle*.zip资源包参见https://editor.csdn.net/md/?articleId=107882711,如有需要可当做工具收藏。这里坚持并且免积分下载,如有需要积分可以博客下留言邮箱

    Gradle脚本上传Apk到蒲公英应用平台Demo

    在AndroidStudio利用Gradle脚本上传Apk到蒲公英应用平台

    gradle-2.1-all压缩资源包系列.zip

    使用说明 1,官网下载地址...2,更多版本gradle*.zip资源包参见https://editor.csdn.net/md/?articleId=107882711,如有需要可当做工具收藏。这里坚持并且免积分下载,如有需要积分可以博客下留言邮箱

    gradle-2.7-all压缩资源包系列.zip

    使用说明 1,官网下载地址...2,更多版本gradle*.zip资源包参见https://editor.csdn.net/md/?articleId=107882711,如有需要可当做工具收藏。这里坚持并且免积分下载,如有需要积分可以博客下留言邮箱

    gradle-6.7-all压缩资源包系列.zip

    使用说明 1,官网下载地址...2,更多版本gradle*.zip资源包参见https://editor.csdn.net/md/?articleId=107882711,如有需要可当做工具收藏。这里坚持并且免积分下载,如有需要积分可以博客下留言邮箱

    gradle的如下版本gradle-6.7.1-bin.rar

    gradle的如下版本gradle-6.7.1-bin.rar gradle的如下版本gradle-6.7.1-bin.rar gradle的如下版本gradle-6.7.1-bin.rar gradle的如下版本gradle-6.7.1-bin.rar

    gradle-5.1.1-all.zip

    android 构建 gradle-5.1.1-all.zip和gradle-5.1.1-all.zip.sha256;

    gradle-5.4.1-all

    有一天急用,发现官网地址下载很慢,网上很多都是需要积分,明明都是公共资源,大家共享就可以了,gradle-5.4.1-all免费下载,下载成功后拷贝到gradle下面即可

    gradle-4.4-rc-2-all.zip,完整版-解压即可使用

    官网下载不成功的,嫌官网下载速度慢的,可以直接在这里下载。 官网原下载地址:https://services.gradle.org/distributions/

    gradle-4.6-all

    gradle-4.6-all下载 gradle-4.6-all下载 gradle-4.6-all下载 gradle-4.6-all下载

    gradle-3.3-all.z01,第一部分

    官网下载不成功的,或者嫌官网下载速度慢的,可以直接在这里下载。...这是gradle-3.3-all.zip压缩包的第一部分,总共有2个部分。 请把两个压缩包放到同一个文件夹下,任选一个压缩包解压后即为全部gradle-3.3的code。

    关于Gradle下载失败问题的快速解决方法

    每一次,当我们在新的环境中搭建 Android 开发环境并尝试运行或者当我们更换 gradle 版本时,总是会有一个漫长…漫长…漫长的下载 gradle 过程。 怎么办?难道先去睡一觉? 其实解决办法是有有两个。 一、使用已...

    gradle-6.6-all压缩资源包系列.zip

    使用说明 1,官网下载地址...2,更多版本gradle*.zip资源包参见https://editor.csdn.net/md/?articleId=107882711,如有需要可当做工具收藏。这里坚持并且免积分下载,如有需要积分可以博客下留言邮箱

    gradle-3.3-all.zip 绿色版本,欢迎下载

    官网下载不成功的,可以直接在这里下载。 官网原下载地址:https://services.gradle.org/distributions/

    gradle-5.3-all压缩资源包系列.zip

    使用说明 1,官网下载地址...2,更多版本gradle*.zip资源包参见https://editor.csdn.net/md/?articleId=107882711,如有需要可当做工具收藏。这里坚持并且免积分下载,如有需要积分可以博客下留言邮箱

Global site tag (gtag.js) - Google Analytics