介绍

Gradle 是google开发的基于groovy语言 ,用于代替 ant 构建的一种配置型语言

Gradle 是基于groovy语言实现(基于JVM的语法和java类似的脚本语言)的一个Android编译系统, google针对Android编译用groovy语言开发了一套 DSL 语言 有额外需要直接使用groovy,或者java代码解决

下载 / 安装

地址: http://services.gradle.org/distributions/

环境配置

1
2
3
4
5
6
GRADLE_HOME={installed path}
PATH=%GRADLE_HOME%\bin

# 缓存依赖项/元数据/插件数据
# 该属性的默认值根据平台不同而不同,Windows平台默认为C:\Users\用户名\.gradle,Linux和Mac平台默认为~/ .gradle。可以通过设置该属性来指定Gradle用户目录的位置
# GRADLE_USER_HOME=

验证

gradle -v

问题&解决办法记录

Idea中gradle下载太慢解决办法

项目名称\gradle\wrapper\gradle-wrapper.properties中的distributionUrl使用阿里云腾讯的代理地址就可以了

1
distributionUrl=https://mirrors.cloud.tencent.com/gradle/gradle-8.0-bin.zip

更新最新依赖问题

脚本工具由 python2 编写,怎么做到全局使用,请配置在环境变量中,需要额外功能,请自行修改脚本

  • gradle 相对 maven 做了一层本地缓存 ${user}/.gradle/caches/modules-2(默认缓存更新是 24小时)
  • gradle 在当前工程也做了一层缓存 ${project.root}/.gradle
  • 使用 IDE 这种集成开发环境,也加了一层缓存(在 IDE 的缓存目录里面)
  • 工程开发配置文件(当前工程下 .idea .vsc 等等),这个会影响到代码提示 所以,经常出现 gradle 命令更新到最新依赖代码,IDE 不显示的问题,你需要自行处理好缓存 一般命令行 加入 --refresh-dependencies 可以更新 gradle 部分,但不会影响到 IDE 如果想要 IDE 在写代码时知道更新,你需要刷新或者修改 IDE 的缓存,具体怎么操作需要根据情况自行解决 这里提供2个工具脚本辅助

脚本工具 当前目录 IDEA 类工程清理工具

脚本工具 gradle 本地缓存 SNAPSHOT 清理工具

版本冲突问题

如果依赖了库A的1.0版本,又依赖了库B,这个库B依赖了库A的2.0版本,此时就发生了版本冲突问题

  • 我们可以手动去除冲突的依赖,在冲突的库选一个进行exclue
1
2
3
4
5
implementation ('com.carlos.test:Test:1.0.0') {
exclude group: "io.reactivex.rxjava2",module: "rxjava"
// exclude group: "io.reactivex.rxjava2:rxjava:2.1.11"
}
implementation 'io.reactivex.rxjava2:rxjava:2.1.13'
  • 我们可以强制使用某版本依赖
1
2
3
4
5
configurations.all {
resolutionStrategy {
force 'io.reactivex.rxjava2:rxjava:2.1.13'
}
}

项目结构

1
2
3
4
5
6
7
8
|____gradle
| |____wrapper
| | |____gradle-wrapper.jar
| | |____gradle-wrapper.properties
|____gradlew
|____build.gradle
|____gradlew.bat
|____settings.gradle

gradle/wrapper/gradle-wrapper.jar

  • 这是Gradle Wrapper的核心文件,是一个可执行的Java归档文件。
  • 它的作用是下载并安装指定版本的Gradle。
  • 配合gradle-wrapper.properties文件使用,确保项目在不同的开发环境中使用一致的Gradle版本。

gradle/wrapper/gralde-wrapper.properties

每个基于gradle构建的工程都有一个gradle本地代理,叫做 gradle wrapper, 在 /gradle/wrapper/gralde-wrapper.properties 目录中声明了指向目录和版本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.13-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
# 开启并行编译
org.gradle.parallel=true
# 开启守护进程
org.gradle.daemon=true
# 按需编译
org.gradle.configureondemand=true
# 设置编译jvm参数
org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
# 设置代理
systemProp.http.proxyHost=127.0.0.1
systemProp.http.proxyPort=10384
systemProp.https.proxyHost=127.0.0.1
systemProp.https.proxyPort=10384
# 开启JNI编译支持过时API
android.useDeprecatedNdk=true

