Gradle系列之基础篇

2,505 阅读7分钟

定义

Gradle是一个基于Apache Ant和Apache Maven概念的项目自动化构建开源工具,它使用一种基于Groovy的特定领域语言(DSL)来声明项目设置, 项目配置简单且任务扩展方便。

构建工具的前世今生

Gradle 诞生前有两个非常流行的自动化构建工具Ant和Maven,下列表格对比这两个构建工具的优缺点:

image

Gradle是基于Ant和Maven诞生的自动化构建工具,那么它必须要同时拥有Ant和Maven的优势,也就是说Gradle具有如下特点:

  • 包含依赖管理器,方便引用外部依赖库
  • 具有默认的构建任务周期
  • 灵活的自定义构建逻辑

Gradle基础

本节重点介绍下Gradle的基础内容,包括运行机制和脚本内容的分析。

Gradle工作流程

Gradle 工作流程分为三个阶段,如下图所示:

image

  • initialization
    Gradle初始化阶段会到root工程根目录找到setting.gradle文件,所有在该文件中声明的工程均是Gradle自动化构建的工程
  • configure
    Gradle初始化过后就会根据setting.gradle中配置的所有工程目录下找build.gradle文件,然后分析build.gradle文件,确定需要执行的任务以及任务的顺序
  • build 根据configure阶段确定的Task执行顺序执行Task任务
脚本分析

Gradle有很多插件,这里主要分析Android插件的脚本配置。

setting.gradle

Setting.gradle中主要是声明了哪些Gradle自动化构建的工程,内容如下所示:

include ':app', ':library1', ':library2’ 

上面内容是包括三个Gradle工程,其中冒号可以理解为/,解释为构建工程的相对目录

根目录build.gradle

根目录build.gradle是对所有Gralde工程均起作用的全局声明,内容如下:

image

  • buildscript 该标签是编译脚本的作用域,也就是对Gradle的配置,其中repositories是Gradle构建脚本的仓库声明,其中dependencies也是Gradle构建脚本所需要的,这里明显是Android工程的Gradle构建工具
  • repositories 仓库的意思,就是声明依赖库的地址,allprojects声明的是所有Gradle工程中引用外部库的地址,当有一些lib库放在私有仓库里,需要在这里面添加私有仓库;其中buildscript中的声明的是Gradle构建工具需要依赖的仓库
  • task 这里默认声明了一个task,这个Task是用于删除Gradle构建过程生成的文件,Task用法后面再具体说

Android工程build.gradle

Android 工程中的build.gradle文件内容重点是android标签里面的特殊配置项,这里贴一个简单的配置:

image

  1. apply plugin
    表示当前Gradle工程构建过程需要使用到的插件,其中com.android.application表示的是使用Android项目的构建过程,当然也可以引用其它插件,前提是在root project的build.gradle中的buildscipt中的dependencises中配置,这里由于配置了com.android.tools.build:gradle所以可以直接使用Android插件

  2. android
    这个是Android工程特有的配置项,这里介绍一下几个基本配置选项:

    compileSdkVersion: 编译时使用的SDK版本
    buildToolsVersion: 编译时使用的编译工具的版本
    applicationId: 应用唯一标识
    buildTypes: 编译类型,一般默认deubg和release两种,可以自定义

    Android里面有很多配置选项,基本就能满足日常开发需求

  3. dependencies
    依赖标签,主要是设置工程需要的外部库,里面有很多依赖方式,这个具体后面介绍

依赖

依赖主要是引用外部库的过程,这里需要说明两点:仓库以及依赖方式

  • 仓库
    Gradle中仓库声明主要使用repositories,除了使用远程仓库,还可以使用本地仓库,如在工程中依赖aar时,就是使用的本地仓库:
repositories {    
    flatDir {        
        dirs 'libs'   // aar目录
      }
}

这里是把本地libs目录当作仓库使用

  • 依赖
    依赖方式比较多,Gradle3.0后又对依赖方式进行了修改,这里列出不同版本以及不同依赖方式之间的差别:
    image
    需要注意如下几点:
  1. implementation和api主要差别是可见性,api的可见性更强
  2. 上面的依赖方式往往结合Flavor使用构建不同的Variant

