變異感知比對 一節所述,屬性為變異賦予語意,且由 Gradle 的相依性管理引擎用於選取最佳比對變異。

對 Gradle 使用者而言,屬性通常隱藏在實作細節中。但了解 Gradle 及其核心外掛程式所定義的標準屬性可能會有幫助。

對外掛程式作者而言,這些屬性及其定義方式可作為在生態系統外掛程式中 建置您自己的屬性集 的基礎。

Gradle 定義的標準屬性

Gradle 定義了一系列由 Gradle 的核心外掛程式使用的標準屬性。

與生態系統無關的標準屬性

表 1. 與生態系統無關的標準變異屬性
屬性名稱 說明 相容性和消除歧義規則

org.gradle.usage

表示變異的主要目的

Usage 值建構自 Usage 中定義的常數

遵循生態系統語意(例如,java-runtime 可用於取代 java-api,但反之則不行)

org.gradle.category

表示此軟體元件的類別

Category 值建構自 Category 中定義的常數

遵循生態系統語意(例如,library 是 JVM 上的預設值,否則不相容)

org.gradle.libraryelements

表示 org.gradle.category=library 變異的內容

LibraryElements 值建構自 LibraryElements 中定義的常數

遵循生態系統語意(例如,在 JVM 世界中,jar 是預設值,且與 classes 相容)

org.gradle.docstype

表示 org.gradle.category=documentation 變異的內容

DocsType 值建構自 DocsType 中定義的常數

沒有預設值,不相容

org.gradle.dependency.bundling

表示如何存取變異的相依性。

Bundling 值建構自 Bundling 中定義的常數

遵循生態系統語意(例如,在 JVM 世界中,embeddedexternal 相容)

org.gradle.verificationtype

表示產生此輸出的驗證任務類型。

VerificationType 值建構自 VerificationType 中定義的常數

沒有預設值,不相容

當變異上存在 Category 屬性,且具有孵化值 org.gradle.category=verification 時,該變異會被視為僅限驗證時間的變異。

這些變異僅包含執行驗證任務的結果,例如測試結果或程式碼覆蓋率報告。它們不可發布,且如果新增到已發布的元件中,將會產生錯誤。

表 2. 與生態系統無關的標準元件屬性
屬性名稱 說明 相容性和消除歧義規則

org.gradle.status

組件層級屬性,衍生

基於狀態配置,預設狀態配置基於原始存放庫。

基於正在使用的配置

JVM 生態系統特定屬性

除了上述定義的生態系統獨立屬性之外,JVM 生態系統還新增下列屬性

表 3. JVM 生態系統標準組件屬性
屬性名稱 說明 相容性和消除歧義規則

org.gradle.jvm.version

指出 JVM 版本相容性。

整數,對於 Java 1.4 及之前版本,使用 1. 之後的版本,對於 Java 5 及之後版本,使用主要版本。

預設值為 Gradle 使用的 JVM 版本,較低版本與較高版本相容,優先使用相容性最高的版本。

org.gradle.jvm.environment

指出變異已針對特定 JVM 環境最佳化。

常見值為 standard-jvmandroid。允許使用其他值。

如果有多個變異可用,屬性用於優先選擇其中一個變異,但一般而言,所有值都相容。預設值為 standard-jvm

org.gradle.testsuite.name

指出產生此輸出的TestSuite名稱。

值為套件名稱。

沒有預設值,不相容

org.gradle.testsuite.target.name

指出產生此輸出的TestSuiteTarget名稱。

值為目標名稱。

沒有預設值,不相容

org.gradle.testsuite.type

指出測試套件類型(單元測試、整合測試、效能測試等)。

TestSuiteType 值建置自TestSuiteType中定義的常數,或自訂值,供使用者定義的測試套件類型使用。

沒有預設值,不相容