build.gradle

  • 这是Gradle项目的主要构建脚本文件。它定义了项目的构建逻辑、依赖项、插件、任务等。
  • 主要内容可能包括:
    • 项目的依赖(如第三方库、插件等)。
    • 构建任务(如编译、测试、打包)。
    • 配置构建行为(如Java版本、编译选项等)。
  • 每个子项目通常也会有自己的build.gradle文件。

gradlew

  • 这是Gradle Wrapper的可执行脚本文件(Linux/macOS系统下的版本)。
  • 它的作用是运行Gradle构建,而不需要用户在本地安装Gradle。
  • 使用./gradlew可以确保使用项目指定的Gradle版本,而无需担心环境中安装的Gradle版本是否匹配。

settings.gradle

  • 这是Gradle项目的配置文件,用于定义项目的结构。
  • 主要用于多模块项目,指定哪些子模块(subprojects)属于当前项目。
  • 对于单模块项目,settings.gradle通常是可选的,但可以用来设置项目的根名称或其他全局配置。

Gradle 常用命令

注意:在window下可以直接运行 gradlew 如果是Linux 或者 mac 命令为 gradle gradlew 这里都简写成 ./gradlew

任务查询命令

子模块任务,不代表工程根也有同样的任务,所以需要单独查询
最佳命名实践为 全小写英文 防止编译兼容问题

  • 所有后面的命令,都必须在 tasks --all 可见,不然报告找不到这个任务
1
2
3
4
5
6
7
8
9
10
11
# 查看任务
./gradlew tasks
# 查看所有任务 包括缓存任务等
./gradlew tasks --all
# 对某个module [moduleName] 的某个任务[TaskName] 运行
./gradlew :moduleName:taskName

# 在gradle中task就是一系列的操作任务
# 查看名字为xxx的task命令的构成
./gradlew xxx --dry-run
eg:./gradlew build -x test

快速构建命令

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
# 查看构建版本
./gradlew -v
# 清除build文件夹
./gradlew clean
# 不使用snapshot依赖仓库 - 前提是离线可以使用时
./gradlew clean aDR
./gradlew clean aDR --offline
# 检查依赖并编译打包
./gradlew build
# 编译并安装debug包
./gradlew installDebug
# 编译并打印日志
./gradlew build --info
# 译并输出性能报告,性能报告一般在 构建工程根目录 build/reports/profile
./gradlew build --profile
# 调试模式构建并打印堆栈日志
./gradlew build --info --debug --stacktrace
# 强制更新最新依赖,清除构建并构建
./gradlew clean build --refresh-dependencies

## 守护进程
./gradle build --daemon
## 并行编译模式
./gradle build --parallel --parallel-threads=N
## 按需编译模式
./gradle build --configure-on-demand

注意build命令把 debug、release环境的包都打出来的 如果需要指定构建使用如下命令

gradle 指定构建目标命令

1
2
3
4
5
6
7
8
# 编译并打Debug包
./gradlew assembleDebug
# 这个是简写 assembleDebug
./gradlew aD
# 编译并打Release的包
./gradlew assembleRelease
# 这个是简写 assembleRelease
./gradlew aR

gradle 构建并安装调试命令

1
2
3
4
5
6
7
8
9
10
# 编译并打Debug包
./gradlew assembleDebug
# 编译app module 并打Debug包
./gradlew install app:assembleDebug
# 编译并打Release的包
./gradlew assembleRelease
# Release模式打包并安装
./gradlew installRelease
# 卸载Release模式包
./gradlew uninstallRelease

gradle 多渠道打包

1
2
3
4
5
6
7
8
9
10
11
12
13
# assemble还可以和productFlavors结合使用,如果出现类似 Task 'install' is ambiguous in root project 这种错误,请查看配置的多个渠道然后修改为以下命令来构建调试
./gradlew install[productFlavorsName] app:assembleDebug

# Release模式打包并安装
./gradlew installRelease
# 卸载Release模式包
./gradlew uninstallRelease
# Release模式全部渠道打包
./gradlew assembleRelease
# Release模式 test 渠道打包
./gradlew assembleTestRelease
# debug release模式全部渠道打包
./gradlew assemble

