Gradle笔记——构建基础

来源:互联网 发布:淘宝物流宝 编辑:程序博客网 时间:2024/05/21 21:41

本篇文章主要介绍一下Gradle的构建基础。它看起来似乎和android项目没多大关系,不能让人一下子理解android项目中的Gradle配置文件,但是这篇基础真的很重要。

学习Gradle前,需要有一个Groovy语言的基础,以免被Groovy的语法困扰,反而忽略了Gradle的知识。这里有一个Groovy的简明中文教程文档,可以快速学习Groovy的一些语法:http://download.csdn.net/detail/maosidiaoxian/8049823


1 Projects和tasks

先明确两个概念,projects和tasks,它们是Gradle中的两个重要概念。

任何一个Gradle构建,都是由一个或多个projects组成的。Project就是你想要用Gradle做什么,比如构建一个jar包,构建一个web应用。Project也不单指构建操作,部署你的应用或搭建一个环境,也可以是一个project。

一个project由多个task组成。每个task代表了构建过程当中的一个原子性操作,比如编译,打包,生成javadoc,发布等等这些操作。


2 编写第一个构建脚本

新建一个文件build.gradle,然后添加以下代码:
[plain] view plaincopy在CODE上查看代码片派生到我的代码片
  1. task hello {  
  2.     doLast {  
  3.         println 'Hello, Gradle!'  
  4.     }  
  5. }  
这是本系列文章里的第一个构建脚本,它定义了一个叫hello的task,task的内容是在最后打印出“Hello, Gradle!”。
我们输入命令gradle hello来执行它:
[plain] view plaincopy在CODE上查看代码片派生到我的代码片
  1. msdx@msdx-ubuntu:~/tmp$ gradle hello  
  2. :hello  
  3. Hello, Gradle!  
  4.   
  5. BUILD SUCCESSFUL  
Gradle是领域驱动设计的构建工具,在它的实现当中,Project接口对应上面的project概念,Task接口对应上面的task概念,实际上除此之外还有一个重要的领域对象,即Action,对应的是task里面具体的某一个操作。一个project由多个task组成,一个task也是由多个action组成。
当执行gradle hello的时候,Gradle就会去调用这个hello task来执行给定操作(Action)。这个操作其实就是一个用Groovy代码写的闭包,代码中的task是Project类里的一个方法,通过调用这里的task方法创建了一个Task对象,并在对象的doLast方法中传入println 'Hello, Gradle!'这个闭包。这个闭包就是一个Action。
Task是Gradle里定义的一个接口,表示上述概念中的task。它定义了一系列的诸如doLast, doFirst等抽象方法,具体可以看gradle api里org.gradle.api.Task的文档。

在上面执行了gradle hello后,除了输出“Hello, Gradle!”之外,我们发现像“:hello”这样的其他内容。这其实是Gradle打印出来的日志,如果不想输出这些内容,可以在gradle后面加上参数 -q。即:gradle -q hello。

3 快速定义任务

上面的代码,还有一种更简洁的写法,如下:
[plain] view plaincopy在CODE上查看代码片派生到我的代码片
  1. task hello << {  
  2.     println 'Hello, Gradle!'  
  3. }  

执行这个脚本,打印出来的是一样的。也就是我们把像doLast这样的代码,直接简化为<<这个符号了。这其实是Gradle利用了Groovy的操作符重载的特性,把左位移操作符实现为将action加到task的最后,相当于调用doLast方法。看Gradle的api文档里对doLast()和leftShift()这两个方法的介绍,可知它们的作用是一样的,所以在这里,<<左移操作符即doLast的简写方式。

4 代码即脚本

Gradle脚本是采用Groovy编写的,所以也像Groovy一样,以脚本方式来执行代码,如下面例子:
[plain] view plaincopy在CODE上查看代码片派生到我的代码片
  1. task upper << {  
  2.     String someString = 'mY_nAmE'  
  3.     println "Original: " + someString   
  4.     println "Upper case: " + someString.toUpperCase()  
  5. }  

执行结果如下,它将定义的字符串转为大写:
[plain] view plaincopy在CODE上查看代码片派生到我的代码片
  1. msdx@msdx-ubuntu:~/tmp$ gradle -q upper  
  2. Original: mY_nAmE  
  3. Upper case: MY_NAME  
这也就是说,我们在写Gradle脚本的时候,可以像写Groovy代码一样。而Groovy是基于Java的,兼容Java语法,所以Java的朋友们,是不是忽然发现Gradle脚本很好上手了呢?

5 任务依赖

我们可以通过以下方式创建依赖:
[plain] view plaincopy在CODE上查看代码片派生到我的代码片
  1. task hello << {  
  2.     print 'Hello, '  
  3. }  
  4. task intro(dependsOn: hello) << {  
  5.     println "Gradle!"  
  6. }  

