您可以使用 IntelliJ 原生匯入器Eclipse Buildship 在 IDE 中開啟此範例。

此範例顯示如何將多專案建置中的建置邏輯組織成可重複使用的外掛。

使用案例

舉例來說,一個有三個子專案的專案產生兩個公開的 Java 函式庫,這兩個函式庫使用第三個子專案作為內部共用函式庫。這是專案結構

專案結構
├── internal-module
│   └── build.gradle.kts
├── library-a
│   ├── build.gradle.kts
│   └── README.md
├── library-b
│   ├── build.gradle.kts
│   └── README.md
└── settings.gradle.kts
專案結構
├── internal-module
│   └── build.gradle
├── library-a
│   ├── build.gradle
│   └── README.md
├── library-b
│   ├── build.gradle
│   └── README.md
└── settings.gradle

假設我們的專案都是 Java 專案。在這種情況下,我們希望對所有專案套用一組共用規則,例如來源目錄配置、編譯器旗標、程式碼樣式慣例、程式碼品質檢查等等。

三個專案中有兩個不只是 Java 專案,它們是我們可能想發佈到外部儲存庫的函式庫。發佈設定,例如函式庫的共用群組名稱以及儲存庫座標,可能是兩個函式庫都需要共用的橫切關注點。對於這個範例,我們也假設我們希望強制我們的函式庫公開一些具有共用結構的文件。

組織建置邏輯

從上述用例中,我們已識別出我們有兩種專案類型 - 一般 Java 專案和公開函式庫。我們可以透過分層兩個不同的外掛程式來建模此用例,每個外掛程式定義套用它們的專案類型

建置邏輯配置
├── buildSrc
│   ├── build.gradle.kts
│   ├── settings.gradle.kts
│   ├── src
│   │   ├── main
│   │   │   └── kotlin
│   │   │       ├── myproject.java-conventions.gradle.kts
│   │   │       └── myproject.library-conventions.gradle.kts
...
建置邏輯配置
├── buildSrc
│   ├── build.gradle
│   ├── settings.gradle
│   ├── src
│   │   ├── main
│   │   │   └── groovy
│   │   │       ├── myproject.java-conventions.gradle
│   │   │       └── myproject.library-conventions.gradle
...
  • myproject.java-conventions - 設定組織中任何 Java 專案的一般慣例。它套用核心 javacheckstyle 外掛程式,以及外部 com.github.spotbugs 外掛程式,設定常見編譯器選項以及程式碼品質檢查。

  • myproject.library-conventions - 新增發布設定以發布到組織的儲存庫,並檢查 README 中的強制性內容。它套用 java-librarymaven-publish 外掛程式,以及 myproject.java-conventions 外掛程式。

內部函式庫子專案套用 myproject.java-conventions 外掛程式

internal-module/build.gradle.kts
plugins {
    id("myproject.java-conventions")
}

dependencies {
    // internal module dependencies
}
internal-module/build.gradle
plugins {
    id 'myproject.java-conventions'
}

dependencies {
    // internal module dependencies
}

兩個公開函式庫子專案套用 myproject.library-conventions 外掛程式。

library-a/build.gradle.kts
plugins {
    id("myproject.library-conventions")
}

dependencies {
    implementation(project(":internal-module"))
}
library-b/build.gradle.kts
plugins {
    id("myproject.library-conventions")
}

dependencies {
    implementation(project(":internal-module"))
}
library-a/build.gradle
plugins {
    id 'myproject.library-conventions'
}

dependencies {
    implementation project(':internal-module')
}
library-b/build.gradle
plugins {
    id 'myproject.library-conventions'
}

dependencies {
    implementation project(':internal-module')
}

請注意套用慣例外掛程式到子專案實際上宣告其類型。透過套用 myproject.java-conventions 外掛程式,我們表示:這是「Java」專案。透過套用 myproject.library-conventions 外掛程式,我們表示:這是「函式庫」專案。

此範例中建立的所有外掛程式都包含使用 TestKit 驗證其行為的功能測試。

此範例沒有任何專案原始碼,只配置一個假設的專案結構,其中兩個函式庫子專案依賴於共用的內部子專案。

