1. 程式人生 > >Gradle基礎:9:wrapper的使用

Gradle基礎:9:wrapper的使用

Gradle Wrapper是gradle建議的使用方式,這篇文章將會結合具體的例子來說明一下如何使用。

Gradle Wrapper

Gradle Wrapper實際上就是一個指令碼,使用它可以下載和使用指定版本的gradle,根據需要進行在使用之前進行下載,有效避免本地機器的設定等環境一致性問題。
雖然gradle的安裝已經非常簡單,但是使用gradle wrapper是的開發這能夠以一種更為標準化的方式建立gradle專案。

使用方式

Gradle Wrapper的使用方式主要是按照如下步驟:

  • Step 1: 下載gradle
  • Step 2: 將下載的gradle解壓並存儲至GRADLE_USER_HOME所指定的目錄
  • Step 3: 使用解壓的gradle
    在這裡插入圖片描述

事前準備

使用下面的程式碼示例,內容不再說明,具體說明資訊請參看:

liumiaocn:wrapper liumiao$ ls
build.gradle
liumiaocn:wrapper liumiao$ cat build.gradle 
println "[phase:configuration] build.gradle ..."

task compile {
  group 'compile'
  description 'compile task'
  println "[phase:configuration] compile"
  doFirst {
    println "[phase:execution] compile :doFirst()"
  }
}

tasks.create(name: 'test',dependsOn: compile) {
  group 'test'
  description 'test task'
  println "[phase:configuration] test"
  doLast {
    println "[phase:execution] test:doLast()"
  }
}

tasks.create("packaging") {
  group 'packaging'
  description 'packaging task'
  dependsOn test
  enabled   true
  println "[phase:configuration] packaging"
  doLast {
    println "[phase:execution] packaging:doLast()"
  }
}

class Install extends DefaultTask{
  String installObjectName

  @TaskAction
  void checkObject() {
    println "[phase:execution] install:checkObject   (${installObjectName})"
  }

  @TaskAction
  void installObject() {
    println "[phase:execution] install:installObject (${installObjectName})"
  }
}

task install(type: Install) {
  group 'install'
  description 'install task'
  installObjectName 'test.jar'

  println "[phase:configuration] install"
  doFirst {
    println "[phase:execution] install:doFirst()"
  }
  doLast {
    println "[phase:execution] install:doLast()"
  }
}
install.dependsOn packaging
install.onlyIf { packaging.enabled }
liumiaocn:wrapper liumiao$

gradle wrapper

通過gradle tasks可以確認到在Build Setup tasks中有wrapper這樣一個內建的任務。

liumiaocn:wrapper liumiao$ gradle tasks
...省略
------------------------------------------------------------
All tasks runnable from root project
------------------------------------------------------------

Build Setup tasks
-----------------
init - Initializes a new Gradle build.
wrapper - Generates Gradle wrapper files.
...省略
BUILD SUCCESSFUL in 0s
1 actionable task: 1 executed
liumiaocn:wrapper liumiao$ 

wrapper的說明是這個任務是用來建立gradle wrapper檔案,接下里我們來看一下具體建立了那些檔案

liumiaocn:wrapper liumiao$ ls
build.gradle
liumiaocn:wrapper liumiao$ gradle wrapper

> Configure project :
[phase:configuration] build.gradle ...
[phase:configuration] compile
[phase:configuration] test
[phase:configuration] packaging
[phase:configuration] install

BUILD SUCCESSFUL in 0s
1 actionable task: 1 executed
liumiaocn:wrapper liumiao$ ls
build.gradle gradle       gradlew      gradlew.bat
liumiaocn:wrapper liumiao$ tree
.
├── build.gradle
├── gradle
│   └── wrapper
│       ├── gradle-wrapper.jar
│       └── gradle-wrapper.properties
├── gradlew
└── gradlew.bat

2 directories, 5 files
liumiaocn:wrapper liumiao$ 

檔案說明:

  • gradlew:linux或者Unix下用於執行wrapper命令的Shell指令碼
  • gradlew.bat:Windows下用於執行wrapper命令的批處理指令碼
  • gradle-wrapper.jar:用於下載Gradle的相關程式碼實現
  • gradle-wrapper.properties:wrapper所使用的配置資訊,比如gradle的版本等資訊
  • 預設狀況下的gradle-wrapper.properties的資訊如下
liumiaocn:wrapper liumiao$ cat gradle/wrapper/gradle-wrapper.properties 
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.2-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
liumiaocn:wrapper liumiao$

GRADLE_USER_HOME可以通過環境變數的方式設定,預設的GRADLE_USER_HOME為 H O M E / . g r a d l e g r a d l e {HOME}/.gradle,根據這裡的資訊可以看到,下載的gradle將會解壓到 {HOME}/.gradle/wrapper/dists

使用場景

當前系統安裝的gradle的版本為4.10.2,但是在當前的project裡面希望使用5.0的gradle,這時gradle wrapper就可以一顯身手了

事前確認

當前gradle的版本為4.10.2

liumiaocn:wrapper liumiao$ gradle -v

------------------------------------------------------------
Gradle 4.10.2
------------------------------------------------------------

Build time:   2018-09-19 18:10:15 UTC
Revision:     b4d8d5d170bb4ba516e88d7fe5647e2323d791dd

Kotlin DSL:   1.0-rc-6
Kotlin:       1.2.61
Groovy:       2.4.15
Ant:          Apache Ant(TM) version 1.9.11 compiled on March 23 2018
JVM:          1.8.0_191 (Oracle Corporation 25.191-b12)
OS:           Mac OS X 10.14 x86_64

liumiaocn:wrapper liumiao$

設定wrapper使用的gradle版本