JVM 生態系統還包含許多相容性和消歧義規則,適用於不同的屬性。有興趣的讀者可以查看 org.gradle.api.internal.artifacts.JavaEcosystemSupport 的程式碼。

原生生態系統特定屬性

除了上述定義的生態系統獨立屬性之外,原生生態系統還新增下列屬性

表 4. 原生生態系統標準組件屬性
屬性名稱 說明 相容性和消除歧義規則

org.gradle.native.debuggable

指出二進位檔是否已使用偵錯符號建置

布林值

不適用

org.gradle.native.optimized

指出二進位檔是否已使用最佳化旗標建置

布林值

不適用

org.gradle.native.architecture

指出二進位檔的目標架構

MachineArchitecture 值建置自MachineArchitecture中定義的常數

org.gradle.native.operatingSystem

指示二進制檔案的目標作業系統

OperatingSystemFamily 中定義的常數建置的 OperatingSystemFamily

Gradle 外掛生態系統特定屬性

對於 Gradle 外掛開發,自 Gradle 7.0 起支援下列屬性。Gradle 外掛變體可透過此屬性指定與 Gradle API 版本的相容性。

表 5. Gradle 外掛生態系統標準元件屬性
屬性名稱 說明 相容性和消除歧義規則

org.gradle.plugin.api‑version

指示 Gradle API 版本相容性。

有效的 Gradle 版本字串。

預設為目前執行的 Gradle,較低版本相容於較高版本,偏好最高相容版本。

宣告自訂屬性

如果您正在擴充 Gradle,例如為另一個生態系統撰寫外掛,宣告自訂屬性可能是個選項,如果您想要在您的外掛中支援變體感知相依性管理功能。然而,如果您也嘗試發佈程式庫,您應該小心謹慎。新屬性的語意通常透過外掛定義,外掛可以載入 相容性消歧義 規則。因此,建置使用為特定生態系統發佈的程式庫,也需要套用對應的外掛才能正確詮釋屬性。如果您的外掛預計有更多受眾,亦即如果它公開可用且程式庫發佈到公開儲存庫,定義新屬性實際上會擴充 Gradle 模組元資料的語意,並伴隨著責任。例如,不應移除已發佈屬性的支援,或應在外掛的未來版本中以某種相容性層級處理。

在建置指令碼或外掛中建立屬性

屬性是 型別化的。屬性可透過 Attribute<T>.of 方法建立

範例 1. 定義屬性
build.gradle.kts
// An attribute of type `String`
val myAttribute = Attribute.of("my.attribute.name", String::class.java)
// An attribute of type `Usage`
val myUsage = Attribute.of("my.usage.attribute", Usage::class.java)
build.gradle
// An attribute of type `String`
def myAttribute = Attribute.of("my.attribute.name", String)
// An attribute of type `Usage`
def myUsage = Attribute.of("my.usage.attribute", Usage)

屬性類型支援大多數 Java 基本類別;例如 StringInteger;或任何延伸 org.gradle.api.Named 的類別。屬性必須在 dependencies 處理常式上找到的屬性架構中宣告

build.gradle.kts
dependencies.attributesSchema {
    // registers this attribute to the attributes schema
    attribute(myAttribute)
    attribute(myUsage)
}
build.gradle
dependencies.attributesSchema {
    // registers this attribute to the attributes schema
    attribute(myAttribute)
    attribute(myUsage)
}

然後可以設定組態以設定屬性的值

build.gradle.kts
configurations {
    create("myConfiguration") {
        attributes {
            attribute(myAttribute, "my-value")
        }
    }
}
build.gradle
configurations {
    myConfiguration {
        attributes {
            attribute(myAttribute, 'my-value')
        }
    }
}

對於類型延伸 Named 的屬性,屬性的值必須透過物件工廠建立

範例 4. 命名屬性
build.gradle.kts
configurations {
    "myConfiguration" {
        attributes {
            attribute(myUsage, project.objects.named(Usage::class.java, "my-value"))
        }
    }
}
build.gradle
configurations {
    myConfiguration {
        attributes {
            attribute(myUsage, project.objects.named(Usage, 'my-value'))
        }
    }
}

