Gradle入門教程(四):Gradle插件

四、使用Gradle插件

Gradle本身只是一個框架,它的核心部分在構建過程中起的作用實際上很小。真正起作用的步驟來自於插件,比如編譯Java代碼的功能就是由“java”插件提供。

在本章中,我們會詳細價紹如何使用Gradle的插件

4.1 插件能做些什麼

插件可以做的事情很多,比如:

  • 擴展Gradle的功能
  • 根據用戶的配置來做一些自定義的構建
  • 增加構建多種具體項目的功能,如Android插件

使用插件有許多好處:

  • 促進腳本的複用,可以減少相似的構建腳本

  • 可以更好地組織項目結構

  • 將具體的邏輯封裝起來,然後用聲明式的方式使用

4.2 插件的類型

4.2.1 腳本插件和二進制插件

Gradle的插件分爲兩種類型:腳本插件(script plugins)和二進制插件(binary plugins)。

腳本插件 就是額外的構建腳本,腳本插件通常用來對構建過程進行深度配置,同樣遵循聲明式的思想。腳本插件常常作爲另一個腳本文件(即*.gradle) 文件被放置在項目目錄中,以本地文件的形式應用插件。雖然腳本插件也可以放置在雲端,比如說共享倉庫jcenter,但不常用,一般共享的插件都是二進制插件。

二進制插件就是實現了Plugin接口的類,可以用java、kotlin和groovy編寫,更容易進行測試,還可以被打包成jar包共享出去。

一個插件項目最開始寫的時候通常都是以腳本插件的形式,因爲它們更容易編寫,當項目變得更有價值之後再被遷移成二進制插件,這樣更容易測試以及共享。

4.2.2 核心插件和社區插件

Gradle的插件根據是否內置又分爲核心插件社區插件,核心插件是Gradle必要的插件(如java插件),核心插件隨着Gradle安裝已經解析好了,只需要應用即可;社區插件是共享在社區上的插件,在需要時才被解析到本地。

社區插件會被共享在一些在線倉庫中,例如jcenter、Maven倉庫等,Gradle還提供了一個專門共享Gradle插件的倉庫:Gradle plugin portal,Gradle官方推薦將插件共享在這裏。

4.3 Gradle插件的三種實現方式

(本小節僅簡單介紹,實現Gradle插件的方法詳見“自定義Gradle插件”章節)

4.3.1 腳本插件

可以直接在build.gradle中編寫一個實現了org.gradle.api.plugins接口的類, 這個類就是一個插件。另外,這種方式編寫的插件就是上文所提的腳本插件

4.3.2 在buildSrc中編寫插件類

Gradle提供了一種在現有項目中編寫二進制插件的方法,依舊遵循聲明式的思想。

二進制插件可以用Java、Kotlin、Groovy多種語言編寫,例如使用的是Groovy語言,那麼就創建目錄rootProjectDir/buildSrc/src/main/groovy,如果是kotlin則爲.../kotlin,Groovy則爲.../groovy。Gradle會自動編譯這些目錄下的插件,並且將它們解析,使得在項目的所有構建腳本中都可以應用這些目錄下的插件。

4.3.3 獨立項目

還可以爲你的插件單獨建立一個項目,這個項目可以被打包成一個jar包,可以實現更好的複用,還可以分享到在線倉庫成爲社區插件,給別的項目使用。

4.4 使用插件兩步走

使用插件Gradle的插件大致上分爲兩部,第一步是解析插件,第二步是應用插件。

解析插件 就是找到插件的正確版本,因爲Gradle的插件允許有多個版本同時存在,在選擇插件時要同時指定插件名和版本。對於二進制插件,因爲並不指定它們所在的路徑,Gradle要去指定的倉庫根據插件名和版本號尋找對應的插件,並解析到本地;而對於腳本插件,它是“自解析”的,因爲配置腳本插件時直接指定了它的路徑。

應用插件 就是在解析插件完成之後將插件的腳本內容應用到項目的構建中,對於二進制插件,會在此時調用它的apply方法(這個方法定義在Plugin接口中)。

4.5 傳統apply語法

使用插件有兩種語法,一種是傳統的apply語法,另一種是DSL語法。我們先介紹傳統的apply語法。

每個插件都有一個id,我們可以通過指定插件的id的方式來應用插件,以應用java插件爲例:

//build.gradle
apply plugin: 'java'

也可以直接指定插件的實現類的類名

//build.gradle
apply plugin: JavaPlugin

對於內置插件,我們可以直接通過上述的apply語法應用插件,指定類名時也不需要前綴(org.gradle.api.plugins)以及.class後綴。

但對於社區插件,我們還需要先解析插件。解析插件使用的是buildscript{}語法塊,語法規則如下:

