文章

01.Gradle基础

01.Gradle基础

Gradle

Gradle 基础

Gradle 是一个框架,它定义了一套自己的游戏规则。我们要玩转 Gradle,必须要遵守它设计的规则。

Gradle 介绍

Gradle 是什么?

Gradle 是一个自动化构建工具。Gradle 是通过组织一系列 task 来最终完成自动化构建的,所以 task 是 Gradle 里最重要的概念
我们以生成一个可用的 apk 为例,整个过程要经过资源的处理,javac 编译,dex 打包,apk 打包,签名等等步骤,每个步骤就对应到 Gradle 里的一个 task。

环境安装

Gradle 是一个 运行在 JVM 的通用构建工具。Gradle 基于 JVM, 因此需要 Java 环境 (1.8 及以上版本)。
其核心模型是一个 Task 组成的有向无环图 (Directed Acyclic Graphs).
qd3vo
两个重要的环境变量:

  1. GRADLE_HOME 这个环境变量的作用是告诉操作系统 Gradle 的安装目录。
  2. GRADLE_USER_HOME 类似于用户的 home 目录 ($HOME), 用于存放 Gradle 运行时的一些通用配置, 缓存等等。默认值是 $HOME/.gradle, 一般不用单独配置。

Gradle Wrapper

Wrapper 是对 Gradle 的一层包装,方便在团队中统一管理 Gradle 的版本,项目开发中通常使用的 Wrapper 这种方式,使用 Wrapper 之后就不需要采用配置 Gradle 的构建环境的方式,使用 Wrapper 启用 Gradle 的时候,Wrapper 会检查 Gradle 有没有下载关联,如果没有下载则从配置的地址下载并进行构建,这就一定程度上方便开发人员构建项目。

  • gradle wrapper 生成的文件目录如下:
1
2
3
4
5
6
│─gradlew
│─gradlew.bat
└─gradle
    └─wrapper
		gradle-wrapper.jar
		gradle-wrapper.properties
  • gradle-wrapper.properties
1
2
3
4
5
distributionBase=xxx #下载的Gradle压缩包解压后存储的主目录
distributionPath=xxx #相对于distributionBase解压后压缩包的路径
zipStoreBase=xxx #相对于distributionBase存放Gradle压缩包的
zipStorePath=xxx #相对于distributionPath存放Gradle压缩包的
distributionUrl=xxx #Gradle的下载地址,一般是官网地址
  • 自定义 Wrapper Task
1
2
3
4
5
6
7
task wrapper(type: Wrapper){
	gradleVersion = '3.3'
	distributionBase='GRADLE_USER_HOME'
	distributionPath='wrapper/dists'
	//注意不要这样写:https\://services...
	distributionUrl="https://services.gradle.org/distributions/gradle-3.3-all.zip"
}
  • Wrapper 源码路径:
    $HOME/.gradle/wrapper/dists/gradle-6.5-all/src/wrapper/

Gradle 日志

Gradle 日志主要跟踪构建过程以及调试错误。

Gradle 日志级别

Gradle 的日志级别主要有六种,具体如下:

1
2
3
4
5
6
ERROR // 错误消息
QUIET // 重要消息
WARNING // 警告消息
LIFECYCLE // 进度消息,默认日志输出最低级别
INFO // 信息消息
DEBUG // 调试信息

使用时可以通过命令行的方式控制日志显示级别,下面是可以使用命令控制的日志选项,具体如下:

1
2
3
-q 或 --quiet // 表示QUIET及其更高级别
-i 或 --info // 表示INFO及其更高级别
-d 或 --debug // DEBUG 及其更高级别(输出所有日志)

如果不指定,则默认输出的日志是 LIFECYCLE 及其更高级别的日志。

  1. print 系列方法将日志输出到控制台,这属于 QUIET 级别的日志
  2. 使用内置的 logger 来控制不同级别日志的显示,及 DEBUG 输出日志最完整、ERROR 输出日志最少
  • 测试
1
2
3
4
5
6
7
8
9
10
11
12
13
//日志测试
task hello {
    doLast{
        println '======>>>>>> Hello world'
        print '======>>>>>> Hi'
        logger.error('======>>>>>> error 日志')
        logger.quiet('======>>>>>> quiet 日志')
        logger.warn('======>>>>>> warn 日志')
        logger.lifecycle('======>>>>>> lifecycle 日志')
        logger.info('======>>>>>> info 日志')
        logger.debug('======>>>>>> debug 日志')
    }
}

