如果 Gradle 或 Gradle 社群沒有提供專案所需具備的特定功能,建立您自己的外掛程式可能是一個解決方案。
此外,如果您發現自己重複子專案的組建邏輯,而且需要更好的方式來組織它,自訂外掛程式可以提供幫助。
自訂外掛程式
外掛程式是實作 Plugin
介面的任何類別。以下範例是最直接的外掛程式,一個「hello world」外掛程式
import org.gradle.api.Plugin
import org.gradle.api.Project
abstract class SamplePlugin : Plugin<Project> {
override fun apply(project: Project) {
project.tasks.create("SampleTask") {
println("Hello world!")
}
}
}
腳本外掛程式
許多外掛程式會從在組建腳本中編碼的腳本外掛程式開始。這提供了一種在組建外掛程式時快速建立原型和實驗的簡單方式。讓我們來看一個範例
// Define a task
abstract class CreateFileTask : DefaultTask() { (1)
@get:Input
abstract val fileText: Property<String> (2)
@Input
val fileName = "myfile.txt"
@OutputFile
val myFile: File = File(fileName)
@TaskAction
fun action() {
myFile.createNewFile()
myFile.writeText(fileText.get())
}
}
// Define a plugin
abstract class MyPlugin : Plugin<Project> { (3)
override fun apply(project: Project) {
tasks {
register("createFileTask", CreateFileTask::class) {
group = "from my plugin"
description = "Create myfile.txt in the current directory"
fileText.set("HELLO FROM MY PLUGIN")
}
}
}
}
// Apply the local plugin
apply<MyPlugin>() (4)
1 | 建立 DefaultTask() 的子類別。 |
2 | 在任務中使用延遲組態。 |
3 | 延伸 org.gradle.api.Plugin 介面。 |
4 | 套用腳本外掛程式。 |
1. 建立 DefaultTask()
的子類別
首先,透過子類化 DefaultTask()
建立一個任務。
abstract class CreateFileTask : DefaultTask() { }
這個簡單的任務會將一個檔案加入到我們應用程式的根目錄。
2. 使用延遲配置
Gradle 有個概念稱為延遲配置,它允許在實際設定任務輸入和輸出之前,就可以參考它們。這是透過 Property
類型別來完成的。
abstract val fileText: Property<String>
這種機制的優點之一是,你可以在檔案名稱甚至尚未決定之前,將一個任務的輸出檔案連結到另一個任務的輸入檔案。Property
類別也知道它連結到哪個任務,讓 Gradle 能夠自動加入必要的任務相依性。
3. 擴充 org.gradle.api.Plugin
介面
接著,建立一個新的類別,擴充 org.gradle.api.Plugin
介面。
abstract class MyPlugin : Plugin<Project> {
override fun apply() {}
}
你可以在 apply()
方法中加入任務和其他邏輯。
4. 套用腳本外掛
最後,在建置腳本中套用本地的外掛。
apply<MyPlugin>()
當在建置腳本中套用 MyPlugin
時,Gradle 會呼叫自訂 MyPlugin
類別中定義的 fun apply() {}
方法。
這會讓外掛可用於應用程式。
不建議使用腳本外掛。腳本外掛提供一種快速建置建置邏輯的簡便方式,在將其移轉到更永久的解決方案(例如慣例外掛或二進位外掛)之前。 |
慣例外掛
慣例外掛是一種在 Gradle 中封裝並重複使用常見建置邏輯的方式。它們允許你為專案定義一組慣例,然後將這些慣例套用至其他專案或模組。
上面的範例已重新寫成一個儲存在 buildSrc
中的慣例外掛
import org.gradle.api.DefaultTask
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.api.provider.Property
import org.gradle.api.tasks.Input
import org.gradle.api.tasks.OutputFile
import org.gradle.api.tasks.TaskAction
import java.io.File
abstract class CreateFileTask : DefaultTask() {
@get:Input
abstract val fileText: Property<String>
@Input
val fileName = project.rootDir.toString() + "/myfile.txt"
@OutputFile
val myFile: File = File(fileName)
@TaskAction
fun action() {
myFile.createNewFile()
myFile.writeText(fileText.get())
}
}
class MyConventionPlugin : Plugin<Project> {
override fun apply(project: Project) {
project.tasks.register("createFileTask", CreateFileTask::class.java) {
group = "from my plugin"
description = "Create myfile.txt in the current directory"
fileText.set("HELLO FROM MY PLUGIN")
}
}
}
可以使用 gradlePlugin{}
區塊給予外掛一個 id
,以便在根目錄中參考它
gradlePlugin {
plugins {
create("my-convention-plugin") {
id = "com.gradle.plugin.my-convention-plugin"
implementationClass = "com.gradle.plugin.MyConventionPlugin"
}
}
}
gradlePlugin{}
區塊定義專案建置的外掛。有了新建立的 id
,就可以相應地在其他建置腳本中套用外掛
plugins {
application
id("com.gradle.plugin.my-convention-plugin") // Apply the new plugin
}