定义一个任务hello,输出“Hello, ”,然后定义一个任务intro,并依赖hello,输出“Gradle!”。结果是打印出“Hello, Gradle!”,如下:
[plain] view plaincopy在CODE上查看代码片派生到我的代码片
  1. msdx@msdx-ubuntu:~/tmp$ gradle -q intro  
  2. Hello, Gradle!  

另外,被依赖的task不必放在前面声明,在后面也是可以的,这一点在后面将会用到。

6 动态任务

借助于强大的Groovy,我们还可以动态地创建任务。如下代码:
[plain] view plaincopy在CODE上查看代码片派生到我的代码片
  1. 4.times { counter ->  
  2.     task "task$counter" << {  
  3.         println "I'm task number $counter"  
  4.     }  
  5. }  

我们定义了4个task,分别是task0, task1, task2, task3。我们来执行task1,如下:
[plain] view plaincopy在CODE上查看代码片派生到我的代码片
  1. msdx@msdx-ubuntu:~/tmp$ gradle -q task1  
  2. I'm task number 1  

另外,gradle tasks命令可以查看我们定义的task,从这里我们也可以看到定义的task,如下:
[plain] view plaincopy在CODE上查看代码片派生到我的代码片
  1. ...  
  2. Other tasks  
  3. -----------  
  4. task0  
  5. task1  
  6. task2  
  7. task3  
  8. ...  
注意,如果任务还未定义,不能使用短标记法(见本篇后续内容)来运行任务。

7 任务操纵

在Gradle当中,任务创建之后可以通过API进行访问,这是Gradle与Ant的不同之处。

7.1 增加依赖

还是以上面的例子,但是我们添加一行代码,如下:
[plain] view plaincopy在CODE上查看代码片派生到我的代码片
  1. 4.times { counter ->  
  2.     task "task$counter" << {  
  3.         println "I'm task number $counter"  
  4.     }  
  5. }  
  6. task1.dependsOn task0, task3  
然后还是执行 gradle -q task1,看看结果:
[plain] view plaincopy在CODE上查看代码片派生到我的代码片
  1. msdx@msdx-ubuntu:~/tmp$ gradle -q task1  
  2. I'm task number 0  
  3. I'm task number 3  
  4. I'm task number 1  
它先执行了task0和task3,因为task1依赖于这两个。

7.2 增加任务行为

如下代码:
[plain] view plaincopy在CODE上查看代码片派生到我的代码片
  1. task hello << {  
  2.     println 'Hello, Gradle!'  
  3. }  
  4. hello.doFirst {  
  5.     println 'I am first.'  
  6. }  
  7. hello.doLast {  
  8.     println 'I am last.'  
  9. }  
  10. hello << {  
  11.     println 'I am the the last'  
  12. }  
执行后的输出:
[plain] view plaincopy在CODE上查看代码片派生到我的代码片
  1. msdx@msdx-ubuntu:~/tmp$ gradle -q hello  
  2. I am first.  
  3. Hello, Gradle!  
  4. I am last.  
  5. I am the the last  

8 短标记法

如果你对groovy有一定了解,那你也许会注意到,每个task都是一个构建脚本的属性,所以可以通过“$”这种短标记法来访问任务。如下:
[plain] view plaincopy在CODE上查看代码片派生到我的代码片
  1. task hello << {  
  2.     println 'Hello, Gradle!'  
  3. }  
  4. hello.doLast {  
  5.     println "Greetings from the $hello.name task."  
  6. }  

执行结果:
[plain] view plaincopy在CODE上查看代码片派生到我的代码片
  1. msdx@msdx-ubuntu:~/tmp$ gradle -q hello  
  2. Hello, Gradle!  
  3. Greetings from the hello task.  

注意,通过这种方法访问的任务一定是要已经定义的。

9 增加自定义属性

[plain] view plaincopy在CODE上查看代码片派生到我的代码片
  1. task myTask {  
  2.     ext.myProperty = "myValue"  
  3. }  
  4.   
  5. task printTaskProperties << {  
  6.     println myTask.myProperty  
  7. }  

输出结果:
[plain] view plaincopy在CODE上查看代码片派生到我的代码片
  1. msdx@msdx-ubuntu:~/tmp$ gradle -q printTaskProperties  
  2. myValue  

10. 调用Ant任务

比如利用AntBuilder执行ant.loadfiile。

[plain] view plaincopy在CODE上查看代码片派生到我的代码片
  1. task loadfile << {  
  2.     def files = file('config').listFiles().sort()  
  3.     files.each { File file ->  
  4.         if (file.isFile()) {  
  5.             ant.loadfile(srcFile: file, property: file.name)  
  6.             println " *** $file.name ***"  
  7.             println "${ant.properties[file.name]}"  
  8.         }  
  9.     }  
  10. }  

执行结果:

[plain] view plaincopy在CODE上查看代码片派生到我的代码片
  1. msdx@msdx-ubuntu:~/tmp$ gradle -q loadfile  
  2.  *** db.config ***  
  3. db=mysql  
  4. username=root  
  5. password=123456  
  6.   
  7.  *** user.config ***  
  8. username=admin  
  9. writeable=true  