gradle 查看包依赖

1
2
3
4
5
6
7
8
9
10
11
12
13
14
./gradlew dependencies
# 或者模组的 依赖
./gradlew app:dependencies
# 检索依赖库
./gradlew app:dependencies | grep CompileClasspath
# windows 没有 grep 命令
./gradlew app:dependencies | findstr "CompileClasspath"

# 将检索到的依赖分组找到 比如 multiDebugCompileClasspath 就是 multi 渠道分发的开发编译依赖
./gradlew app:dependencies --configuration multiDebugCompileClasspath
# 一般编译时的依赖库,不是固定配置方式,建议检索后尝试
./gradlew app:dependencies --configuration compile
# 一般运行时的依赖库,不是固定配置方式,建议检索后尝试
./gradlew app:dependencies --configuration runtime

gradle 依赖管理

  • 传递依赖特性
1
2
3
dependencies {
transitive true //手动配置transitive属性为false,阻止依赖的下载
}
  • 强制指定编译版本
1
2
3
4
5
6
7
8
9
configurations.all{
// transitive false
// 强制指定版本
resolutionStrategy{
force 'org.hamcrest:hamcrest-core:1.3'
// 强制不编译
all*.excludegroup: 'org.hamcrest', module:'hamcrest-core'
}
}
  • 动态依赖特性
1
2
3
4
5
6
dependencies {
// 任意一个版本
compile group:'b',name:'b',version:'1.+'
// 最新的版本
compile group:'a',name:'a',version:'latest.integration'
}

设定编码

1
2
3
4
5
6
7
allprojects {
...
tasks.withType(JavaCompile){
options.encoding = "UTF-8"
}
...
}

build.gradle 文件详解

  • build.gradle 是一个 gradle 的构建脚本文件,支持 java、groovy 等语言。
  • 每个 project 都会有一个 build.gradle 文件,该文件是项目构建的入口,可配置版本、插件、依赖库等信息。
  • 每个 build 文件都有一个对应的 Project 实例,对 build.gradle 文件配置,本质就是设置 Project 实例的属性和方法。
  • 由于每个 project 都会有一个 build 文件,那么 Root Project 也不列外.Root Project 可以获取到所有 Child Project,所以在 Root Project 的 build 文件中我们可以对 Child Project 统一配置,比如应用的插件、依赖的 maven 中心仓库等。
  • build 文件中常见的属性和方法如下所示:

常见属性代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
//指定使用什么版本的JDK语法编译源代码,跟编译环境有关,在有java插件时才能用
sourceCompatibility = 1.8
//指定生成特定于某个JDK版本的class文件:跟运行环境有关,在有java插件时才能用
targetCompatibility = 1.8
//业务编码字符集,注意这是指定源码解码的字符集[编译器]
compileJava.options.encoding "UTF-8"
//测试编码字符集,注意这是指定源码解码的字符集[编译器]
compileTestJava.options.encoding "UTF-8"
//编译JAVA文件时采用UTF-8:注意这是指定源码编码的字符集【源文件】
tasks.withType(JavaCompile) {
options.encoding = "UTF-8"
}
//编译JAVA文件时采用UTF-8:注意这是指定文档编码的字符集【源文件】
tasks.withType(Javadoc) {
options.encoding = "UTF-8"
}

提示 1:group+name+version 类似于 maven 的 group+artifactId+version
提示 2:encoding 解决业务代码与测试代码中文乱码问题

Repositories

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
repositories { 
//gradle中会按着仓库配置的顺序,从上往下依次去对应的仓库中找所需要的jar包:
//如果找到,则停止向下搜索,如果找不到,继续在下面的仓库中查找
//指定去本地某个磁盘目录中查找:使用本地file文件协议:一般不用这种方式 maven { url 'file:///D:/repos/mavenrepos3.5.4'}
maven { url "$rootDir/lib/release" }
//指定去maven的本地仓库查找
mavenLocal()
//指定去maven的私服或者第三方镜像仓库查找
maven { name "Alibaba" ; url "https://maven.aliyun.com/repository/public" }
maven { name "Bstek" ; url "https://nexus.bsdn.org/content/groups/public/" }
//指定去maven的远程仓库查找:即 https://repo.maven.apache.org/maven2/
mavenCentral()
//去google仓库查找
google()
}