屬性比對

屬性相容性規則

屬性讓引擎選擇相容變異。在某些情況下,生產者可能沒有完全符合消費者要求的變異,但有可用的變異。

例如,如果消費者要求函式庫的 API,而生產者沒有完全符合的變異,則執行時期變異可以被視為相容。這通常發生在發布到外部儲存庫的函式庫。在這種情況下,我們知道即使沒有完全符合(API),我們仍然可以針對執行時期變異進行編譯(它包含多於我們編譯所需,但仍然可以使用)。

Gradle 提供 屬性相容性規則,可以針對每個屬性定義。相容性規則的角色是說明哪些屬性值相容,根據消費者要求的內容。

屬性相容性規則必須透過 屬性比對策略 註冊,您可以從 屬性架構 取得。

屬性消除歧義規則

由於屬性的多個值可以相容,Gradle 需要在所有相容候選者之間選擇「最佳」候選者。這稱為「消除歧義」。

這是透過實作 屬性消除歧義規則 來完成。

屬性消歧義規則必須透過 屬性比對策略 進行註冊,您可以從 屬性架構 取得此策略,而屬性架構是 DependencyHandler 的成員。

變異屬性比對演算法

當一個元件有許多不同的變異,而且有許多不同的屬性時,尋找最佳變異可能會變得複雜。Gradle 的相依性解析引擎在尋找最佳結果(或失敗)時,會執行下列演算法

  1. 每個候選項的屬性值都會與使用者要求的屬性值進行比對。如果候選項的值與使用者的值完全相符、通過屬性的相容性規則,或未提供值,則該候選項會被視為相容。

  2. 如果只有一個候選項被視為相容,則該候選項獲勝。

  3. 如果有多個候選項相容,但其中一個候選項與其他候選項相符的所有屬性都相同,則 Gradle 會選擇該候選項。這是具有「最長」相符項的候選項。

  4. 如果有多個候選項相容,而且相容的屬性數量相等,則 Gradle 需要對候選項進行消歧義。

    1. 對於每個要求的屬性,如果候選項沒有與消歧義規則相符的值,則會將其從考量中排除。

    2. 如果屬性具有已知的優先順序,則 Gradle 會在只有一個候選項剩餘時停止。

    3. 如果屬性沒有已知的優先順序,則 Gradle 必須考量所有屬性。

  5. 如果仍有多個候選項剩餘,則 Gradle 會開始考量「額外」屬性,以在多個候選項之間進行消歧義。額外屬性是指使用者未要求,但至少存在於一個候選項上的屬性。這些額外屬性會按照優先順序進行考量。

    1. 如果屬性具有已知的優先順序,則 Gradle 會在只有一個候選項剩餘時停止。

    2. 在考量完所有具有優先順序的額外屬性後,如果剩餘的候選項與所有非順序消歧義規則相容,則可以選擇這些候選項。

  6. 如果仍有多個候選項剩餘,則 Gradle 會再次考量額外屬性。如果候選項的額外屬性數量最少,則可以選擇該候選項。

如果在任何步驟中都沒有候選項保持相容,則解析會失敗。此外,Gradle 會輸出從步驟 1 開始的所有相容候選項清單,以協助除錯變異比對失敗。

外掛程式和生態系統可透過實作相容性規則、消除歧義規則,並告知 Gradle 屬性的優先順序,來影響選取演算法。優先順序較高的屬性用於依序消除相容的配對。

例如,在 Java 生態系統中,org.gradle.usage 屬性比 org.gradle.libraryelements 具有更高的優先順序。這表示如果兩個候選項目具有 org.gradle.usageorg.gradle.libraryelements 相容的值,Gradle 將選取通過 org.gradle.usage 消除歧義規則的候選項目。