命令:

1
./gradlew hello

输出 (info 和 debug 级别的日志没有输出):

1
2
3
4
5
6
======>>>>>> Hello world
======>>>>>> error 日志
======>>>>>> quiet 日志
======>>>>>> warn 日志
======>>>>>> lifecycle 日志
======>>>>>> Hi

./gradlew hello --debug 将输出所有日志

输出堆栈信息

默认情况下,堆栈信息的输出是关闭的,可以通过命令行的堆栈信息开关打开它,当构建失败后,Gradle 会将输出错误的堆栈信息,方便定位和分析问题。打开方式具体如下:

1
2
-s 或 --stacktrace // 输出关键性的堆栈信息
-S 或 --full--stacktrace // 输出全部堆栈信息

一般使用 -s 就可以了。

Command-Line Interface Reference

Command-Line Interface Reference

常用 Gradle 命令

gradle projects

  • gradle projects 查看有多少个工程信息
    查看这个 multi projects 到底包含多少个子 Project:

gradle tasks

  • gradle tasks 查看可执行的 Tasks,执行结果以分组形式输出,一个是关于构建的 (Build Setup tasks),另一个是关于帮助的 (Help tasks)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
PS E:\Gradle\study\wrapper> ./gradlew tasks
:tasks

------------------------------------------------------------
All tasks runnable from root project
------------------------------------------------------------

Build Setup tasks
-----------------
init - Initializes a new Gradle build. [incubating]
wrapper - Generates Gradle wrapper files. [incubating]

Help tasks
----------
components - Displays the components produced by root project 'wrapper'. [incubating]
dependencies - Displays all dependencies declared in root project 'wrapper'.
dependencyInsight - Displays the insight into a specific dependency in root project 'wrapper'.
help - Displays a help message.
model - Displays the configuration model of root project 'wrapper'. [incubating]
projects - Displays the sub-projects of root project 'wrapper'.
properties - Displays the properties of root project 'wrapper'.
tasks - Displays the tasks runnable from root project 'wrapper'.

To see all tasks and more detail, run gradlew tasks --all

To see more detail about a task, run gradlew help --task <task>

BUILD SUCCESSFUL

Total time: 8.4 secs
  • 查看某个 Task 的帮助
1
2
3
4
// 命令格式
gradle help --task Task名称
// 举例
gradle help --task projects

查看依赖

