Gradle 5.0 正式版本釋出,一大波新特性來襲

汪海游龍發表於2018-11-27

前言

在歷經了一年多時間, 20 個 4.x 系列版本的迭代後,Gradle 官方終於在 11月26日 釋出了 5.0 的正式版本,先放上一張官方各版本 Gradle 效能對比圖

Gradle 5.0 正式版本釋出,一大波新特性來襲

官方表示這是至今為止最快、最安全,最強大的版本。

  • 改進的增量編譯
  • 更快的構建速度
  • 細粒度的傳遞依賴管理
  • 更高效的記憶體執行等等。
  • ......

讓我們趕緊來看一下有哪些令人激動的新特性。

官方新特性一覽

  • Kotlin DSL 1.0
  • Dependency version alignment
  • Gradle build initialization features
  • Searchable documentation
  • Task timeouts
  • HTTP retries during dependency resolution
  • Java 11 runtime support
  • Plugin authoring features
  • Gradle Native features
  • Promoted features

我擦,感覺一臉懵逼,沒關係,下面我會針對這些特性做些簡要的總結和說明,內容可能比較多,但是乾貨滿滿,建議耐心閱讀下去。

Kotlin DSL 1.0

早在 Gradle 4.x 版本中就已經支援了通過使用 Koltin DSL 的方式去編寫構建指令碼,但是當時剛出來,很多地方支援的還不太好(需要踩坑),所以並不推薦大家遷移過去,而是嚐鮮為主。現在 Kotlin DSL 1.0 release 版本出來後,意味著接下來你可以放心的遷移或者使用 Kotlin DSL 啦。新版本做了很多優化和改進的地方,比如:

  • Code Completion:程式碼自動完成

  • Error Highlighting:錯誤高亮

  • Quick Documentation:文件快速提示

  • Refactoring:程式碼重構

    圖片來自官方

如何遷移你的構建語言到 Kotlin DSL 上,可以參考我的另一篇文章Gradle指南之從Groovy遷移到Kotlin

Dependency version alignment

Dependency version alignment allows different modules belonging to the same logical group (a platform) to have identical versions in a dependency graph.

根據官網的介紹,直譯過來的意思是:依賴版本一致性允許屬於相同的邏輯組(平臺)的不同module 擁有相同的版本依賴圖。

這個概念確實不好理解,我自己也是花了一些時間去理解和消化。還是通過一個示例來說明吧。如果有英文水平高或者理解能力比較強的同學,歡迎指教。

比如,我們 build.gradle 有以下依賴:

	dependencies {
	    // a dependency on Jackson Databind
	    implementation 'com.fasterxml.jackson.core:jackson-databind:2.8.9'

	    // and a dependency on vert.x
	    implementation 'io.vertx:vertx-core:3.5.3'
	}
複製程式碼

因為 vertx-core 也間接依賴了 jackson-core,通過依賴傳遞,當解析依賴資訊的時候,我們實際依賴的版本號是:

  • jackson-core 版本 2.9.5(依賴傳遞)
  • jackson-databind 版本 2.8.9 -> 2.9.5(低版本通過依賴仲裁變為高版本)
  • jackson-annotation 版本 2.9.0 (jackson-databind 2.8.9 版本間接依賴 jackson-annotation 2.9.0 版本,注意這裡,因為上面的依賴仲裁,變成了被高版本 的 jackson-databind 2.9.5 所依賴)

這裡建議有興趣的同學實際在 intellij IDEA CE 裡建個簡單的 Gradle 工程,根據上面說的步驟實際操作一遍就很容易理解了。

再舉個小例子,看下下面的依賴關係:

	+--- com.google:gson:1.0.0 -> 2.0.0
	|    \--- com.google:gson-test:1.0.0
	+--- commons-io:commons-io:2.0.0
	  \--- com.google:gson:2.0.0
複製程式碼

gson 被仲裁到 2.0.0 高版本,而 gson-test 還是 1.0.0 版本,相當於原來是 gson:1.0.0 依賴的是的 gson-test:1.0.0 ,現在變成了高版本的 gson:2.0.0 依賴了低版本的 gson-test:1.0.0,這樣就很有可能會出現一些未知問題。理想的依賴應該是 gson:2.0.0 依賴的 gson-test:2.0.0。

通過以上的分析,我們發現實際上解析出來的依賴庫版本出現了和預期不一致的情況,而類似這種情況很容易會導致一些未知問題,尤其是在一些不相容老版本介面的依賴庫裡就會直接導致 Crash。

通常,針對這種問題,之前的做法可能就是簡單粗暴的強指定版本號,不過,現在有了更加優雅的方式去幫助我們去管理版本,即 Dependency version alignment,我們可以通過指定一個 platform 去管理某一組的 module

回到剛才的場景示例中,我們在 build.gradle 裡可以定義 jackson 為一組的 module 版本的規則,如下所示:

	class JacksonAlignmentRule implements ComponentMetadataRule {
	    void execute(ComponentMetadataContext ctx) {
	        ctx.details.with {
	            if (id.group.startsWith("com.fasterxml.jackson")) {
	                // declare that Jackson modules all belong to the Jackson virtual platform
	                belongsTo("com.fasterxml.jackson:jackson-platform:${id.version}")
	            }
	        }
	    }
	}
複製程式碼

然後應用該規則:

	dependencies {
	    components.all(JacksonAlignmentRule)
	}
複製程式碼

最後,在執行完 ./gradlew app:dependencies 命令後,你會發現當匹配上 com.fasterxml.jackson 組的 module 的版本都保持了一致,也就是

  • jackson-core 版本 2.9.5
  • jackson-databind 版本 2.8.9 -> 2.9.5
  • jackson-annotation 版本 2.9.0 -> 2.9.5

