【Gradle-5】Gradle常用命令與引數
本文為稀土掘金技術社群首發簽約文章,14天內禁止轉載,14天后未獲授權禁止轉載,侵權必究!
1、前言
Gradle的命令有很多,熟悉常用命令之後,在日常開發中,不僅可以提升效率,也可以輔助我們快速定位並解決編譯問題;而且某些情況下命令列(CLI)與按鈕執行的編譯結果是不一樣的,比如構建時要傳參(-P),所以就單拎出來一篇講解,希望對你有幫助~
1、Gradle命令
1.1、gradlew
Gradle執行命令列主要用到的是Gradle Wrapper
,關於Gradle Wrapper的介紹,在前文(【Gradle-2】一文搞懂Gradle配置)中有介紹,這裡不再贅述。
所以我們常用的./gradlew
(Mac),gradlew即Gradle Wrapper的簡寫。
Gradle Wrapper工作流:
再來看下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
http://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主要乾了幾件事:
- 獲取電腦系統核心的資訊,JRE環境資訊等;
- 設定classpath路徑;
- 執行java命令工具,呼叫gradle jar包的class檔案;
1.2、命令大全
當我們想知道一個工具有哪些命令的時候,最簡單直接的方式就是使用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 http://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
簡寫:
./gradlew -?
// or
./gradlew -h
可以看到上面的輸出已經列出來了很多命令,可能有些見過有些沒見過,下面將把常用的提煉出來講解,並進行分類。
1.3、命令結構
gradle [taskName...] [--option-name...]
多個任務用空格分隔。
2、Gradle相關
2.1、檢視Gradle版本
常見的檢視Gradle版本有兩種方式。
第一種是直接在gradle>wrapper>gradle-wrapper.properties檔案下檢視distributionUrl
所使用的gradle版本下載地址:
distributionUrl=http://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 ```
2.2、升級Gradle
常見的升級Gradle有3種方式。
第一種,先手動修改wrapper.properties檔案下distributionUrl指向的版本,再手動修改Android Gradle Plugin(AGP)版本,然後重新sync。
第二種,開啟file>Project Structure修改AGP和Gradle的版本,然後apply。
第三種,用命令列的方式(官方推薦,不過跟著AS一起升也是可以的):
./gradlew wrapper --gradle-version 7.5.1
3、編譯命令
3.1、檢查依賴並編譯打包
./gradlew build
3.2、編譯並打出Debug包
./gradlew assembleDebug
3.3、編譯打出Debug包並安裝
./gradlew installDebug
3.4、編譯並打出Release包
./gradlew assembleRelease
3.5、編譯打出Release包並安裝
./gradlew installRelease
3.6、Debug/Release編譯並列印日誌
./gradlew assembleDebug --info
// or
./gradlew assembleRelease --info
4、清除命令
清除構建目錄下的產物。
./gradlew clean
等同於Build->Clean Project。
5、解除安裝命令
5.1、解除安裝Debug/Release安裝包
./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.
5.2、adb解除安裝
在Android Studio中執行是直接解除安裝的當前專案安裝包,如果是adb執行則需要指定包名
。
adb uninstall com.yechaoa.gradlex
6、除錯命令
除錯命令在定位編譯問題的時候非常有用。
當我們遇到編譯錯誤的時候,經常會看到這個提示:
``` * 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. ```
6.1、編譯並列印堆疊日誌
./gradlew assembleDebug --stacktrace
// or
./gradlew assembleDebug -s
詳細版:
./gradlew assembleDebug --full-stacktrace
// or
./gradlew assembleDebug -S
6.2、日誌級別
有時候構建日誌會有很多,看到的可能不全,甚至不是真正的編譯問題,而構建日誌又不能像logcat
那樣可以視覺化的篩選,這個時候就需要用日誌級別來篩選一下。
``` -q,--quiet 僅記錄錯誤。
-w,--warn 將日誌級別設定為警告。
-i,--info 將日誌級別設定為資訊。
-d,--debug 除錯模式(包括正常的stacktrace)。 ```
示例:
./gradlew assembleDebug -w
7、任務相關
7.1、檢視主要Task
./gradlew tasks
7.2、檢視所有Task
./gradlew tasks --all
7.3、執行Task
./gradlew taskName
// or
./gradlew :moduleName:taskName
同時,可在AS右側工具類Gradle中檢視專案及module的Task,並可以點選執行對應Task。
8、檢視依賴
編譯有很多問題都是依賴導致的錯誤,檢視依賴能幫我們快速定位問題所在。
8.1、檢視專案根目錄下的依賴
./gradlew dependencies
8.2、檢視app模組下的依賴
./gradlew app:dependencies
8.3、檢視依賴輸出到檔案
./gradlew app:dependencies > dependencies.txt
示例:
9、效能相關
9.1、離線編譯
./gradlew assembleDebug --offline
9.2、構建快取
``` ./gradlew assembleDebug --build-cache // 開啟
./gradlew assembleDebug --no-build-cache // 不開啟 ```
9.3、配置快取
``` ./gradlew assembleDebug --configuration-cache // 開啟
./gradlew assembleDebug --no-configuration-cache // 不開啟 ```
9.4、並行構建
``` ./gradlew assembleDebug --parallel // 開啟
./gradlew assembleDebug --no-parallel // 不開啟 ```
以上9.1-9.4的配置也都可以在gradle.properties
中配置。
示例:
```
並行編譯
org.gradle.parallel=true
構建快取
org.gradle.caching=true ```
9.5、編譯並輸出效能報告
./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檔案,用瀏覽器開啟:
9.6、編譯並輸出更詳細效能報告
./gradlew assembleDebug --scan
首次執行需要郵箱驗證,授權即可,完事之後即可開啟連結,scan
報告內容比profile更加詳細。
10、動態傳參
再來介紹一個比較常用的傳參屬性,--project-prop
,我們一般常用-P
表示,用來設定根專案的專案屬性。
10.1、獲取引數
示例:
./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 構建結束了 ```
可以看到已經打印出來了。
還沒完,獲取到引數是不錯,但是還沒獲取到引數的值。
10.2、獲取引數值
我們可以用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'))
。
10.3、自定義操作
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之類的也可以通過動態傳參的方式去做自定義操作。
11、總結
本文介紹了Gradle Command-Line Interface(CLI)相關的知識,像除錯命令、檢視依賴、效能相關、動態傳參這些,在定位問題、提升效率的時候還是非常有用的,希望能給你帶來收穫。(別忘了三連啊喂~)
12、Github
http://github.com/yechaoa/GradleX
13、相關文件
- 【yechaoa】2022進階成長,揚帆再起航!
- 【Gradle-5】Gradle常用命令與引數
- 【Gradle-2】一文搞懂Gradle配置
- 【yechaoa】5年Android開發的2021年終總結,實現Flag的一年
- 程式碼規範-對抗軟體複雜度
- 【建議收藏】17個XML佈局小技巧
- 【造輪子】自定義一個隨意拖拽可吸邊的懸浮View
- 怎麼簡單實現選單拖拽排序的功能
- 【保姆級】包體積優化教程
- Android通知Notification使用全解析,看這篇就夠了
- 【首發】根據桌布修改App主題,它真的來了
- Android原生TabLayout使用全解析,看這篇就夠了
- 【漲姿勢】你沒用過的BadgeDrawable
- Android包體積優化(常規、進階、極致)
- Android Studio Arctic Fox | 2020.3.1、Gradle 7.0升級記錄
- Android 11適配指南之Toast解析
- Android 自定義View之隨機數驗證碼(仿寫鴻洋)
- Jetpack之Room的使用,結合Flow
- Android MediaPlayer音訊播放器詳解
- Android 修改系統音量及監聽