11 方法抽取

在上面的脚本中,我们可以把部分代码抽取出来,如下:

[plain] view plaincopy在CODE上查看代码片派生到我的代码片
  1. task loadfile << {  
  2.     fileList('config').each { File file ->  
  3.         ant.loadfile(srcFile: file, property: file.name)  
  4.         println " *** $file.name ***"  
  5.         println "${ant.properties[file.name]}"  
  6.     }  
  7. }  
  8. File[] fileList(String dir) {  
  9.     file(dir).listFiles({file -> file.isFile() } as FileFilter).sort()  
  10. }  

执行结果一样。

12. 定义默认任务

[plain] view plaincopy在CODE上查看代码片派生到我的代码片
  1. defaultTasks 'clean', 'run'  
  2.   
  3. task clean << {  
  4.     println 'Default Cleaning!'  
  5. }  
  6.   
  7. task run << {  
  8.     println 'Default Running!'  
  9. }  
  10.   
  11. task other << {  
  12.     println "I'm not a default task!"  
  13. }  

执行结果:
[plain] view plaincopy在CODE上查看代码片派生到我的代码片
  1. msdx@msdx-ubuntu:~/tmp$ gradle -q   
  2. Default Cleaning!  
  3. Default Running!  

13 DAG配置

Gradle使用DAG(Directed acyclic graph,有向非循环图)来决定任务执行的顺序。通过这一特性,我们可以实现依赖任务做不同输出。
如下代码:
[plain] view plaincopy在CODE上查看代码片派生到我的代码片
  1. task distribution << {  
  2.     println "We build the zip with version=$version"  
  3. }  
  4.   
  5. task release(dependsOn: 'distribution') << {  
  6.     println 'We release now'  
  7. }  
  8.   
  9. gradle.taskGraph.whenReady {taskGraph ->  
  10.     if (taskGraph.hasTask(release)) {  
  11.         version = '1.0'  
  12.     } else {  
  13.         version = '1.0-SNAPSHOT'  
  14.     }  
  15. }  

执行结果如下:
[plain] view plaincopy在CODE上查看代码片派生到我的代码片
  1. msdx@msdx-ubuntu:~/tmp$ gradle -q distribution  
  2. We build the zip with version=1.0-SNAPSHOT  
  3. msdx@msdx-ubuntu:~/tmp$ gradle -q release  
  4. We build the zip with version=1.0  
  5. We release now  
  6. msdx@msdx-ubuntu  
在上面的脚本代码中,whenReady会在release任务执行之前影响它,即使这个任务不是主要的任务(即不是通过命令行传入参数来调用)。

本文原创,参考自Gradle官方文档,可看作是阅读该文档的笔记。转载请注明本段内容及本文出处:http://blog.csdn.net/maosidiaoxian/article/details/40340571

0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 电子录入系统中无法打开影像怎么办 火车票退票后说银行退款失败怎么办 苹果4s玩游戏闪退怎么办 买了二手房原房主不迁户口怎么办 苹果禁反忘记工id密码了怎么办 玩英雄联盟用腾讯游戏平台卡怎么办 游戏代练接单了没有给我账号怎么办 华为手机进入设置立即闪退怎么办 股东发现公司有做假账现象怎么办 中国在服役期间有纹身被发现怎么办 脚碰了肿了紫了怎么办 外阴出血了怎么办去医院检查没问题 三个半月宝宝体检脚有的紧怎么办 肛门被红枣核刺了一个洞怎么办 肛门里面有棉签上的棉花怎么办 孩子裤子沾屎怎么洗下来怎么办 做完痔疮手术后有点肛门狭窄怎么办 孕妇做b超宝宝不配合怎么办 怀孕产检医生问的尴尬怎么办 带着节育环做的核磁怎么办 便秘洗肠后最一周未排便怎么办 用了开塞露后肚子疼拉不出来怎么办 冰点脱毛当天用沐浴露洗澡了怎么办 自体脂肪填充脸部但发红又痒怎么办 金矿受伤死亡不给开死亡证明怎么办 手机欠费了导致没信号了怎么办 金立手机指纹硬件无法使用怎么办 试管取卵医生说卵子碎片多怎么办 取卵腹水抽水后尿不通怎么办 手机锁屏密码忘了怎么办求解锁 苹果手表锁屏密码忘记了怎么办 苹果手表锁屏密码忘了怎么办 电脑输密码时点了用户账户怎么办 w7电脑锁屏密码忘记了怎么办 台式电脑w7锁屏密码忘记了怎么办 win7电脑锁屏密码忘记了怎么办 苹果手机4s开机密码忘记了怎么办 苹果4s下载东西忘记密码怎么办 苹果4s不记得开机密码怎么办? 苹果手机id密码忘了怎么办能解锁 苹果5s id密码忘了怎么办?