工具----利器

gradle构建

2017-11-10  本文已影响12人  我为峰2014

百度百科

Gradle是一个基于Apache Ant和Apache Maven概念的项目自动化构建工具。它使用一种基于Groovy的特定领域语言(DSL)来声明项目设置,抛弃了基于XML的各种繁琐配置。主要用于Java语言。

Groovy对自己的定义就是:Groovy是在 java平台上的、 具有像Python, Ruby 和 Smalltalk 语言特性的灵活动态语言, Groovy保证了这些特性像 Java语法一样被 Java开发者使用。Groovy 是一门JVM 语言,也就是,Groovy 的代码最终也会被编译成JVM 字节码,交给虚拟机去执行。

Groovy 基本语法

变量

在groovy 中,没有固定的类型,变量可以通过def关键字引用,比如:

def name = 'Andy'

我们通过单引号引用一串字符串的时候这个字符串只是单纯的字符串,但是如果使用双引号引用,在字符串里面还支持插值操作,

def name = 'Andy'
def greeting = "Hello, $name!"

方法

类似 python 一样,通过def关键字定义一个方法。方法如果不指定返回值,默认返回最后一行代码的值。

def square(def num) {
    num * num
}
square 4

Groovy 也是通过Groovy 定义一个类:

class MyGroovyClass {
    String greeting
    String getGreeting() {
        return 'Hello!'
    }
}

闭包

在Groovy 中有一个闭包的概念。闭包可以理解为就是 Java 中的匿名内部类。闭包支持类似lamda形式的语法调用。如下:

def square = { num ->
    num * num
}
square 8

如果只有一个参数,我们甚至可以省略这个参数,默认使用it作为参数,最后代码是这样的:

Closure square = {
    it * it
}
square 16

安装

下载官网的压缩包,下载地址https://guides.gradle.org
解压,

image.png

配置本地的环境变量

image.png

验证

image.png

第一次输入gradle -v会在本地用户文件夹生成.gradle的文件夹,是Gradle的本地仓库

Eclipse安装Gradle

现在新版本的Eclipse/oxygen已经集成了Geadle
创建一个新项目,观察是否有Gradle,若有就注明,已经集成,不需要下载插件了。

image.png

若无,需要下载Buildship插件

help---》 Eclipse Markeplace....

image.png

安装完成后重启Eclipse,观察是否出现Gradle项目。

Eclipse创建Gradle项目

image.png image.png image.png image.png image.png image.png

Gradle的编译周期

在解析 Gradle 的编译过程之前我们需要理解在 Gradle 中非常重要的两个对象。ProjectTask

每个项目的编译至少有一个 Project,一个 build.gradle就代表一个project,每个project里面包含了多个task,task 里面又包含很多actionaction是一个代码块,里面包含了需要被执行的代码。

在编译过程中, Gradle 会根据 build 相关文件,聚合所有的projecttask,执行task 中的 action。因为 build.gradle文件中的task非常多,先执行哪个后执行那个需要一种逻辑来保证。这种逻辑就是依赖逻辑,几乎所有的Task 都需要依赖其他 task 来执行,没有被依赖的task 会首先被执行。所以到最后所有的 Task 会构成一个 有向无环图(DAG Directed Acyclic Graph)的数据结构。

编译过程分为三个阶段:

Gradle的目录

image.png

src文件夹