另外,platform 同樣也提供了強制為一組 module 指定某個版本號,比如:

	dependencies {
	    // Forcefully downgrade the Jackson platform to 2.8.9
	    implementation enforcedPlatform('com.fasterxml.jackson:jackson-platform:2.8.9')
	}
複製程式碼

還有一個比較方便的地方,就是通過 platform,我們可以直接省略該 module 的版本號(從此告別通過定義版本變數去維護眾多 module 的版本資訊),如下所示:

	dependencies {
	    // import a BOM. The versions used in this file will override any other version found in the graph
	    implementation(enforcedPlatform("org.springframework.boot:spring-boot-dependencies:1.5.8.RELEASE"))

	     // define dependencies without versions
	    implementation("com.google.code.gson:gson")
	    implementation("dom4j:dom4j")

	     // this version will be overriden by the one found in the BOM
	    implementation("org.codehaus.groovy:groovy:1.8.6")
	}
複製程式碼

Gradle build initialization features

新版本對 gradle init 方法進行了升級,通過更多的特性和互動,來幫助我們去快速初始化一個 Gradle 專案。簡單來說的話,就是加強版的腳手架。

Gradle 5.0 正式版本釋出,一大波新特性來襲

Interactive mode

當你在控制檯執行 init task 後,Gradle 將會提供更多的構建資訊提示,來幫助你生成 Gradle 模版專案。

Kotlin library and applications

init task 可以通過 kotlin-library 或者 kotlin-application 型別來設定生成一個 Kotlin 的類庫或者應用。你只需要根據它的提示來操作即可。

Generated builds use recommended configurations

init task 生成的構建指令碼將推薦使用新的 implementationtestImplementationtestRuntimeOnly 去代替 compiletestCompiletestRuntime

Configure project and source package names

  • --project-name 選項可以幫助你調整生成的專案名稱
  • --package 選項可以幫助你調整生成的專案包名

Create resource directories

init task 會建立一個空的 resource 目錄

Create a .gitignore file

init task 會生成一個簡單的 .gitignore 檔案來幫助你設定你的 Git repository 。

Searchable documentation

Gradle 的文件搜尋功能回來了(雖然我一直不知道這個功能在哪裡),總之,可以更加方便的搜尋使用者手冊和 DSL 的描述。

Gradle 5.0 正式版本釋出,一大波新特性來襲

當然,還有更方便查詢類和方法的 Gradle API Javadocs

Task timeouts

這個超時設定簡直太有用了有木有。特別是當你因為一些網路原因,導致你的 build task 一直卡在那裡的時候,你的心裡一定是萬馬奔騰的感覺,趕緊用起來吧,不要再浪費這些無用的時間了。示例:

	task hangingTask() {
	    doLast {
	        Thread.sleep(100000)
	    }
	    timeout = Duration.ofMillis(500)
	}
複製程式碼

HTTP retries during dependency resolution

HTTP 訪問重試功能,嗯。挺好

Performance features

Gradle can be started as a low-priority process

通過 --priority low 命令引數或者 org.gradle.priority=low 屬性設定可以讓你的 Gradle 以一個低優先順序的程式啟動,至於好處嘛,當然是你一邊在 building 的時候,一邊聽音樂的時候,再也不會感覺一卡一卡的了 :)

JaCoCo plugin now works with the build cache and parallel test execution

簡單看了下介紹,可以幫助你檢視程式碼覆蓋率的 JaCoCo 外掛,感興趣的同學可以點這裡瞭解更多

Gradle 5.0 正式版本釋出,一大波新特性來襲

Java 11 runtime support

Gradle 5.0 版本構建支援 Java 11 版本

Plugin authoring features

這個版本為外掛和自定義 task 提供了建立 SourceDirectorySet 的 API、提高 Provider 的 API、和構建快取的相容性提高。

Gradle Native features

Gradle Native project 持續的改善和提升 native 生態系統, 更多細節:Changes included in Gradle 5.0

Promoted features

一些現有功能的提升,詳細點選這裡

其他

5.0 版本共計修復了 166 個 issues(驚人),當然,伴隨而來的還有一些已知的 issues ,詳細可以點選這裡 5.0 release-notes

總結

Gradle 5.0 版本真的是乾貨滿滿,尤其是對於使用 Gradle 構建的 Android 或者 Java 開發者來說,像 Kotlin DSL(構建語言)、Dependency version alignment(依賴版本一致性)、Performance features(效能提升) 等等這些特性還是很讓人期待的。有興趣的小夥伴可以趕緊更新一波了。

如何升級到 Gradle 5.0 版本呢,很簡單,以下兩種方式任選其一

  • 執行 ./gradlew wrapper --gradle-version=5.0 命令

  • 或者直接修改你的 rootProject/gradle/wrapper/gradle-wrapper.properties

      distributionBase=GRADLE_USER_HOME
      distributionPath=wrapper/dists
      distributionUrl=https\://services.gradle.org/distributions/gradle-5.0-all.zip
      zipStoreBase=GRADLE_USER_HOME
      zipStorePath=wrapper/dists
    複製程式碼
  • 附上官方升級說明: Upgrade Gradle 4.x to 5.0
  • 需要注意的是:目前 Android 的專案如果要升級到 5.0 版本的 Gradle ,需要配套的升級 Android Gradle Plugin 和 Android Studio 到 3.4 版本,由於 5.0 Gradle 版本剛出來,Android Studio 3.4 版本現在還是預覽版,所以建議想升級的小夥伴,再耐心等待一段時間。

相關文章