因为 Gradle 没有自己的远程仓库,而是使用 Maven、jcenter、jvy、google 这些远程仓库。

Subprojects 与 Allprojects

allprojects 是对所有 project(包括 Root Project+ child Project[当前工程和所有子工程])的进行统一配置,而 subprojects 是对所有 Child Project 的进行统一配置。

1
2
3
4
5
6
7
8
9
10
11
12
allprojects { 
tasks.create('hello') {
doLast {
task ->println "project name is $task.project.name"
}
}
}
subprojects {
hello.doLast{
task-> println "here is subprojects $task.project.name"
}
}

通常在 subprojects 和 allprojects 中:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
allprojects(){ //本质Project中的allprojects方法,传递一个闭包作为参数。 
apply plugin: 'java'
ext {
junitVersion = '4.10'
..
}
task allTask{
...
}
repositories {
...
}
dependencies {
...
}
}
subprojects(){
//同上面allprojects中的方法。
}

1: 如果是直接在 根 project 配置 repositories 和 dependencies 则 只针对根工程有效。
2: 我们也可以在对单个 Project 进行单独配置:

1
2
3
4
5
6
7
project('subject01') { 
task subject01 {
doLast {
println 'for subject01'
}
}
}

执行 gradle build 指令即可查看测试效果。

ext 用户自定义属性

Project 和 Task 都允许用户添加额外的自定义属性,要添加额外的属性,通过应用所属对象的 ext 属性即可实现。添加 之后可以通过 ext 属性对自定义属性读取和设置,如果要同时添加多个自定义属性,可以通过 ext 代码块:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
//自定义一个Project的属性 
ext.age = 18
//通过代码块同时自定义多个属性
ext {
phone = 19292883833
address="北京"
}
task extCustomProperty {
//在task中自定义属性
ext {
desc = "奥利给"
}
doLast {
println "年龄是:${age}"
println "电话是:${phone}"
println "地址是:${address}"
println "口号:${desc}"
}
}

测试:通过 gradle extCustomProperty
输出结果为:

年龄是:18
电话是:19292883833
地址是:北京
口号:奥利给

ext 配置的是用户自定义属性,而 gradle.properties 中一般定义 系统属性、环境变量、项目属性、JVM 相关配置 信息。例如 gradle.properties 文件案例:加快构建速度的,gradle.properties 文件中的属性会自动在项目运行时加载。

1
2
3
4
5
6
7
8
9
10
## 设置此参数主要是编译下载包会占用大量的内存,可能会内存溢出 
org.gradle.jvmargs=-Xms4096m -Xmx8192m
## 开启gradle缓存
org.gradle.caching=true
#开启并行编译
org.gradle.parallel=true
#启用新的孵化模式
org.gradle.configureondemand=true
#开启守护进程
org.gradle.daemon=true

Buildscript

buildscript 里是 gradle 脚本执行所需依赖,分别是对应的 maven 库和插件。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import org.apache.commons.codec.binary.Base64 
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath group: 'commons-codec', name: 'commons-codec', version: '1.2'
}
}
tasks.register('encode') {
doLast {
def byte[] encodedString = new Base64().encode('hello world\n'.getBytes())
println new String(encodedString)
}
}

需要注意的是:

  1. buildscript{}必须在 build.gradle 文件的最前端。
  2. 2.对于多项目构建,项目的 buildscript ()方法声明的依赖关系可用于其所有子项目的构建脚本。
  3. 构建脚本依赖可能是 Gradle 插件。

如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
//老式apply插件的引用方式,使用apply+buildscript 
buildscript {
ext {
springBootVersion = "2.3.3.RELEASE"
}
repositories {
mavenLocal()
maven { url 'http://maven.aliyun.com/nexus/content/groups/public' }
jcenter()
}
//此处引入插件
dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
}
}
apply plugin: 'java' //核心插件,无需事先引入
apply plugin: 'org.springframework.boot' //社区插件,需要事先引入,才能应用,不必写版本号
asspath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
}
}
apply plugin: 'java' //核心插件,无需事先引入
apply plugin: 'org.springframework.boot' //社区插件,需要事先引入,才能应用,不必写版本号