[[03.Gradle依赖#dependencies查看]]

其他命令

  • gradle clean 执行清理任务
  • gradle properties 查看所有属性信息
  • gradle 指定moudle执行编译任务
    ./gradlew :<ModuleName>:assembleRelease 如:
1
./gradlew --debug :libcommon:build
  • 强制刷新第三方依赖
1
./gradlew taskXXX --refresh-dependencies

构建选项

--profile

--profile 选项输出构建时会执行的任务列表,以及每一个任务耗时情况:

1
./gradlew :app:assembleDebug --profile

-q

-q 选项表示静默构建,只会打印出 error 信息:

1
./gradlew :app:assembleDebug -q

--offline

–offline 选项表示构建时不访问网络资源:

1
2
./gradlew :app:assembleDebug --offline -q 

--info

–info 选项表示构建时,打印出 info 信息:info 信息包含构建时,所有 task 相关的信息,这有助于排查构建问题,或帮助熟悉项目构建情况。

1
./gradlew :app:assembleDebug --info

--s

–s 选项表示构建时,打印出异常的所有栈信息:

1
./gradlew :app:assembleDebug --s

--refresh-dependencies

–refresh-dependencies 选项表示构建时,刷新相关依赖:

1
2
./gradlew :app:assembleDebug --refresh-dependencies
# 如果更新了项目相关依赖库版本,在构建后发现没有生效,就可以使用这个选项。

--no-build-cache

–no-build-cache 选项表示构建时,不使用构建缓存:

1
./gradlew :app:assembleDebug --no-build-cache

如果更改了项目代码,在构建后发现没有生效,就可以使用这个选项,或者执行 clean。

备注:这个选项在 Gitlab CI 中构建,或远程构建项目时,发现更改代码没有生效,可以选择使用。

Gradle 自带变量和引用属性值

Project 可用的标准属性

1
2
3
4
5
6
7
8
9
//    Project可用的标准属性
    println "name-->" + name  // app   --项目目录
    println "project-->" + project // project ':app'   -- project实例
    println "project.name-->" + project.name // app
    println "project.path-->" + project.path // :app  --项目绝对路径
    println "project.description-->" + project.description // null  --项目描述
    println "project.projectDir-->" + project.projectDir // D:\workspace_studio\GradleDemo\app  --包含生成脚本的目录
    println "project.buildDir-->" + project.buildDir // D:\workspace_studio\GradleDemo\app\build  --build目录
    println "project.ant-->" + project.ant // org.gradle.api.internal.project.DefaultAntBuilder@139d5492  --AntBuilder实例

Android for gradle 自带变量

1
2
3
4
5
6
7
8
9
10
11
12
println '[rootDir]' + rootDir // D:\workspace_studio\GradleDemo
println '[buildDir]' + buildDir
println '[projectDir]' + projectDir
println '[project]' + project
println '[project]' + project.getName();
println '[rootProject]' + rootProject
//        [rootDir]D:\workspace_studio\GradleDemo
//        [buildDir]D:\workspace_studio\GradleDemo\app\build
//        [projectDir]D:\workspace_studio\GradleDemo\app
//        [project]project ':app'
//        [project]app
//        [rootProject]root project 'GradleDemo'</pre>

引用配置文件 gradle.properties 里的变量

注意:

  1. 要注意参数类型要与 gradle.properties 对应,如果是配置的是 true,不是 boolean 是个 string,获取的时候判断 xxx.toBoolean()
  2. 配置的都是 string,所有 value 不用有 ““,不然获取出来的带 ""

gradle.properties

1
2
3
4
5
6
sdk.dir=D\:\\adt-bundle-windows-x86_64-20140702\\sdk
sdk.ndk = D\:\\ndk

isRunWithAAR=true
libwidget=true
libcommon=true

引用方式

  1. 直接获取属性名
1
println 'myLibrary1'+novoda_bintray
  1. project.properties.get(“ 属性名 “) 获取
1
println 'myLibrary1'+project.properties.get("novoda_bintray")

settings.gradle 引用 gradle.properties(直接引用或 project.properties.get)

1
2
3
4
5
6
7
8
9
10
11
12
println('================ settings.gradle配置 ================\n')
println('isRunWithAAR=' + (isRunWithAAR.toBoolean()) + ", libcommon=" + libcommon.toBoolean() + ", libwidget=" + libwidget.toBoolean())
println('================ settings.gradle配置 end ================\n')

if (!isRunWithAAR.toBoolean() || !libcommon.toBoolean()) {
    println('------include :libcommon------\n')
    include ':libcommon'
}
if (!isRunWithAAR.toBoolean() || !libwidget.toBoolean()) {
    println('------include :libwidget------\n')
    include ':libwidget'
}

根目录的 build.gradle 引用 (直接引用或 project.properties.get)

1
2
3
4
println novoda_bintray
if (novoda_bintray.toBoolean()){
    println("开启了novoda_bintray")
}

app 的 build.gradle 引用 (直接引用或 project.properties.get)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
buildTypes {
    release {
        ......
        buildConfigField("String", "appKey", project.properties.get("appKey"))
        buildConfigField("String", "appType", project.properties.get("appType"))
        buildConfigField "String", "hotfixTag", hotfixTag
        buildConfigField("boolean", "useAndroidX",  project.properties.get("android.useAndroidX"))
    }
    debug {
        ......
        buildConfigField("String", "appKey", project.properties.get("appKey"))
        buildConfigField("String", "appType", project.properties.get("appType"))
        buildConfigField "String", "alihotfixFlag", alihotfixFlag
        buildConfigField("boolean", "useAndroidX",  project.properties.get("android.useAndroidX"))
    }
}

其他脚本

1
2
3
4
5
// 使用 project.hasProperty('sdk.dir') 判断key值是否存在
 println '[sdk.dir]:' + project.hasProperty("sdk.dir") // true
 println '[sdk.ndk]:' + project.hasProperty("sdk.ndk") // true
 println '[sdk.hacket]:' + project.hasProperty("sdk.hacket") // false
// 使用project.properties['sdk.dir']进行key值的value引用

Project

[[Gradle Project]]

本文由作者按照 CC BY 4.0 进行授权