一、前言
Gradle 提供多种机制用于配置 Gradle 和 指定项目的性能。开发者可以通过配置各种属性,用以提高Gradle的性能,以及实现某些特殊的构建需求(比如网络代理)
二、Gradle 属性配置途径
你可以用以下列出的方法来配置 Gradle 的环境变量,从上到下优先级依次降低,以找到的第一个配置为准。
- 命令行参数:命令行参数具有最高的优先级,比属性配置和环境变量优先级都要高,例如命令行参数选项
--build-cache
。 - 系统属性:存放
gradle.properties
文件中的系统属性配置,例如systemProp.http.proxyHost=somehost.org stored
。 - Gradle属性:存放在项目根目录下或者Gradle用户目录(由
GRADLE_USER_HOME
环境变量指定)下的gradle.properties
文件中的Gradle属性配置,例如org.gradle.caching=true
。 - 环境变量:执行 Gradle 的环境变量配置,例如
GRADLE_OPTS
、GRADLE_USER_HOME
等。
注意事项:以上列出来的Gradle属性配置方法,从上而下优先级依次降低,如果出现多个相同的配置,会以第一个找到的属性配置为准。
三、Gradle属性参数相关
Gradle为用于执行构建的 Java 进程提供了多种简单的配置方法。虽然可以通过 GRADLE_OPTS
或者 JAVA_OPTS
这些本地环境变量来设置构建的 Java 进程,但是这些方法依赖于开发者的设备,无法共享配置,如果对于多开发者的团队项目来说是非常不便的(每个开发者都需要在自己的设备上配置同一套配置)。我们可以将共享的统一配置(例如 JVM 内存配置、Java根目录等)存储在 gradle.properties
文件中,并将文件提交到版本控制系统(例如Git),这样依赖所有参与项目的开发者都可以获取到统一的配置,无需单独配置。
Gradle最终的参数配置是命令行参数和 gradle.properties
文件中定义的属性参数的整合,如果一个参数在多个地方进行了定义配置,那么将会按以下的顺序从上往下顺序,第一个出现的配置为准:
- 命令行中通过
-P
或者--project-prop
配置的变量参数; - Gradle用户目录(
GRADLE_USER_HOME
)中gradle.properties
文件中定义的属性; - Gradle用户目录中
gradle.properties
文件中定义的属性; - 项目根目录中
gradle.properties
文件中定义的属性; - Gradle安装目录中
gradle.properties
文件中定义的属性;
注意事项:
1. Gradle参数配置中,命令行传入的参数具有最高优先级;
2. 整个体系会存在多个gradle.properties
文件,根据优先级查找属性配置,如果配置的属性不生效,请检查更高优先级的gradle.properties
文件中是否也存在同样的属性配置;
3. Gradle用户目录是可以通过命令行传入的-Dgradle.user.home
参数变更。
下面的属性,可用于配置Gradle属性(在 gradle.properties
文件中配置):
org.gradle.caching=(true,false)
构建缓存配置。当设置为true
时,Gradle会尽可能复用任何之前构建的任务输出,可以大大提高构建速度。默认值为false
(禁用构建缓存)。org.gradle.caching.debug=(true,false)
构建缓存调试开关。当设置为true
时,部分输入属性的哈希值和构建缓存中的每一个任务的缓存key
将会在控制台中输出。默认为false
。org.gradle.configureondemand=(true,false)
启用按需配置,如果设置为true
,Gradle只会尝试配置必须的项目。默认为false
。org.gradle.console=(auto,plain,rich,verbose)
控制台显示配置,用于自定义控制台输出文字样式(彩色或者黑白等)。默认值取决于Gradle唤起方式。org.gradle.continuous.quietperiod=(# of quiet period millis)
连续构建静默等待时间配置。在使用连续性构建中,Gradle会在触发另一个构建之前静默等待一段时间,在静默等待时间内任何额外的改变,都将会重置静默等待时间。默认值是250毫秒。org.gradle.daemon=(true,false)
启用守护进程,如果设置为true
,Gradle将会启动守护进程运行构建,默认值为true
。org.gradle.daemon.idletimeout=(# of idle millis)
守护进程空闲时间上限,如果Gradle守护进程空闲时间超过这个上限,守护进程将会自己关闭。默认值是 10800000 毫秒(3小时)。org.gradle.debug=(true,false)
开启调试模式,如果设置为true
,Gradle将会启用远程调试模式运行构建,监听端口为5005,默认值为false
。需要注意的是,这个属性配置跟在 JVM 命令行中添加-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=5005
具有同等效果,并且在调试器附加完成之前,JVM虚拟机将处于暂停状态。org.gradle.debug.port=(port number)
指定调试器监听端口,仅在开启调试模式时生效,默认值是 5005。org.gradle.debug.suspend=(true,false)
附加调试器时 JVM 虚拟机是否暂停。当设置为true
并且启用了调试模式,在调试器附加完成之前,JVM虚拟机将会暂停(挂起),默认值是true
。org.gradle.java.home=(path to JDK home)
指定Java根目录。为Gradle构建进程指定一个Java主目录,这个值可以设置为 JDK 或者 jar 所在的目录路径(取决于你构建的内容,使用JDK更安全)。这个属性配置不会影响启动 Gradle 客户端VM的 Java 版本(仅影响当前的 Gradle 构建)。如果没有指定,正常情况下默认值是在系统环境变量中JAVA_HOME
指定或者指向 Java 的路径。org.gradle.jvmargs=(JVM arguments)
设置 JVM参数。指定用于 Gradle 守护进程使用的 JVM 参数。这个参数设置仅仅作用与 Gradle 构建的 JVM 内存配置,并不会影响 Gradle 客户端运行的 JVM 设置。默认值是-Xmx512m "-XX:MaxMetaspaceSize=256m"
。rg.gradle.logging.level=(quiet,warn,lifecycle,info,debug)
指定日志输出级别。Gradle会使用指定的日志输出级别,不同的级别将会影响日志输出结果和详细情况。默认值是lifecycle
。org.gradle.parallel=(true,false)
是否开启并行构建。如果设置为true
,Gradle 将会以org.gradle.workers.max
参数指定数量的 JVM 并行执行项目的并行构建。默认值是false
。org.gradle.priority=(low,normal)
指定 Gradle 守护进程极其启动的所有进程的优先级。默认值是normal
。org.gradle.vfs.verbose=(true,false)
配置监视文件系统时是否记录详细日志信息。默认值是false
。org.gradle.vfs.watch=(true,false)
是否开启监视文件系统。如果开启(设置为true
),Gradle 在构建多个项目之间会重复使用收集到的文件系统信息。默认值是false
。org.gradle.warning.mode=(all,fail,summary,none)
设置 Gradle 警告展示级别,Gradle 会根据不同值展示不同级别类型的警告信息。默认值是summary
。org.gradle.workers.max=(max # of worker processes)
设置 Gradle 最大工作线程数,设置之后,Gradle 会根据给定的最大工作线程数并行构建项目。默认值是当前设备 CPU 的线程数。org.gradle.logging.stacktrace=(internal,all,full)
指定异常堆栈输出信息级别,Gradle 会根据设置的级别在输出信息中显示异常堆栈信息的详细情况(跟命令行的--stacktrace
选项具有相同效果)。设置为internal
,只有内部的异常堆栈信息才会输出到控制台。如果设置成all
或者full
,控制台会输出所有的异常堆栈信息和构建失败信息,使用full
是控制台不会截断异常堆栈信息,将会得到更详细的输出。默认值是internal
。org.gradle.welcome=(never,once)
控制 Gradle 是否需要输出欢迎信息。如果设置为never
,不会打印欢迎信息,如果设置为once
,每一个新版本的 Gradle 启动执行时只会打印一次欢迎信息(以后不会再打印输出)。默认值是once
。- 示例:在根目录中的
gradle.properties
添加一下配置
org.gradle.logging.level=debug
- 执行任务控制台输出效果
E:\AndroidStudioProjects\ElectricityNoteLocal>gradlew testG
// 此处省略大量输出................
2022-08-11T18:45:24.825+0800 [DEBUG] [org.gradle.launcher.daemon.server.exec.ExecuteBuild] The daemon has finished executing the build.
2022-08-11T18:45:28.247+0800 [DEBUG] [org.gradle.launcher.daemon.client.DaemonClientInputForwarder] Dispatching close input message: org.gradle.launcher.daemon.protocol.CloseInput@220dc685
2022-08-11T18:45:28.247+0800 [DEBUG] [org.gradle.launcher.daemon.client.DaemonClientConnection] thread 14: dispatching class org.gradle.launcher.daemon.protocol.CloseInput
2022-08-11T18:45:28.248+0800 [DEBUG] [org.gradle.launcher.daemon.client.DaemonClient] Received result Success[value=org.gradle.launcher.exec.BuildActionResult@3232a28a] from daemon DaemonInfo{pid=3376, address=[16511852-5510-4ea9-
a66b-1788f6d3b4e4 port:59112, addresses:[/127.0.0.1]], state=Idle, lastBusy=1660214703502, context=DefaultDaemonContext[uid=8403b6d2-b421-44ab-8f88-5693ef3d7c5c,javaHome=D:\Program Files\Java\jdk1.8.0_131,daemonRegistryDir=C:\User
s\Administrator.P-20180507NGCRB\.gradle\daemon,pid=3376,idleTimeout=10800000,priority=NORMAL,daemonOpts=-Xmx2048m,-Dfile.encoding=UTF-8,-Duser.country=CN,-Duser.language=zh,-Duser.variant]} (build should be done).
2022-08-11T18:45:28.248+0800 [DEBUG] [org.gradle.launcher.daemon.client.DaemonClientConnection] thread 1: dispatching class org.gradle.launcher.daemon.protocol.Finished
2022-08-11T18:45:28.248+0800 [DEBUG] [org.gradle.launcher.daemon.client.DaemonClientConnection] thread 1: connection stop
2022-08-11T18:45:28.249+0800 [LIFECYCLE] [org.gradle.launcher.cli.DebugLoggerWarningAction]
#############################################################################
WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
Debug level logging will leak security sensitive information!
https://docs.gradle.org/6.7.1/userguide/logging.html#sec:debug_security
#############################################################################
说明:从上面的例子可以看出,执行任务时,控制台输出大量的调试信息,多数是
[DEBUG]
,当然,更高级别的[LIFECYCLE]
也会在其中。这个跟在命令行执行是使用--debug
选项参数具有一样的效果。
四、系统属性参数相关
在 Gradle 命令行中使用 -D
选项可以向运行 Gradle 的 JVM 虚拟机中传递系统参数, Gradle 命令行中 -D
选项跟 Java 命令中的 -D
选项具有相同的效果。Gradle 除了在命令行中传递系统参数之外,还可以在 gradle.properties
文件中添加以 systemProp.
为前缀的属性来设置系统属性参数。下面介绍几个可以使用的系统参数名称:
gradle.wrapperUser=(myuser)
用来指定Gradle wrapper 使用 HTTP 基本身份认证从服务器下载 Gradle 分发时的用户名。gradle.wrapperPassword=(mypassword)
用来指定Gradle wrapper 使用 HTTP 基本身份认证从服务器下载 Gradle 分发时的密码(配合gradle.wrapperUser=(myuser)
使用)。gradle.user.home=(path to directory)
用来指定Gradle 用户目录。https.protocols
指定支持的 TLS 版本,支持多个版本时使用逗号隔开。示例:TLSv1.2,TLSv1.3`
注意事项:
1. 在gradle.properties
中配置的系统属性必须以systemProp.
为前缀;
2. 在多项目构建中,只有项目根目录下的gradle.properties
文件中配置的系统属性参数有效,因为 Gradle 只会检查项目根目录中的gradle.properties
文件中以systemProp.
为前缀的属性参数,在子项目中配置的系统属性参数将会被忽略。
五、环境变量相关
在 Gradle 中,支持的环境变量有以下几个:
注意事项:命令行参数和系统属性参数,优先级均高于环境变量。
GRADLE_OPTS
用来指定启动 Gradle 客户端虚拟机时要使用到的 JVM 参数。Gradle 客户端 VM 处理命令行输入/输出,因此极少情况需要更改它的 VM 选项,实际的构建有 Gradle 守护进程运行,不受此环境变量影响。GRADLE_USER_HOME
用来指定 Gradle 用户目录(Gradle用户目录默认值为$USER_HOME/.gradle
)。JAVA_HOME
用来指定客户端 VM 使用的 JDK 所在的安装目录,这个客户端 VM 也用于守护进程(一般配置JDK环境的时候都会配置此环境变量)。如果在gradle.properties
文件中 使用org.gradle.java.home
属性配置了不同的目录,将会忽略此环境变量配置。
六、项目参数相关
在 Gradle 命令行中可以通过 -P
选项直接向 Project
实例对象添加属性参数。Gradle 也可以在系统属性参数和环境变量中使用特殊命名的变量来添加项目参数。
6.1 在系统参数中添加项目参数
在系统参数中,可以使用 org.gradle.project.
为前缀定义项目参数,Gradle 会扫描系统参数配置文件中以这个前缀开头的参数,将其解析为项目参数,并添加到 Project
对象中。但是需要注意的是,项目参数名称是去掉前缀之后的。如下示例
org.gradle.project.param1 = params1_value // 将向 Project 对象中添加 param1参数,参数值为 param1_value
6.2 在环境变量配置中添加项目参数
在环境变量中,可以使用 ORG_GRADLE_PROJECT_
为前缀定义项目参数,Gradle 会扫描环境变量中以这个前缀开头的参数,将其解析为项目参数,并添加到 Project
对象中。但是需要注意的是,项目参数名称是去掉前缀之后的。如下示例:
ORG_GRADLE_PROJECT_param1 = params1_value // 将向 Project 对象中添加 param1参数,参数值为 param1_value
注意事项:
1. 用户主目录下的属性文件配置优先级要高于项目目录下的属性文件配置。
2. 如果引用了不存在的项目参数,构建将会发生异常导致失败(对可选的参数配置应当始终使用Project.hasProperty(java.lang.String)
方法检查后使用)。
对于服务器持续构建系统来说,如果你没有管理员权限,设置项目参数这个功能就非常有用,而且设置的项目参数不易被发觉。在持续构建系统中,你无法使用 -P
选项参数,也无法更改系统级别的文件配置,那么最佳的做法就是修改持续构建系统的参数配置,添加符合期望的环境变量参数配置,这些参数配置对于普通的用户来说,也是不可见的(对用户 具有隐蔽性)。
七、配置 JVM 内存
在Gradle中,有两种方式可以修改 JVM 参数。
7.1 更改构建虚拟机的 JVM 配置
在 Gradle 属性参数配置中 org.gradle.jvmargs
属性控制运行构建的虚拟机,默认值是 -Xmx512m "-XX:MaxMetaspaceSize=256m"
。如下示例:
org.gradle.jvmargs=-Xmx2g -XX:MaxMetaspaceSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
7.2 更改虚拟机客户端的 JVM 配置
可以通过 JAVA_OPTS
环境变量更改客户端虚拟机的 JVM 配置,如下示例:
JAVA_OPTS="-Xmx64m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8"
注意事项:有一种情况下客户端VM会当做构建VM使用:如果停用了 Gradle 守护进程,并且构建 VM 需要的设定和客户端 VM 的设定一直,客户端 VM 将会直接运行构建,否则,客户端 VM 为了赋予不同的设定,将会启动一个新的 VM 来运行实际构建。
在命令行构建中,使用 --scan
选项可以使用 构建scan 功能获取 JVM 信息(包括其他构建详细信息),构建完成后会提示是否上传信息,如果上传,会生成一条连接,开发者可以通过这条连接查看整个构建的各种详细信息。如下示例:
八、使用项目属性参数配置任务
在 Gradle 构建中,可以通过在调用时指定项目属性来改变任务的行为。前面我们已经说到,项目属性参数可以配置在 gradle.properties
文件中。 运行构建时,会创建一个 Project
对象,并将 gradle.properties
文件中定义的属性添加到这个对象的属性表中,其中键值是配置文件中的属性名称。如下示例:
gradle.properties
isRelease=true
build.gradle
tasks.register("testG") {
println("regist task testG")
it.doLast {
println("TaskG do Last")
if(project.hasProperty("isRelease")) {
println("This is a release build")
} else {
println("This is not a release build")
}
}
}
- 执行结果
E:\AndroidStudioProjects\ElectricityNoteLocal>gradlew testG
> Configure project :
Task testG is added
regist task testG
> Task :testG
TaskG do Last
This is a release build
BUILD SUCCESSFUL in 1s
1 actionable task: 1 executed
九、为Gradle配置网络代理
可以通过标准的 JVM 系统属性为 Gradle 配置网络代理(可用于下载依赖等,代理的作用,这里就不多说)。可以在构建脚本中通过 System.setProperty("http.proxyHost","some_proxy_host")
进行配置,也可以在 gradle.properties
文件中添加。
注意事项:
1.gradle.properties
文件可以在多个目录中存在,有不同的优先级,如果设置的代理不生效,可检查其他目录中的gradle.properties
文件是否设置了不同的代理,更多详情可查阅前面章节: 三、Gradle属性参数相关;
2. 在gradle.properties
文件中指定代理配置时,参数是系统属性参数,所以需要添加systemProp.
前缀,例如:systemProp.http.proxyHost=some_proxy_host
。
9.1 在 gradle.properties
中配置 HTTP 代理
systemProp.http.proxyHost=www.somehost.org
systemProp.http.proxyPort=8080
systemProp.http.proxyUser=userid
systemProp.http.proxyPassword=password
systemProp.http.nonProxyHosts=*.nonproxyrepos.com|localhost
9.2 在 gradle.properties
中配置 HTTPS 代理
systemProp.https.proxyHost=www.somehost.org
systemProp.https.proxyPort=8080
systemProp.https.proxyUser=userid
systemProp.https.proxyPassword=password
# NOTE: this is not a typo.
systemProp.http.nonProxyHosts=*.nonproxyrepos.com|localhost
9.3 在 gradle.properties
中配置 SOCKS 代理
systemProp.socksProxyHost=www.somehost.org
systemProp.socksProxyPort=1080
systemProp.java.net.socks.username=userid
systemProp.java.net.socks.password=password
以上是在 gradle.properties
中配置各种代理的示例,如需了解更多的代理配置,可自行在网上学习。在这里需要注意的是,可能你的设备上已经使用了网络代理软件,但是依旧会出现 Gradle 无法下载依赖,在排除依赖问题之后,可以在 Gradle 中也配置代理尝试一下。笔者就遇到了 Gradle 无法直接使用设备上配置的网络代理。设备上已经配置了网络代理,在配置 Gradle 网络代理时,可以直接将 proxyHost
指定为 localhost
(当然,你也可以重新配置一套)。
9.4 NTLM 身份验证
NTLM 是 NT LAN Manager 的缩写,NTLM是基于挑战/应答的身份验证协议,是 Windows NT 早期版本中的标准安全协议。如果需要配置 NTLM 身份认证,除了需要提供用户名和密码外,同样需要提供身份认证域。以下有两种方法可以在设置 NTLM 代理时身份认证域。
- 在设置代理用户名(
http.proxyUser
)系统属性时,属性值采用域/用户名
的形式; - 通过
http.auth.ntlm.domain
系统属性提供身份验证域。