依赖远程库文件主要由三部分构成: group Name version
如下所示:

image
Group:com.android.Support
Name:appcompat-v7
Version:25.1.0

Variant

Android 主要使用BuildType和Product Flavor构建多种Variant

  • BuildType
    BuildType默认有debug和release两种:

    image
    BuildType构建类型其实很有用,比如配置签名,测试链接,以及混淆等,对日常测试开发很有帮助,如下就定义了在不同的构建类型里面定义了不同的访问连接:
    image

  • Product Flavor
    Product Flavor表示不同特点的产品,例如APK打包发布时需要发不到不同的应用市场,开发者需要设置不同渠道的渠道号,有的时候还需要针对不同渠道的产品定制特殊的图标或者界面。

    1. 设置不同Product Flavor:
      上图设置了不同的ProductFlavor,内容是不同渠道的渠道号,这样在构建不同的产品时,渠道号就直接被修改了
    2. 生成不同的Product 源集
      定制特定的功能,可以将功能独立出来,然后根据不同的Product实现,生成不同的Product源集需要了解下列规则:
    • java文件:java文件需要在product具体包名下生成,不可在main中也生成,否则会出现类被定义2次的错误
    • drawable和layout文件:会直接覆盖main源集中相同名称的资源
    • value目录文件:合并内容
    1. 构建Variant
      上述步骤是配置不同的Variant,当配置完成后,就可以执行编译命令,一般编译的时候,会使用如下命令构建:
        ./gradlew assemble
    

    该命令会构建所有的的Variant,且产物的数量为BuildTypes x Product Flavor, 如果想要只构建某一个或者一类的Variant,可以执行如下构建命令:

    ./gradlew assemble + Product Name(可选) + BuildTypes(可选)
    
Task

Task是Gradle中一个非常重要的工具,通过使用Task能完成一些特定的需求,本节主要从以下三个方面说明:

  • Task使用
  • Task解析
  • Hook Task
Task使用

声明Task有好几种方式,下面展示一种直接定义的方式:

image
直接执行gradle命令运行:
image

这里注意输出:

Configure project:app
Hello world

其中在Hello Task中定义的内容在Configure阶段就输出了,这里再看下Gradle执行流程:

image

如果想要在build task阶段执行Task,可以将task定义如下:

image
任务执行结果如下:
image
可以看出这里任务是在Task执行阶段运行,这里的<<符号代表doLast的意思,具体后面说明

Task解析

上面简单说明了Task的使用,这里主要解析一下Task。
Task内部定义了很多属性和动作,本质上是一个定义了很多方法和属性的接口,所有的方法都已经被DefaultTask实现了,所以在Gradle中使用Task都是基于DefalutTask来实现的。 每个Task中都包含了一个Action对象的集合,这个动作都会被按照顺序执行,动作为doLast和doFirst方法,这里举一个简单的例子:

image
这里定义了一个Hello的Task,里面声明了很多doFirst和doLast的闭包,执行结果如下:
image
这里说明一下:

  1. 没有在闭包doLast和doFirst中定义的将会在Gradle的Configure阶段执行
  2. 闭包doLast和doFirst在Gradle中的Build Task阶段执行
  3. doLast和doFirst同种声明从上往下优先级递增

总结:
Task归根结底是一个类,所以也可以继承task来完成一些特定动作,这里不做自定义task的介绍,比较少用到,这里主要介绍几个常用的特定task,如copy,zip,delete,下面例举删除的task的使用:

image

HooK Task

Hook Task是指在项目构建的过程中插入自定义任务,完成一些特定的需求,Hook的点有很多,主要能Hook两个阶段:

image
Configure阶段和Build阶段进行Hook,这里简单举两个例子,后面会在进阶篇重点讲解

  • Hook Configure阶段

    image
    上面是在构建Task有向图的时候忽略一些Task,这里直接忽略AndroidTest任务

  • Hook Build阶段

    image
    这里是对编译的产物进行处理

总结

本篇主要从整体上介绍一下Gradle,重点要理解Gradle的执行流程,以及build.gradle文件中的配置作用已经作用范围,下一篇将重点介绍Gradle在Android中比较高级的用法。