src/main/javasrc/test/java是和一般的Java项目一样,存放源码配置的位置,方便调试,和``·src```是一样的。

gradle文件夹

存放gradle的版本里面有一个 wrapper文件夹

gradlw wrapper 包含一些脚本文件和针对不同系统下面的运行文件。wrapper 有版本区分,但是并不需要手动去下载,当运行脚本的时候,如果本地没有会自动下载对应版本文件。

image.png image.png

build.gradle

配置整个projeck的项目的构建的依赖

apply plugin: 'java-library' 声明:我们构建的是一个java的library

image.png

setting.gradle

这个 setting 文件定义了哪些module 应该被加入到编译过程,对于单个module 的项目可以不用需要这个文件,但是对于 multimodule 的项目就需要这个文件,否则gradle 不知道要加载哪些项目。这个文件的代码在初始化阶段就会被执行。

image.png

gradlew和gradlew.bat

gradkew的配置和运行文件

image.png

Gradle 的 Task

Task的介绍

一个Task代表一个构建工作的原子操作,例如编译calsses或者生成javadoc。
Gradle中,每一个待编译的工程都叫一个Project。每一个Project在构建的时候都包含一系列的Task。比如一个Android APK的编译可能包含:Java源码编译Task、资源编译Task、JNI编译Task、lint检查Task、打包生成APK的Task、签名Task等。插件本身就是包含了若干Task的。

  • 一个Task包含若干Action。所以,Task有doFirst和doLast两个函数,用于添加需要最先执行的Action和需要和需要最后执行的Action。
    Action就是一个闭包。闭包,英文叫Closure,是Groovy中非常重要的一个数据类型或者说一种概念。
  • Task创建的时候可以通过 type: SomeType 指定Type,Type其实就是告诉Gradle,这个新建的Task对象会从哪个基类Task派生。比如,Gradle本身提供了一些通用的Task,最常见的有Copy 任务。Copy是Gradle中的一个类。当我们:task myTask(type:Copy)的时候,创建的Task就是一个Copy Task。
  • 当我们使用 taskmyTask{ xxx}的时候,花括号就是一个closure。
  • 当我们使用taskmyTask << {xxx}的时候,我们创建了一个Task对象,同时把closure做为一个action加到这个Task的action队列中,并且告诉它“最后才执行这个closure”
task myTask
task myTask { configure closure }  // closure是一个闭包
task myType << { task action }    // <<符号是doLast的缩写  
task myTask(type: SomeType)   // SomeType可以指定任务类型,Gradle本身提供有Copy、Delete、Sync等
task myTask(type: SomeType) { configure closure }

Task的API文档:

https://docs.gradle.org/current/dsl/org.gradle.api.Task.html

自定义Task

在Gradle中,我们有3种方法可以自定义Task。

(1)在build.gradle文件中定义

Gradle使用的是Groovy代码,所以在build.gradle文件中,我们便可以定义Task类。

// 需要继承自DefaultTask
class HelloWorldTask extends DefaultTask {
    // @Optional 表示在配置该Task时,message是可选的。
    @Optional
    String message = 'I am kaku'
    // @TaskAction 表示该Task要执行的动作,即在调用该Task时,hello()方法将被执行
    @TaskAction
    def hello(){
        println "hello world $message"
    }
}

// hello使用了默认的message值
task hello(type:HelloWorldTask)

// 重新设置了message的值
task helloOne(type:HelloWorldTask){
   message ="I am a android developer"
}

(2)在当前工程中定义

当项目中自定义Task类型比较多时,可以将自定义Task写在buildSrc项目中。
具体做法为:在项目的根目录下新建一个名为buildSrc文件夹,然后依次新建子目录src/main/groovy,然后可以建自己的包名,这里以demo.gradle.task为例,依次新建子目录demo/gradle/task,然后在buildSrc根目录下新建build.gradle文件,里面写入:

apply plugin: 'groovy'

 dependencies {
    compile gradleApi()
    compile localGroovy()
}

接着在demo.gradle.task包下,创建HelloWorldTask.groovy文件,将(1)中的HelloWorldTask部分代码粘贴过来

import org.gradle.api.DefaultTask
import org.gradle.api.tasks.Optional
import org.gradle.api.tasks.TaskAction

class HelloWorldTask extends DefaultTask {
    @Optional
    String message = 'I am kaku'

    @TaskAction
    def hello() {
        println "hello world $message"
    }
}

最终目录结构如下:

image.png

(3)在单独的项目中定义

当自定义的Task需要能够提供给其他项目中使用时,可以通过声明依赖的方式引入Task。
具体做法为: 创建一个项目,将(2)中的buildSrc目录下的内容copy到新建项目中,然后将该项目生成的jar文件上传到repository中。

build.gradle如下:

apply plugin: 'groovy'
apply plugin: 'maven'
version = '1.0'
group = 'skr'
archivesBaseName = 'hellotask'

repositories.mavenCentral()

dependencies {
    compile gradleApi()
    compile localGroovy()
}

uploadArchives {
    repositories.mavenDeployer {
        repository(url: 'file:../lib')
    }
}

执行 gradlew uploadArchives ,所生成的jar文件将被上传到上级目录的lib(../lib)文件夹中

在使用该HelloWorldTask时,客户端的build.gradle文件需要做以下配置:

buildscript {
    repositories {
        maven {
            url 'file:../lib'
        }

    }

    dependencies {
        classpath group: 'skr', name: 'hellotask', version: '1.0'
    }
}


task hello(type: HelloWorldTask)

自定义Plugin

与自定义Task相似,也是3种定义方式,只是代码不一样:

apply plugin: DateAndTimePlugin

dateAndTime {
    timeFormat = 'HH:mm:ss.SSS'
    dateFormat = 'MM/dd/yyyy'
}

// 每一个自定义的Plugin都需要实现Plugin<T>接口
class DateAndTimePlugin implements Plugin<Project> {
    //该接口定义了一个apply()方法,在该方法中,我们可以操作Project,
    //比如向其中加入Task,定义额外的Property等。
    void apply(Project project) {
        project.extensions.create("dateAndTime", DateAndTimePluginExtension)
        //每个Gradle的Project都维护了一个ExtenionContainer,
        //我们可以通过project.extentions进行访问
        //比如读取额外的Property和定义额外的Property等。
        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)
        }
    }
}

//向Project中定义了一个名为dateAndTime的extension
//并向其中加入了2个Property,分别为timeFormat和dateFormat
class DateAndTimePluginExtension {
    String timeFormat = "MM/dd/yyyyHH:mm:ss.SSS"
    String dateFormat = "yyyy-MM-dd"
}
上一篇 下一篇

猜你喜欢

热点阅读