--- title: 'Gradle - Console 命令' disqus: kyleAlien --- Gradle - Console 命令 === ## Overview of Content 這裡說明的 gradle 命令可以全部替換為 `./gradlew` 命令,`./gradlew` 命令對於專案來說更佳的可靠 > 參考 [**Gradle 官方文件**](https://docs.gradle.org/current/userguide/command_line_interface.html#sec:command_line_executing_tasks) [TOC] ## Gradle 常見任務 以下列出幾個 Gradle 常見任務(大部分都有,但並非一定有) | 任務名 | 功能說明 | | - | - | | build | 建構專案,運行所有檢查 | | run | 運行專案 | | test | 測試項目 | | check | 檢查所有任務(包括測試、linkting) | | clean | 清除已建構任務的緩存 | ## Gradle 執行任務 gradle 命令的基本格式如下 ```shell= gradle [taskName*] [--option-name] ``` gradle 命令還有以下特點 * gradle 可執行多個任務,每個任務之間使用 空格 隔開 ```shell= # 執行 hello、world 兩個任務 gradle hello world ``` * `option` 如果有要指定數值,建議使用 `=` 來指定(空格也是可以) ```shell= # 建議方案(`=`) option=1000 # 仍可使用舊方案(`空格`) option 1000 ``` * 長格式的 `option` 有個特色,如果需要 **反向指定 `option` 只需要在原本 `option` 之前改為 `--no-`** 即可;範例如下 ```shell= --build-cache --no-build-cache ``` :::success * 為何要學習 CLI? 盡可能的學習使用,而不是依靠 IDE 給予的 UI 介面操控,知道根源這樣才能拉高開發水平 ```shell= # 查看所有命令參數 gradlew -? gradlew -h gradlew -help ``` > ![](https://hackmd.io/_uploads/B1SloxqN2.png) ::: ### 執行 tasks * gradle 執行 Tasks 的基本格式如下 1. 運行任務 ```shell= # 執行單個任務 gradle taskName ``` 2. 運行任務並指定該任務所需的 Options ```shell= # 執行單個任務 gradle taskName # 執行單個任務並帶有 option gradle taskName --exampletOption=exampleValue ``` :::warning * **`options` 名稱衝突**? 為了避免與內置(built-in)的 options 衝突,可以使用 `--` 符號來隔離自身任務的 options ```shell= gradle [--built-in-option-name...] -- [taskName] [--task-option-name...] ``` 範例:假設內置符號有 `--profile`,而你自己的任務(myTask)也有 `--profile`,指令如下(請注意註解) ```shell= # 這種指令會被誤認是內置 options gradle myTask --profile # 這種方式,才會區分出是自身 options gradle -- myTask --profile ``` ::: * 運行範例 1. 運行 **單個任務** ```shell= gralde test ``` > ![](https://hackmd.io/_uploads/B1RXS-cEn.png) 2. 運行 **多個任務**:基於任務的安全性,**任務會 ++依照你的指令順序執行++** ```shell= gralde clean test build ``` > ![](https://hackmd.io/_uploads/r1N5rW9E3.png) ### 執行 tasks - 多專案 * 有時你的專案中有許多子專案(`sub-project`),那每個子專案中都可能有相同的 gradle 任務,這是可以使用 `:` 符號區分出專案 > 就像是 Android 中可以創建多個 subProject (Module),每個 Module 都有相同的任務,這時就可以透過 `:` 指定運行的任務 指令格式如下:以下兩種方法都可以,根專案可以不用特別指定,如果要指定的話就單獨寫 `:` 即可 ```shell= gralde :子專案名稱:任務名 gralde 子專案名稱:任務名 ``` 1. 根專案下的 gradle 任務 ```shell= gradle :myTask gradle myTask ``` 2. 如果你當前在跟專案目錄下,要運行子專案下的 gradle 任務,指令如下 ```shell= gralde :my-subproject:taskName gralde my-subproject:taskName ``` :::info * 有些任務可以從根專案運行整個專案的相同任務名,有一些任務則不能 ```shell= # 所有子專案的測試任務都會被運行 gradle test # 只會運行你指定的轉案中的協助任務(目前就是根專案) gradle help ``` ::: ### 排除 task - x * 排除指定任務 ```shell= gradle -x 任務名 gradle --exclude-task 任務名 ``` * 範例:排除指定任務 ```shell= gradle clean test --exclude-task build ``` > ![](https://hackmd.io/_uploads/BybII-542.png) ### 強制運行 task --rerun-tasks * 每個 task 之間有可能會存在檢查的狀況,當遇到已經建構過並沒有修改的項目就會忽略該任務; 可以使用 `--rerun-tasks` 命令來強制運行每一個任務(也就是 cache 不會起作用),範例如下 ```shell= gradle test --rerun-tasks ``` > 以上命令類似於 `gradle clean test` > > ![](https://hackmd.io/_uploads/HJcIo-9Vn.png) ### 強制繼續執行 task --continue * gradle 如果其中一個任務失敗默認情況下會終止整個構建過程;而 `--continue` 選項的作用是允許繼續執行其他獨立的任務 ```shell= # test 失敗也會執行 clean 任務 gradle test --continue clean ``` :::warning * `--continue` 指令並不會讓會失敗的任務建構成功 (最終仍會失敗),但是他會執行其他任務 * `--continue` 指令通常用於 debug 中,可以讓我們看到建構過程中錯誤的輸出 ::: ### task 簡寫 * gradle 是透過呼叫任務名來啟動,而這個任務名我們可以簡寫,簡寫方式有幾個方案 * task name 簡寫 ```shell= gradle check gradle che ``` * task name 駝峰方式 ```shell= gradle HelloWorld gradle HW ``` :::warning 以上這兩個方法如果有重複的簡寫,則會導致任務無法被執行(因為無法分辨) ::: ## Project 資訊 Gralde 提供幾個內置任務任我們區分專案建構,可以讓我們快速了解專案關係 ### Project 自身關係資訊 * 查看目前 Project 內的結構關係 | Sub-cmd | 功能 | | - | - | | `projects` | 快速了解專案內的 Project 關係 | ```shell= gradle projects ``` > ![](https://hackmd.io/_uploads/HkJ-pzcV2.png) ### Project 依賴資訊 * 查看目前 Project/Sub-project 結構關係 > `Sub-project` 需使用 `:` 符號去指定 `Sub-project` 名,預設則是查詢根目錄的專案 | Sub-cmd | 功能 | | - | - | | `dependencies` | 找出當前專案的依賴,按配置細分(樹狀顯示) | | `buildEnvironment` | Gradle 構建的環境信息 | | `dependencyInsight` | 深入了解與指定輸入匹配的特定依賴項 | | `properties` | 專案中的屬性列表 | * 範例:`dependencies` 會列出項目的編譯依賴、運行時依賴和測試依賴,包括外部庫和其他模塊的依賴關係 ```shell= # 列出 sub-project 的依賴關係 gradle :app:dependencies ``` > 這個命令對於了解項目的依賴關係以及檢查衝突和重複依賴項非常有用 > > ![](https://hackmd.io/_uploads/rkiX2zoEn.png) * 範例:Gradle 專案的環境訊息 ```shell= # Project(根專案)的建構環境 gradle :buildEnvironment ``` :::danger * Gradle 引用插件時(`classpath`)可能有多的依賴關係,這時就可以透過 `buildEnvironment` 命令來查看插件依賴關係 ::: > ![](https://hackmd.io/_uploads/SJMiRzo4h.png) * 範例:專案中的屬性列表 ```shell= # Project 的屬性列表 gradle properties ``` > ![](https://hackmd.io/_uploads/S11MlQjE2.png) :::info * 可以 **使用 `--property` 選項**,查看特定單個屬性的詳細資訊 ```shell= # Project 的屬性列表 gradle properties --property buildDir ``` > ![](https://hackmd.io/_uploads/SJyix7o4h.png) ::: ### Project 擁有的 Task 資訊 * 查看 Project 擁有的 Task 指令,請見下表 | Sub-cmd & Options | 功能 | | - | - | | `tasks` | 依照群組的概念列出主要任務訊息 | | `tasks --all` | 獲取全部的任務訊息 | | `tasks --group 群組` | 列出指定群組任務 | | `help --task 任務名` | 顯示指定任務的協助訊息 (任務路徑、類型... 等等訊息) | * tasks Option 範例: 1. 依照群組的概念列出主要任務訊息 ```shell= gradle tasks ``` > ![](https://hackmd.io/_uploads/rySyRzqE3.png) 2. 獲取全部的任務訊息 ```shell= gradle tasks --all ``` > ![](https://hackmd.io/_uploads/B1dvAMq4n.png) 3. 列出指定群組中所有任務 ```shell= gradle tasks --group="build setup" ``` > ![](https://hackmd.io/_uploads/r1usEziE3.png) * help Option 範例:顯示指定任務的協助訊息 ```shell= gradle help --task build ``` > 包含任務完整路徑、類型、選項... 等等 > > ![](https://hackmd.io/_uploads/H1G7k75N3.png) ### Task 資訊 - 可視覺化資訊 * 任務自身依賴範例:顯示指定任務的依賴 | Options | 功能 | | - | - | | `任務名 --scan` | 列出該任務的所有依賴項目的報告 | ```shell= gradle build --scan ``` > ![](https://hackmd.io/_uploads/S1b9LfsV2.png) 掃描過後,該任務的相關訊息(報告)會傳至網站,你可以在網頁上看到相關資訊 > ![](https://hackmd.io/_uploads/H1bWDGsVh.png) :::success 任務報告依賴 查看方式 [**請看連結**](https://docs.gradle.org/current/userguide/viewing_debugging_dependencies.html#viewing-debugging-dependencies) ::: ## Debug 常用指令 * 當錯誤發生時 Gradle 有提供堆棧讓我們進行追蹤,**默認情況下堆棧是關閉的**,必須使用指令將其打開 | gradle option | 功能 | | - | - | | `-?`, `-h`, `--help` | CLI 協助訊息 | | `-v`, `--version` | 輸出 Gradle、Groovy、Ant、JVM 操作系統版本訊息 | | `-s`, `--stacktrace` | 輸出關鍵性堆棧訊息 | | `-S`, `--full-stacktrace` | 輸出全部堆棧訊息 | | `--scan` | Gradle 建構資訊 | ### 調適 - 指令設定參數 * **透過指令設定 `gradle.properties` 的值,也可以說透過指令設置 Gradle 系統屬性(暫時設定,並非真正寫入)**;其格式如下 ```shell= gralde -D設定項目=設定值 ``` Daemon 守護進程相關設置如下 | 指令 Options 設定 | 說明 | 補充 | | - | - | - | | `-Dorg.gradle.debug=(true, false)` | 調整 Gradle 客戶端(非守護進程) | - | | `-Dorg.gradle.debug.port=(port number)` | 設定 debug port 號 | 默認情況下調適器為 `localhost:5005` | | `-Dorg.gradle.debug.server=(true,false)` | Gradle 會以 socket-attach 模式調適(監聽運行) | 默認 true | | `-Dorg.gradle.debug.suspend=(true,false)` | Debug 連接上之前暫停 JVM | 默認 true | | `-Dorg.gradle.daemon.debug=(true,false)` | debug gradle daemon | - | ## 性能選項 使用指令可以設定 Gradle 建構專案的附加條件,而以下這些條件則會影響到建構專案時的性能 | 指令 Options 設定 | 說明 | 補充 | | - | - | - | | `--build-cache`, `--no-build-cache` | 取用以編譯過的輸出 | 默認 no cache | | `--configuration-cache`, `--no-configuration-cache` | 使用緩存設定 | 默認 no configuration | | `--configuration-cache-problems=(fail,warn)` | 當緩存設定出問題時的處理方式 | 預設 fail | | `--configure-on-demand`, `--no-configure-on-demand` | 是否設置在保護進程中 | 預設為 no demand | | `--max-workers` | Gradle 建構時使用的 CPU 數量 | 預設最大 | | `--parallel`, `--no-parallel` | 是否並行建構 | 預設 false | | `--priority` | 調整 Gradle 建構的優先級 | 預設 normal | | `--profile` | 在目錄 (`$buildDir/reports/profile`) 中生成性能報告 | 預設使用 scan, 而不是 profile | | `--scan` | 生成詳細的性能報告 | - | | `--watch-fs`, `--no-watch-fs` | 是否監視文件系統 (FS) | 默認開啟 | ### Gradle 守護進程 * Gradle 守護進程簡單來說就是在背景啟動一個進程協助我們建構專案,一般來說可以加快建構的速度 * 當然 Gradle 守護進程 也可以透過指令控制 | 指令 Options 設定 | 說明 | 補充 | | - | - | - | | `--daemon`, `--no-daemon` | 是否使用守護進程 | 默認 daemon | | `--foreground` | 在前台啟動守護進程 | - | | `--status` | 列出所有運行中、最近關閉的守護進程,只顯示相同版本的守護進程 | 獨立命令 | | `--stop` | 停止相同版本的守護進程 | 獨立命令 | | `-Dorg.gradle.daemon.idletimeout=(ms)` | 守護進程閒置多久後關閉 | 默認 10800000(3 小時) | :::info * 同常在 CI 集成時,會使用 `--no-deamon` 加強建構效能(因為 CI 不需要背景建構) > 背景建構通常是在開發時可以加快建構 ::: ## 日誌 在編譯時若無下達日誌指令,則會自動打印 `LIFECYCLE` 及 `ERROR` 日誌 | 級別 | 適用於 | 指令使用 | | - | - | - | | ERROR | 錯誤消息(高) | | | QUIET | 重要消息 | `-q`, `--quiet` | | WARNING | 警告消息 | `-w`, `--warn` | | LIFECYCLE | 進度消息 | | | INFO | 所有信息 | `-i`, `--info` | | DEBUG | 調適消息 | `-d`, `--debug` | ```shell= # 輸出 QUIET 等級以上(包括)的日誌訊息 gradle tasks -q # 輸出 INFO 等級以上(包括)的日誌訊息 gradle tasks -i ``` ### 指令調整日誌 - 格式 * 可以透過指令來調整日誌類型,其格式如下 ```shell= -Dorg.gradle.console=(auto,plain,rich,verbose) ``` 控制台的類型特性如下 | 類型 | 說明 | | - | - | | `auto` | 純文本,++未使用++ 終端時的默認選項 | | `plain` | 更豐富色彩的輸出,++使用++ 終端時的默認選項 | | `rich` | 構建輸出將使用 ANSI 控製字符來生成豐富的輸出 | | `verbose` | 跟 `rich` 差異不大,但在生命週期時會輸出任務名稱、結果 | ### 指令調整日誌 - 警告訊息 * **默認情況下 Gradle 不會在建構時顯示所有警告訊息**,但它會在建構完成後輸出摘要到結果(例如以下訊息) ```shell= # 建構結束時輸出的摘要 Deprecated Gradle features were used in this build, making it incompatible with Gradle 5.0. ``` * 可以通過以下指令去控制輸出的警告模式 | 指令 Options 選項 | 說明 | | - | - | | `-Dorg.gradle.warning.mode=(all,fail,none,summary)` | 同設置 `gradle.properties` | | `--warning-mode=(all,fail,none,summary)` | 單純使用指令 | 其中報告的詳細程度如下 | 報告詳細程度 | 說明 | | - | - | | `all` | 顯示所有警告 | | `fail` | **任何的警告都會讓建構失敗!** | | `summary` | 建構結束後顯示摘要 | | `none` | 不顯示任何訊息(包括摘要) | ## Build 選項 建構時可以不用全部建構、或是可以使用緩存建構,這些都可以透過指令來控制建構方式 | 指令 Options 設定 | 說明 | | - | - | | `--include-build` | 複合建構 | | `--offline` | 在不訪問網路的狀況下運行 | | `--refresh-dependencies` | 刷新依賴 | | `-m,--dry-run` | 在禁用所有任務操作的狀況下運行 | | `-t,--continuous` | 當 Gradle 任務出錯時,繼續建構(如果有失敗,最終仍會建構失敗) | | `--write-locks` | 是在構建過程中更新鎖定文件,確保鎖定文件與實際構建過程中使用的依賴項版本保持一致 | | `--update-locks <group:name>[,<group:name>]*` | 指示必須在鎖定文件中更新指定模塊的版本 | | `-a,--no-rebuild` | 對於已建立的依賴項目,不重新建構 | ## 依賴驗證 | 指令 Options 設定 | 說明 | | - | - | | `-F=(strict,lenient,off),--dependency-verification=(strict,lenient,off)` | 預設驗證(`strict`) | | `-M,--write-verification-metadata` | 對於專案中的依賴項生成校驗、進行驗證 | | `--refresh-keys` | 刷新依賴的公鑰 | | `--export-keys` | 導出依賴的公鑰 | ## 環境選項控制 在建構時可以透過指令,設定 Gradle 建構的環境 ### 指定建構文件 | 指令 Options 設定 | 說明 | 補充 | | - | - | - | | `-b`, `--build-file` | 透過該選項可以 **指定建構的文件** | 默認是使用 `build.gradle` | | `-c`, `--settings-file` | 透過該選項可以 **指定專案結構的文件** | 默認是使用 `setting.gradle` | | `-I`, `--init-script` | 指定初始化腳本文件 | - | * 以下創建一個 `test.gradle` 檔案 ```groovy= // test.gradle tasks.register("test_gradle") { doLast { println("test.gradle working.") } } ``` **使用指令選項 `--build-file` 指定 `test.gradle` 檔案作為運行建構檔,並運行 `test_gradle` 任務** > ![](https://hackmd.io/_uploads/rJJzlslrn.png) ### 指定屬性 | 指令 Options 設定 | 說明 | 補充 | | - | - | - | | `-D`, `--system-prop` | 設定系統屬性(**設定 JVM 參數**) | 常見用法:`-D參數=數值` | | `-P`, `--project-prop` | 設定項目屬性(**設定 `properties.gradle` 參數**) | 常見用法:`-P參數=數值` | ### 指定目錄 | 指令 Options 設定 | 說明 | 補充 | | - | - | - | | `--project-cache-dir` | 指定緩存目錄 | 預設為 `.gradle` 在根目錄中 | | `-p`, `--project-dir` | 指定 Gradle 的起始目錄 | 預設為當前目錄 | | `-g`, `--gradle-user-home` | 指定 Gradle 用戶目錄 | 預設在各個使用者目錄下的 `.gradle/` 資料夾 | ## 任務選項 使用 `help --task` 選項 就可以查看到相關指定任務的相關訊息 > ![](https://hackmd.io/_uploads/SJiUGjlS3.png) ### 內置任務選項 * 內置任務選項是可以跟任何任務(不管是你自己創建、或是 built-in)一起使用;Gradle 目前的內置任務選項是 `--rerun-tasks` > `--rerun-tasks` 代表,就算有緩存也強制任務重新運行 > ![](https://hackmd.io/_uploads/r10Gfsern.png) ## Gradle 初始化項目 1. Gradle 初始化時可以使用基礎的 **指令互動** ```shell= gradle init ``` 2. 直接指定 Gradle 初始化項目;詳細選項請參考 [**Init plugin**](https://docs.gradle.org/current/userguide/build_init_plugin.html#build_init_plugin) ```shell= gradle init --type basic --dsl groovy ``` ### Gradle wrapper 設置 * 在初始化項目後,預設被就就會有一個 `gradle` 資料夾,其內部就裝有 Gradle wrapper 相關文件,透過 **Gradle wrapper 可以控制專案使用的 gradle 版本**(協作任務會更方便) > ![](https://hackmd.io/_uploads/HJCtUslHn.png) 以下是幾個 Gradle wrapper 常用的指令 | Gradle Wrapper 指令 Options 設定 | 說明 | | - | - | | `--gradle-version` | 設定使用的 Gradle 版本 | | `-distribution-type` | 目前有 `bin`、`all` 可以使用,預設為 `bin` | | `--gradle-distribution-url` | 下載 Gradle 的 URL | ## 其他 ### 自動補齊工具 * **Gradle 有推出一個自動補全指令的工具** [**gradle-completion**](https://github.com/gradle/gradle-completion),幫助我們快速完成指令 * Mac 透過 `brew` 就可以快速安裝、使用 ```shell= brew install gradle-completion ``` * 手動下載安裝 1. 使用 git clone `gradle-completion` 專案 ```shell= git clone https://github.com/gradle/gradle-completion ~/.zsh/gradle-completion ``` 2. 設定 `fpath` 至 `.zshrc` 文件中 ```shell= echo "\nfpath=($HOME/.zsh/gradle-completion \$fpath)" >> ~/.zshrc ``` 3. 手動初始化 > 請先移動至你的專案資料夾下,再執行以下命令 ```shell= source ~/.zsh/gradle-completion/_gradle 1>&2 2>/dev/null; __gradle-completion-init ``` ## Appendix & FAQ :::info ::: ###### tags: `Gradle`