可以使用命令來修改wrapper所使用的gradle版本資訊

liumiaocn:wrapper liumiao$ gradle wrapper --gradle-version 5.0-rc-5 --distribution-type bin
Starting a Gradle Daemon (subsequent builds will be faster)

> Configure project :
[phase:configuration] build.gradle ...
[phase:configuration] compile
[phase:configuration] test
[phase:configuration] packaging
[phase:configuration] install

BUILD SUCCESSFUL in 3s
1 actionable task: 1 executed
liumiaocn:wrapper liumiao$

可以看到,實際這條命令只是修改了gradle wrapper的配置檔案的下載檔案的資訊

liumiaocn:wrapper liumiao$ cat gradle/wrapper/gradle-wrapper.properties 
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-5.0-rc-5-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
liumiaocn:wrapper liumiao$ 

當然設定也可以通過gradle-distribution-url選項或者直接修改配置檔案來更快實現,至於具體版本,gradle的安裝檔案包符合:
gradle-版本資訊-bin|all.zip的格式,按照這種格式即可
在這裡插入圖片描述

wrapper使用

只需要設定下載url所指定的gradle版本資訊,wrapper的準備就已經就緒,隨便使用任何一個wrapper的命令,第一次執行都會首先下載gradle並解壓到${HOME}/.gradle/wrapper/dists,在在執行之前我們可以看到目前還沒有任何內容

liumiaocn:wrapper liumiao$ ls
build.gradle gradle       gradlew      gradlew.bat
liumiaocn:wrapper liumiao$ ls ${HOME}/.gradle/wrapper/dists
ls: /Users/liumiao/.gradle/wrapper/dists: No such file or directory
liumiaocn:wrapper liumiao$ 

gradle wrapper之所以有被叫做wrapper,就是因為封了一層,所以gradle的基本命令在這裡都可以使用,這裡直接使用上文確認gradle版本所用的-v

liumiaocn:wrapper liumiao$ ./gradlew -v
Downloading https://services.gradle.org/distributions/gradle-5.0-rc-5-bin.zip
.................................................................................

Welcome to Gradle 5.0-rc-5!

Here are the highlights of this release:
 - Kotlin DSL 1.0
 - Task timeouts
 - Dependency alignment aka BOM support
 - Interactive `gradle init`

For more details see https://docs.gradle.org/5.0-rc-5/release-notes.html


------------------------------------------------------------
Gradle 5.0-rc-5
------------------------------------------------------------

Build time:   2018-11-22 19:58:45 UTC
Revision:     42e59c2484a49702234030881640aa8d8bfa6d43

Kotlin DSL:   1.0.4
Kotlin:       1.3.10
Groovy:       2.5.4
Ant:          Apache Ant(TM) version 1.9.13 compiled on July 10 2018
JVM:          1.8.0_191 (Oracle Corporation 25.191-b12)
OS:           Mac OS X 10.14 x86_64

liumiaocn:wrapper liumiao$

所以看到第一次執行有Downloading https://services.gradle.org/distributions/gradle-5.0-rc-5-bin.zip的動作,而具體的版本正是之前所設定的,gradle的下載和解壓對我們來說都是透明的,為什麼wrapper能找到這個5.0的版本呢

liumiaocn:wrapper liumiao$ ls ${HOME}/.gradle/wrapper/dists
gradle-5.0-rc-5-bin
liumiaocn:wrapper liumiao$ 

可以看到,wrapper把它下載並解壓到這裡了,當然也可以使用系統已經安裝的gradle,這種方式直接設定GRADLE_USER_HOME即可。而且下載和設定的動作只會發生一次,除非你手動再次將其刪除,現在再次使用gradlew就會清晰的多了

liumiaocn:wrapper liumiao$ ./gradlew -v

------------------------------------------------------------
Gradle 5.0-rc-5
------------------------------------------------------------

Build time:   2018-11-22 19:58:45 UTC
Revision:     42e59c2484a49702234030881640aa8d8bfa6d43

Kotlin DSL:   1.0.4
Kotlin:       1.3.10
Groovy:       2.5.4
Ant:          Apache Ant(TM) version 1.9.13 compiled on July 10 2018
JVM:          1.8.0_191 (Oracle Corporation 25.191-b12)
OS:           Mac OS X 10.14 x86_64

liumiaocn:wrapper liumiao$

接下來就可以想使用gradle一樣使用gradlew了,比如需要執行install的任務

liumiaocn:wrapper liumiao$ ./gradlew install
Starting a Gradle Daemon (subsequent builds will be faster)

> Configure project :
[phase:configuration] build.gradle ...
[phase:configuration] compile
[phase:configuration] test
[phase:configuration] packaging
[phase:configuration] install

> Task :compile
[phase:execution] compile :doFirst()

> Task :test
[phase:execution] test:doLast()

> Task :packaging
[phase:execution] packaging:doLast()

> Task :install
[phase:execution] install:doFirst()
[phase:execution] install:installObject (test.jar)
[phase:execution] install:checkObject   (test.jar)
[phase:execution] install:doLast()

BUILD SUCCESSFUL in 3s
4 actionable tasks: 4 executed
liumiaocn:wrapper liumiao$ 

可以看到同樣的指令碼在gradle 5中也能正常執行

總結

gradle wrapper對於較為熟悉設定使用者來說,似乎更像一個雞肋的功能,因為gradle本身的設定就非常簡單,但是對於團隊開發來說,這種事情如果能夠坐等透明化和標準化對於專案來說自然是很不錯的一個方式,也是我們在推行DevOps時對於開發環境標準化的一個小的實踐。

參考內容

https://docs.gradle.org/current/userguide/gradle_wrapper.html