赞
踩
Gradle的命令有很多,熟悉常用命令之后,在日常开发中,不仅可以提升效率,也可以辅助我们快速定位并解决编译问题;而且某些情况下命令行(CLI)与按钮执行的编译结果是不一样的,比如构建时要传参(-P),所以就单拎出来一篇讲解,希望对你有帮助~
Gradle执行命令行主要用到的是Gradle Wrapper
,关于Gradle Wrapper的介绍,在前文(【Gradle-2】一文搞懂Gradle配置)中有介绍,这里不再赘述。
所以我们常用的./gradlew
(Mac),gradlew即Gradle Wrapper的简写。
Gradle Wrapper工作流:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-u7v6ehMV-1669900260133)(https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/79e8b3f26baa4012a6cfcfbc1e1a4c54~tplv-k3u1fbpfcp-zoom-in-crop-mark:4536:0:0:0.image)]
再来看下gradlew
的脚本内容
#!/usr/bin/env sh # # Copyright 2015 the original author or authors. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # https://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ############################################################################## ## ## Gradle start up script for UN*X ## ############################################################################## # Attempt to set APP_HOME # Resolve links: $0 may be a link PRG="$0" # Need this for relative symlinks. while [ -h "$PRG" ] ; do ls=`ls -ld "$PRG"` link=`expr "$ls" : '.*-> (.*)$'` if expr "$link" : '/.*' > /dev/null; then PRG="$link" else PRG=`dirname "$PRG"`"/$link" fi done SAVED="`pwd`" cd "`dirname "$PRG"`/" >/dev/null APP_HOME="`pwd -P`" cd "$SAVED" >/dev/null APP_NAME="Gradle" APP_BASE_NAME=`basename "$0"` # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD="maximum" warn () { echo "$*" } die () { echo echo "$*" echo exit 1 } # OS specific support (must be 'true' or 'false'). cygwin=false msys=false darwin=false nonstop=false case "`uname`" in CYGWIN* ) cygwin=true ;; Darwin* ) darwin=true ;; MINGW* ) msys=true ;; NONSTOP* ) nonstop=true ;; esac CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar # Determine the Java command to use to start the JVM. if [ -n "$JAVA_HOME" ] ; then if [ -x "$JAVA_HOME/jre/sh/java" ] ; then # IBM's JDK on AIX uses strange locations for the executables JAVACMD="$JAVA_HOME/jre/sh/java" else JAVACMD="$JAVA_HOME/bin/java" fi if [ ! -x "$JAVACMD" ] ; then die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME Please set the JAVA_HOME variable in your environment to match the location of your Java installation." fi else JAVACMD="java" which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. Please set the JAVA_HOME variable in your environment to match the location of your Java installation." fi # Increase the maximum file descriptors if we can. if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then MAX_FD_LIMIT=`ulimit -H -n` if [ $? -eq 0 ] ; then if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then MAX_FD="$MAX_FD_LIMIT" fi ulimit -n $MAX_FD if [ $? -ne 0 ] ; then warn "Could not set maximum file descriptor limit: $MAX_FD" fi else warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" fi fi # For Darwin, add options to specify how the application appears in the dock if $darwin; then GRADLE_OPTS="$GRADLE_OPTS "-Xdock:name=$APP_NAME" "-Xdock:icon=$APP_HOME/media/gradle.icns"" fi # For Cygwin or MSYS, switch paths to Windows format before running java if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then APP_HOME=`cygpath --path --mixed "$APP_HOME"` CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` JAVACMD=`cygpath --unix "$JAVACMD"` # We build the pattern for arguments to be converted via cygpath ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` SEP="" for dir in $ROOTDIRSRAW ; do ROOTDIRS="$ROOTDIRS$SEP$dir" SEP="|" done OURCYGPATTERN="(^($ROOTDIRS))" # Add a user-defined pattern to the cygpath arguments if [ "$GRADLE_CYGPATTERN" != "" ] ; then OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" fi # Now convert the arguments - kludge to limit ourselves to /bin/sh i=0 for arg in "$@" ; do CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` else eval `echo args$i`=""$arg"" fi i=`expr $i + 1` done case $i in 0) set -- ;; 1) set -- "$args0" ;; 2) set -- "$args0" "$args1" ;; 3) set -- "$args0" "$args1" "$args2" ;; 4) set -- "$args0" "$args1" "$args2" "$args3" ;; 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; esac fi # Escape application args save () { for i do printf %s\n "$i" | sed "s/'/'\\''/g;1s/^/'/;$s/$/' \\/" ; done echo " " } APP_ARGS=`save "$@"` # Collect all arguments for the java command, following the shell quoting and substitution rules eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS ""-Dorg.gradle.appname=$APP_BASE_NAME"" -classpath ""$CLASSPATH"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" exec "$JAVACMD" "$@"
代码量不多,gradlew主要干了几件事:
当我们想知道一个工具有哪些命令的时候,最简单直接的方式就是使用help
命令查看支持哪些,然后从中找到我们想要的。
执行:
./gradlew --help
输出:
USAGE: gradlew [option...] [task...] -?, -h, --help Shows this help message. -a, --no-rebuild Do not rebuild project dependencies. -b, --build-file Specify the build file. [deprecated] --build-cache Enables the Gradle build cache. Gradle will try to reuse outputs from previous builds. -c, --settings-file Specify the settings file. [deprecated] --configuration-cache Enables the configuration cache. Gradle will try to reuse the build configuration from previous builds. [incubating] --configuration-cache-problems Configures how the configuration cache handles problems (fail or warn). Defaults to fail. [incubating] --configure-on-demand Configure necessary projects only. Gradle will attempt to reduce configuration time for large multi-project builds. [incubating] --console Specifies which type of console output to generate. Values are 'plain', 'auto' (default), 'rich' or 'verbose'. --continue Continue task execution after a task failure. -D, --system-prop Set system property of the JVM (e.g. -Dmyprop=myvalue). -d, --debug Log in debug mode (includes normal stacktrace). --daemon Uses the Gradle daemon to run the build. Starts the daemon if not running. --export-keys Exports the public keys used for dependency verification. -F, --dependency-verification Configures the dependency verification mode. Values are 'strict', 'lenient' or 'off'. --foreground Starts the Gradle daemon in the foreground. -g, --gradle-user-home Specifies the Gradle user home directory. Defaults to ~/.gradle -I, --init-script Specify an initialization script. -i, --info Set log level to info. --include-build Include the specified build in the composite. -M, --write-verification-metadata Generates checksums for dependencies used in the project (comma-separated list) -m, --dry-run Run the builds with all task actions disabled. --max-workers Configure the number of concurrent workers Gradle is allowed to use. --no-build-cache Disables the Gradle build cache. --no-configuration-cache Disables the configuration cache. [incubating] --no-configure-on-demand Disables the use of configuration on demand. [incubating] --no-daemon Do not use the Gradle daemon to run the build. Useful occasionally if you have configured Gradle to always run with the daemon by default. --no-parallel Disables parallel execution to build projects. --no-scan Disables the creation of a build scan. For more information about build scans, please visit https://gradle.com/build-scans. --no-watch-fs Disables watching the file system. --offline Execute the build without accessing network resources. -P, --project-prop Set project property for the build script (e.g. -Pmyprop=myvalue). -p, --project-dir Specifies the start directory for Gradle. Defaults to current directory. --parallel Build projects in parallel. Gradle will attempt to determine the optimal number of executor threads to use. --priority Specifies the scheduling priority for the Gradle daemon and all processes launched by it. Values are 'normal' (default) or 'low' --profile Profile build execution time and generates a report in the <build_dir>/reports/profile directory. --project-cache-dir Specify the project-specific cache directory. Defaults to .gradle in the root project directory. -q, --quiet Log errors only. --refresh-dependencies Refresh the state of dependencies. --refresh-keys Refresh the public keys used for dependency verification. --rerun-tasks Ignore previously cached task results. -S, --full-stacktrace Print out the full (very verbose) stacktrace for all exceptions. -s, --stacktrace Print out the stacktrace for all exceptions. --scan Creates a build scan. Gradle will emit a warning if the build scan plugin has not been applied. (https://gradle.com/build-scans) --status Shows status of running and recently stopped Gradle daemon(s). --stop Stops the Gradle daemon if it is running. -t, --continuous Enables continuous build. Gradle does not exit and will re-execute tasks when task file inputs change. --update-locks Perform a partial update of the dependency lock, letting passed in module notations change version. [incubating] -v, --version Print version info. -w, --warn Set log level to warn. --warning-mode Specifies which mode of warnings to generate. Values are 'all', 'fail', 'summary'(default) or 'none' --watch-fs Enables watching the file system for changes, allowing data about the file system to be re-used for the next build. --write-locks Persists dependency resolution for locked configurations, ignoring existing locking information if it exists -x, --exclude-task Specify a task to be excluded from execution.
简写:
./gradlew -?
// or
./gradlew -h
可以看到上面的输出已经列出来了很多命令,可能有些见过有些没见过,下面将把常用的提炼出来讲解,并进行分类。
gradle [taskName...] [--option-name...]
多个任务用空格分隔。
常见的查看Gradle版本有两种方式。
第一种是直接在gradle>wrapper>gradle-wrapper.properties文件下查看distributionUrl
所使用的gradle版本下载地址:
distributionUrl=https://services.gradle.org/distributions/gradle-7.4-bin.zip
这里的distributionUrl即表示当前所用的gradle版本为7.4。
第二种就是使用命令行的方式查看当前版本。
执行:
./gradlew -version
// or
./gradlew -v
输出:
------------------------------------------------------------
Gradle 7.4
------------------------------------------------------------
Build time: 2022-02-08 09:58:38 UTC
Revision: f0d9291c04b90b59445041eaa75b2ee744162586
Kotlin: 1.5.31
Groovy: 3.0.9
Ant: Apache Ant(TM) version 1.10.11 compiled on July 10 2021
JVM: 11 (Oracle Corporation 11+28)
OS: Mac OS X 10.16 x86_64
常见的升级Gradle有3种方式。
第一种,先手动修改wrapper.properties文件下distributionUrl指向的版本,再手动修改Android Gradle Plugin(AGP)版本,然后重新sync。
第二种,打开file>Project Structure修改AGP和Gradle的版本,然后apply。
第三种,用命令行的方式(官方推荐,不过跟着AS一起升也是可以的):
./gradlew wrapper --gradle-version 7.5.1
./gradlew build
./gradlew assembleDebug
./gradlew installDebug
./gradlew assembleRelease
./gradlew installRelease
./gradlew assembleDebug --info
// or
./gradlew assembleRelease --info
清除构建目录下的产物。
./gradlew clean
等同于Build->Clean Project。
./gradlew uninstallDebug
// or
./gradlew uninstallRelease
输出:
Uninstalling com.yechaoa.gradlex (from app:debug) from device 'Pixel_5_API_31(AVD) - 12' (emulator-5554).
Uninstalled com.yechaoa.gradlex from 1 device.
在Android Studio中执行是直接卸载的当前项目安装包,如果是adb执行则需要指定包名
。
adb uninstall com.yechaoa.gradlex
调试命令在定位编译问题的时候非常有用。
当我们遇到编译错误的时候,经常会看到这个提示:
* Try:
> Run gradle tasks to get a list of available tasks.
> Run with --stacktrace option to get the stack trace.
> Run with --info or --debug option to get more log output.
> Run with --scan to get full insights.
./gradlew assembleDebug --stacktrace
// or
./gradlew assembleDebug -s
详细版:
./gradlew assembleDebug --full-stacktrace
// or
./gradlew assembleDebug -S
有时候构建日志会有很多,看到的可能不全,甚至不是真正的编译问题,而构建日志又不能像logcat
那样可以可视化的筛选,这个时候就需要用日志级别来筛选一下。
-q,--quiet
仅记录错误。
-w,--warn
将日志级别设置为警告。
-i,--info
将日志级别设置为信息。
-d,--debug
调试模式(包括正常的stacktrace)。
示例:
./gradlew assembleDebug -w
./gradlew tasks
./gradlew tasks --all
./gradlew taskName
// or
./gradlew :moduleName:taskName
同时,可在AS右侧工具类Gradle中查看项目及module的Task,并可以点击执行对应Task。
编译有很多问题都是依赖导致的错误,查看依赖能帮我们快速定位问题所在。
./gradlew dependencies
./gradlew app:dependencies
./gradlew app:dependencies > dependencies.txt
示例:
./gradlew assembleDebug --offline
./gradlew assembleDebug --build-cache // 开启
./gradlew assembleDebug --no-build-cache // 不开启
./gradlew assembleDebug --configuration-cache // 开启
./gradlew assembleDebug --no-configuration-cache // 不开启
./gradlew assembleDebug --parallel // 开启
./gradlew assembleDebug --no-parallel // 不开启
以上9.1-9.4的配置也都可以在gradle.properties
中配置。
示例:
#并行编译
org.gradle.parallel=true
#构建缓存
org.gradle.caching=true
./gradlew assembleDebug --profile
性能报告位于构建项目的GradleX/build/reports/profile/
路径下
See the profiling report at: file:///Users/yechao/AndroidStudioProjects/GradleX/build/reports/profile/profile-2022-11-29-23-13-29.html
输出的是html文件,用浏览器打开:
./gradlew assembleDebug --scan
首次执行需要邮箱验证,授权即可,完事之后即可打开链接,scan
报告内容比profile更加详细。
再来介绍一个比较常用的传参属性,--project-prop
,我们一般常用-P
表示,用来设置根项目的项目属性。
示例:
./gradlew assembleDebug -PisTest=true
这里我们用-P传了一个isTest
字段,并赋值为true
。
那在代码里如何获取这个参数呢?然后在build.gradle中编写如下代码:
if (hasProperty("isTest")){
println("---hasProperty isTest yes")
}else {
println("---hasProperty isTest no")
}
我们可以用hasProperty
来获取命令行(CLI)的参数,module或者插件也可以这么获取:
project.property('isTest')
然后我们用上面的命令编译看下输出:
➜ GradleX git:(master) ✗ ./gradlew assembleDebug -PisTest=true
---Gradle:开始初始化了
---Gradle:settingsEvaluated Settings对象评估完毕
---Gradle:projectsLoaded 准备加载Project对象了
> Configure project :
---Gradle:Projec beforeEvaluate Project开始评估,对象是 = GradleX
---hasProperty isTest yes // --- 看这里 ---
---Gradle:Projec afterEvaluate Project评估完毕,对象是 = GradleX
> Configure project :app
---Gradle:buildFinished 构建结束了
可以看到已经打印出来了。
还没完,获取到参数是不错,但是还没获取到参数的值。
我们可以用getProperty()
来获取:
if (hasProperty("isTest")) {
println("---hasProperty isTest yes")
if (Boolean.valueOf(getProperty('isTest'))) {
println("---isTest true")
} else {
println("---isTest false")
}
} else {
println("---hasProperty isTest no")
}
注意,getProperty('isTest')
这里要用单引号,另外命令行里面的参数值都是对象,还需要基本数据类型转换一下,即Boolean.valueOf(getProperty('isTest'))
。
ok,现在我们就可以针对获取的参数去做一些自定义的操作了,比如修改我们的依赖。
app>build.gradle:
dependencies { implementation 'androidx.core:core-ktx:1.7.0' if (project.hasProperty("isTest")) { println("---hasProperty isTest yes") if (Boolean.valueOf(getProperty('isTest'))) { println("---isTest true") implementation 'com.yechaoa.gradlex.devtools:devtools:1.1.1' } else { println("---isTest false") implementation 'com.yechaoa.gradlex.devtools:devtools:2.2.2' } } else { println("---hasProperty isTest no") } testImplementation 'junit:junit:4.13.2' }
这里举例,在isTest=true
的时候依赖了devtools 1.1.1版本,isTest=false
时依赖了devtools 2.2.2版本。
除了dependencies里面的依赖之外,Plugin、Task之类的也可以通过动态传参的方式去做自定义操作。
本文介绍了Gradle Command-Line Interface(CLI)相关的知识,像调试命令、查看依赖、性能相关、动态传参这些,在定位问题、提升效率的时候还是非常有用的,希望能给你带来收获。(别忘了三连啊喂~)
本文转自 [https://juejin.cn/post/7171493698243395597],如有侵权,请联系删除。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。