//build.gradle
buildscript {
	repositories {
		jcenter()
	}
	dependencies {
		classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:0.4.1'
	}
}
apply plugin: 'com.jfrog.bintray'

裏面還有兩個子塊:

  • repositories{}語法塊,用於指定倉庫,有以下常用選項:
    • mavenLocal():本地Maven倉庫( ${user.home}/.m2/repository )
    • mavenCentral():中央Maven倉庫( http://repo1.maven.org/maven2 )
    • maven { url 'https://...' }:可用於Maven私服、鏡像服務器等
    • ivy {url "../local-repo"}:本地的ivy倉庫
    • ivy {url "http://repo.mycompany.com/repo"}:遠程的ivy倉庫
    • google():google倉庫(https://maven.google.com)
  • dependencies{}語法塊,用於指定要使用的插件,由classpath關鍵字指定,格式爲:classpath 'group:name:version'

4.6 plugins DSL語法

Gradle鼓勵將Gradle插件共享在它的Gradle plugin portal上,對於上面的插件Gradle還提供了簡潔的應用插件的語法,這就是“plugins DSL"語法。

因爲解析插件和應用插件通常都同時使用,所以plugins DSL語法默認同時對插件進行解析和應用,核心插件和社區插件的使用方式略有不同,核心插件只需要指定插件名,以java插件爲例:

//build.gradle
plugins {
	id 'java'
}
//build.gradle.kts
plugins {
	java
}

社區插件還需要指定版本

//build.gradle
plugins {
	id 'com.jfrog.bintray' version '0.4.1'
}
//build.gradle.kts
plugins {
	id("com.jfrog.bintray") version "0.4.1"
}

DSL語法存在着一些限制,首先是語法規則比較嚴格,這也是出於聲明式的思想,語法規則如下:

//build.gradle
plugins {
	id «plugin id» ①
	id «plugin id» version «plugin version» [apply «false»] ②
}
//① 適用於核心插件,或者已經解析好的插件、或者buildSrc中的插件
//② 適用於社區插件,因爲DSL語法默認同時解析和應用插件,加上apply «false»可以只解析不應用
//apply false的具體用法見後續章節

而且DSL語法只能用於構建腳本中,不能用於腳本插件中,也不能用於settings.gradleinit script,不過Gradle官方說會在之後的版本移除這種限制(筆者當前版本是5.6.3)

4.7 Plugin Management語法塊

4.7.1 基本語法

pluginManagement{}語法塊是專門用於管理整個項目插件的,只能出現在settings.gradle文件或”初始化腳本“中,並且在settings.gradle文件中pluginManagement{}必須是文件中的第一個塊。

語法格式如下(限於篇幅,僅以groovy舉例,kotlin語法見手冊P313):

//build.gradle
pluginManagement {
	plugins {
	}
	resolutionStrategy {
	}
	repositories {
	}
}
//init.gradle
settingsEvaluated { settings ->
	settings.pluginManagement {
		plugins {
		}	
		resolutionStrategy {
		}
		repositories {
		}
	}
}

4.7.2 設置插件的來源倉庫

默認情況下,plugins DSL語法會從Gradle plugin portal去解析插件,但許多插件開發者喜歡使用私有的Maven或Ivy倉庫,爲了指定使用的插件倉庫,Gradle提供了repositories{}語法塊,放在pluginManagement語法塊中使用,用於管理整個項目使用的插件倉庫。

語法規則如下(以本地路徑爲例,如果使用網絡資源就將路徑替換成http url):

//build.gradle
pluginManagement {
	repositories {
		maven {
			url '../maven-repo'
		}
		gradlePluginPortal()
		ivy {
			url '../ivy-repo'
		}
	}
}
//注:指定的倉庫順序就是Gradle尋找插件順序的優先級,本例中會先
//去maven倉庫嘗試解析所需插件,如果找不到再去gradlePluginPortal
//如果再找不到,最後再去ivy倉庫

4.7.3 插件版本管理

Gradle提供了plugins{}語法塊,用於pluginManagement語法塊中,用於統一指定整個倉庫使用的某個插件的版本。

使用這種方式管理插件的版本有一些好處,例如在多projects構建中很有用,因爲在多projects構建中統一每個子project依賴的插件版本很有必要;另外,前面提過,DSL語法在build.gradle有嚴格的限制,但是在settings.gradle中語法卻比較寬鬆,這允許它從gradle.properties文件中去獲取版本。

在根目錄下的settings.gradle指定了插件的版本後,在build.gradle中只需要指定插件的id即可,插件版本配置在gradle.properties中。

使用示例如下:

//settings.gradle
pluginManagement {
	plugins {
		id 'org.gradle.sample.hello' version "${helloPluginVersion}"
	}
}
//build.gradle
plugins {
	id 'org.gradle.sample.hello'
}
//gradle.properties
helloPluginVersion=1.0.0
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章