編譯慣例外掛程式

在此範例中,慣例外掛程式實作為 預編譯指令碼外掛程式 - 這是最簡單的入門方式,因為您可以直接使用 Gradle 的其中一種 DSL 來實作建置邏輯,就像外掛程式是常規建置指令碼一樣。

為了偵測預編譯指令碼外掛程式,buildSrc 專案需要在其 build.gradle.kts 檔案中套用 kotlin-dsl 外掛程式

為了偵測預編譯指令碼外掛程式,buildSrc 專案需要在其 build.gradle 檔案中套用 groovy-gradle-plugin 外掛程式

buildSrc/build.gradle.kts
plugins {
    `kotlin-dsl`
}
buildSrc/build.gradle
plugins {
    id 'groovy-gradle-plugin'
}

注意事項

在預編譯腳本外掛中套用外部外掛

myproject.java-conventions 外掛使用 SpotBugs 外掛執行靜態程式碼分析。

SpotBugs 是外部外掛,外部外掛 需要新增為實作相依性,才能在預編譯腳本外掛中套用。

buildSrc/build.gradle.kts
repositories {
    gradlePluginPortal() // so that external plugins can be resolved in dependencies section
}

dependencies {
    implementation("com.github.spotbugs.snom:spotbugs-gradle-plugin:5.2.1")
    testImplementation("junit:junit:4.13")
}
buildSrc/build.gradle
repositories {
    gradlePluginPortal() // so that external plugins can be resolved in dependencies section
}

dependencies {
    implementation 'com.github.spotbugs.snom:spotbugs-gradle-plugin:5.2.1'
    testImplementation platform("org.spockframework:spock-bom:2.2-groovy-3.0")
    testImplementation 'org.spockframework:spock-core'
}

tasks.named('test', Test) {
    useJUnitPlatform()
}
  • 外掛的相依性工件座標 (GAV) 可能與外掛 ID 不同。

  • Gradle 外掛入口網站 (gradlePluginPortal()) 新增為外掛相依性的儲存庫。

  • 外掛版本由相依性版本決定。

新增相依性後,即可透過 ID 在預編譯腳本外掛中套用外部外掛。

buildSrc/src/main/kotlin/myproject.java-conventions.gradle.kts
plugins {
    java
    checkstyle

    // NOTE: external plugin version is specified in implementation dependency artifact of the project's build file
    id("com.github.spotbugs")
}
buildSrc/src/main/groovy/myproject.java-conventions.gradle
plugins {
    id 'java'
    id 'checkstyle'

    // NOTE: external plugin version is specified in implementation dependency artifact of the project's build file
    id 'com.github.spotbugs'
}

套用其他預編譯腳本外掛

預編譯腳本外掛可以套用其他預編譯腳本外掛。

myproject.library-conventions 外掛套用 myproject.java-conventions 外掛。

buildSrc/src/main/kotlin/myproject.library-conventions.gradle.kts
plugins {
    `java-library`
    `maven-publish`
    id("myproject.java-conventions")
}
buildSrc/src/main/groovy/myproject.library-conventions.gradle
plugins {
    id 'java-library'
    id 'maven-publish'
    id 'myproject.java-conventions'
}

使用主來源集中的類別

預編譯腳本外掛可以使用外掛專案主來源集中定義的類別。

在此範例中,myproject.library-conventions 外掛使用 buildSrc/src/main/java 中的客製化工作類別來設定函式庫 README 檢查。

buildSrc/src/main/kotlin/myproject.library-conventions.gradle.kts
val readmeCheck by tasks.registering(com.example.ReadmeVerificationTask::class) {
    readme = layout.projectDirectory.file("README.md")
    readmePatterns = listOf("^## API$", "^## Changelog$")
}
buildSrc/src/main/groovy/myproject.library-conventions.gradle
def readmeCheck = tasks.register('readmeCheck', com.example.ReadmeVerificationTask) {
    // Expect the README in the project directory
    readme = layout.projectDirectory.file("README.md")
    // README must contain a Service API header
    readmePatterns = ['^## API$', '^## Changelog$']
}

有關撰寫客製化 Gradle 外掛的詳細資訊,請參閱 使用者手冊