了解變體選擇
在其他相依性管理引擎中,例如 Apache Maven™,相依性和人工製品會繫結到一個元件,而該元件會在特定 GAV(群組-人工製品-版本)座標中發佈。此元件的相依性集合始終相同,無論從元件中使用哪個人工製品。
如果元件確實有多個人工製品,則每個人工製品都會由一個繁瑣的分類器識別。沒有與分類器相關聯的共用語意,這使得難以保證全球一致的相依性圖。這表示沒有任何機制可以防止單一元件的(例如 jdk7
和 jdk8
分類器)多個人工製品出現在類別路徑中,並造成難以診斷的問題。
Maven 元件模型

Gradle 元件模型

Gradle 的相依性管理引擎是變異感知的。
除了組件之外,Gradle 還有一個組件變異的概念。變異對應於組件可使用的不同方式,例如 Java 編譯、原生連結或文件。人工製品附加到變異,每個變異都可能有一組不同的相依性。
當有多個變異時,Gradle 如何知道要選擇哪個變異?變異的配對是透過使用屬性來完成的,屬性提供語意給變異,並協助引擎產生一致的解析結果。
Gradle 區分兩種組件
-
從來源建置的本機組件(例如專案)
-
發佈到儲存庫的外部組件
對於本機組件,變異會對應到可消耗組態。對於外部組件,變異是由發佈的 Gradle 模組元資料定義,或衍生自 Ivy/Maven 元資料。
由於歷史原因,變異和組態有時在文件、DSL 或 API 中可以互換使用。
所有組件都提供變異,這些變異可能由可消耗組態支援。並非所有組態都是變異,因為它們可能用於宣告或解析相依性。
變異屬性
屬性是消費者(對於可解析組態)和生產者(對於每個變異)定義的類型安全鍵值對。
消費者可以定義任意數量的屬性。每個屬性有助於縮小可選的變異範圍。屬性值不需要完全相符。
變異也可以定義任意數量的屬性。這些屬性應描述變異的預期用途。例如,Gradle 使用一個名為 org.gradle.usage
的屬性來描述消費者如何使用組件(編譯、執行階段執行等)。變異擁有的屬性通常會多於消費者選擇變異時所提供的屬性。
變異屬性配對
變體名稱主要用於除錯目的和錯誤訊息。名稱不會參與變體比對,只有其屬性會參與。
元件可以定義的變體數量沒有限制。通常,元件至少有一個實作變體,但也可以公開測試固定裝置、文件或原始程式碼。元件也可以針對不同的使用者公開不同的變體,以供相同用途。例如,在編譯時,元件可以針對 Linux、Windows 和 macOS 使用不同的標頭。
Gradle 透過比對使用者要求的屬性與生產者定義的屬性,來執行變體感知選取。選取演算法會在其他章節中詳細說明。
此規則有兩個例外,會繞過變體感知解析
|
一個簡單的範例
我們來考慮一個範例,其中使用者嘗試使用某個函式庫進行編譯。
首先,使用者需要說明它將如何使用相依解析的結果。這會透過在使用者的可解析組態上設定屬性來完成。
使用者想要解析與下列內容相符的變體:org.gradle.usage=java-api
其次,生產者需要公開元件的不同變體。
生產者元件公開 2 個變體
-
其 API(命名為
apiElements
),屬性為org.gradle.usage=java-api
-
其執行時間(命名為
runtimeElements
),屬性為org.gradle.usage=java-runtime
最後,Gradle 會透過查看變體屬性來選取適當的變體
-
使用者想要一個屬性為
org.gradle.usage=java-api
的變體 -
生產者有一個相符的變體(
apiElements
) -
生產者有一個不相符的變體(
runtimeElements
)
Gradle 會將 apiElements
變體的人工製品和相依項提供給使用者。
一個更複雜的範例
在真實世界中,使用者和生產者會有多個屬性。
Gradle 中的 Java 函式庫專案將包含幾個不同的屬性
-
org.gradle.usage
描述變體的使用方式 -
org.gradle.dependency.bundling
描述變體如何處理依賴項(shadow jar 與 fat jar 與一般 jar) -
org.gradle.libraryelements
描述變體的封裝(類別或 jar) -
org.gradle.jvm.version
描述此變體所針對的 Java 的最低版本 -
org.gradle.jvm.environment
描述此變體所針對的 JVM 類型
讓我們考慮一個範例,其中使用者想要在 Java 8 上執行測試,而生產者支援兩個不同的 Java 版本(Java 8 和 Java 11)。
首先,使用者需要說明它需要的 Java 版本。
使用者想要解析一個變體,這個變體
-
可以在執行時期使用(具有
org.gradle.usage=java-runtime
) -
可以在至少 Java 8 上執行(
org.gradle.jvm.version=8
)
其次,生產者需要公開元件的不同變體。
就像在簡單的範例中,同時存在 API(編譯)和執行時期變體。這些變體同時存在於元件的 Java 8 和 Java 11 版本中。
-
其針對 Java 8 使用者的 API(稱為
apiJava8Elements
),具有屬性org.gradle.usage=java-api
和org.gradle.jvm.version=8
-
其針對 Java 8 使用者的執行時期(稱為
runtime8Elements
),具有屬性org.gradle.usage=java-runtime
和org.gradle.jvm.version=8
-
其針對 Java 11 使用者的 API(稱為
apiJava11Elements
),具有屬性org.gradle.usage=java-api
和org.gradle.jvm.version=11
-
其針對 Java 11 使用者的執行時期(稱為
runtime11Elements
),具有屬性org.gradle.usage=java-runtime
和org.gradle.jvm.version=11
最後,Gradle 透過檢視所有屬性來選取最佳的相符變體
-
使用者想要一個具有與
org.gradle.usage=java-runtime
和org.gradle.jvm.version=8
相容屬性的變體 -
變體
runtime8Elements
和runtime11Elements
具有 `org.gradle.usage=java-runtime -
變體
apiJava8Elements
和apiJava11Elements
不相容 -
變體
runtime8Elements
相容,因為它可以在 Java 8 上執行 -
變體
runtime11Elements
不相容,因為它無法在 Java 8 上執行
Gradle 提供 runtime8Elements
變體的成品和依賴項給使用者。
如果使用者將 org.gradle.jvm.version
設定為 7 會如何?
依賴項解析會失敗,並顯示錯誤訊息,說明沒有合適的變體。Gradle 會辨識使用者想要相容於 Java 7 的函式庫,而生產者提供的 Java 最低版本是 8。
如果使用者要求 org.gradle.jvm.version=15
,Gradle 會知道 Java 8 或 Java 11 變體都可以使用。Gradle 會選取相容性最高的 Java 版本 (11)。
變體選取錯誤
在選取元件最相容的變體時,解析可能會失敗
-
當生產者有多個變體符合使用者的屬性時 (模稜兩可錯誤)
-
當生產者沒有任何變體符合使用者的屬性時 (不相容錯誤)
處理模稜兩可錯誤
模稜兩可的變體選取看起來像這樣
> Could not resolve all files for configuration ':compileClasspath'. > Could not resolve project :lib. Required by: project :ui > Cannot choose between the following variants of project :lib: - feature1ApiElements - feature2ApiElements All of them match the consumer attributes: - Variant 'feature1ApiElements' capability org.test:test-capability:1.0: - Unmatched attribute: - Found org.gradle.category 'library' but wasn't required. - Compatible attributes: - Provides org.gradle.dependency.bundling 'external' - Provides org.gradle.jvm.version '11' - Required org.gradle.libraryelements 'classes' and found value 'jar'. - Provides org.gradle.usage 'java-api' - Variant 'feature2ApiElements' capability org.test:test-capability:1.0: - Unmatched attribute: - Found org.gradle.category 'library' but wasn't required. - Compatible attributes: - Provides org.gradle.dependency.bundling 'external' - Provides org.gradle.jvm.version '11' - Required org.gradle.libraryelements 'classes' and found value 'jar'. - Provides org.gradle.usage 'java-api'
所有相容的候選變體都會顯示其屬性。
-
不匹配的屬性會先顯示,因為它們可能是選取適當變體時遺漏的部分。
-
相容的屬性會其次顯示,因為它們表示使用者想要什麼,以及這些變體如何符合該要求。
-
不會有任何不相容的屬性,因為變體不會被視為候選變體。
在上面的範例中,修正方法不在於屬性匹配,而在於功能匹配,顯示在變體名稱旁邊。由於這兩個變體實際上提供相同的屬性和功能,因此無法消除模稜兩可。因此,在這種情況下,修正方法很可能是提供生產者端 (project :lib
) 的不同功能,並在使用者端 (project :ui
) 表達功能選擇。
處理沒有匹配變體的錯誤
沒有匹配變體的錯誤看起來像這樣
> No variants of project :lib match the consumer attributes: - Configuration ':lib:compile': - Incompatible attribute: - Required artifactType 'dll' and found incompatible value 'jar'. - Other compatible attribute: - Provides usage 'api' - Configuration ':lib:compile' variant debug: - Incompatible attribute: - Required artifactType 'dll' and found incompatible value 'jar'. - Other compatible attributes: - Found buildType 'debug' but wasn't required. - Provides usage 'api' - Configuration ':lib:compile' variant release: - Incompatible attribute: - Required artifactType 'dll' and found incompatible value 'jar'. - Other compatible attributes: - Found buildType 'release' but wasn't required. - Provides usage 'api'
或像這樣
> No variants of project : match the consumer attributes: - Configuration ':myElements' declares attribute 'color' with value 'blue': - Incompatible because this component declares attribute 'artifactType' with value 'jar' and the consumer needed attribute 'artifactType' with value 'dll' - Configuration ':myElements' variant secondary declares attribute 'color' with value 'blue': - Incompatible because this component declares attribute 'artifactType' with value 'jar' and the consumer needed attribute 'artifactType' with value 'dll'
取決於錯誤發生在變體選取演算法的哪個階段。
所有可能相容的候選變體都會顯示其屬性。
-
不相容的屬性會先顯示,因為它們通常是了解為什麼無法選取變體的關鍵。
-
其他屬性會其次顯示,這包括要求的和相容的屬性,以及使用者未要求的所有額外生產者屬性。
與模稜兩可的變體錯誤類似,目標是了解應該選取哪個變體。在某些情況下,生產者可能沒有任何相容的變體 (例如,嘗試使用為 Java 11 建置的函式庫在 Java 8 上執行)。
處理不相容變體錯誤
不相容變體錯誤看起來像以下範例,使用者想要選取具有 color=green
的變體,但唯一可用的變體具有 color=blue
> Could not resolve all task dependencies for configuration ':resolveMe'. > Could not resolve project :. Required by: project : > Configuration 'mismatch' in project : does not match the consumer attributes Configuration 'mismatch': - Incompatible because this component declares attribute 'color' with value 'blue' and the consumer needed attribute 'color' with value 'green'
當 Gradle 無法選擇相依項的單一變體,因為明確要求的屬性值與相依項的任何變體上該屬性的值不符(且不相容)時,就會發生此情況。
此失敗的子類型發生於 Gradle 成功選擇同一個元件的多個變體,但所選的變體彼此不相容時。
這看起來像下列情況,其中消費者想要選擇元件的兩個不同變體,每個變體提供不同的功能,這是可以接受的。不幸的是,一個變體具有 color=blue
,另一個變體具有 color=green
> Could not resolve all task dependencies for configuration ':resolveMe'. > Could not resolve project :. Required by: project : > Multiple incompatible variants of org.example:nyvu:1.0 were selected: - Variant org.example:nyvu:1.0 variant blueElementsCapability1 has attributes {color=blue} - Variant org.example:nyvu:1.0 variant greenElementsCapability2 has attributes {color=green} > Could not resolve project :. Required by: project : > Multiple incompatible variants of org.example:pi2e5:1.0 were selected: - Variant org.example:pi2e5:1.0 variant blueElementsCapability1 has attributes {color=blue} - Variant org.example:pi2e5:1.0 variant greenElementsCapability2 has attributes {color=green}
處理模稜兩可的轉換錯誤
ArtifactTransforms 可用於將一種類型的成品轉換為另一種類型,變更其屬性。變體選擇可以使用成品轉換結果中可用的屬性作為候選變體。
如果專案註冊多個成品轉換,需要使用成品轉換來產生與消費者要求相符的變體,且多個成品轉換都可以用於達成此目的,那麼 Gradle 會失敗,並產生類似下列的模稜兩可轉換錯誤
> Could not resolve all task dependencies for configuration ':resolveMe'. > Found multiple transforms that can produce a variant of project : with requested attributes: - color 'red' - shape 'round' Found the following transforms: - From 'configuration ':roundBlueLiquidElements'': - With source attributes: - color 'blue' - shape 'round' - state 'liquid' - Candidate transform(s): - Transform 'BrokenTransform' producing attributes: - color 'red' - shape 'round' - state 'gas' - Transform 'BrokenTransform' producing attributes: - color 'red' - shape 'round' - state 'solid'
視覺化變體資訊
傳出變體報告
報告任務 outgoingVariants
顯示專案消費者可選擇的變體清單。它顯示每個變體的功能、屬性和成品。
此任務類似於 dependencyInsight
報告任務。
預設情況下,outgoingVariants
會列印所有變體的資訊。它提供選用參數 --variant <variantName>
來選擇單一變體顯示。它也接受 --all
旗標來納入舊版和已棄用的組態資訊,或 --no-all
來排除此資訊。
以下是 outgoingVariants
任務在新產生的 java-library
專案上的輸出
> Task :outgoingVariants -------------------------------------------------- Variant apiElements -------------------------------------------------- API elements for the 'main' feature. Capabilities - new-java-library:lib:unspecified (default capability) Attributes - org.gradle.category = library - org.gradle.dependency.bundling = external - org.gradle.jvm.version = 11 - org.gradle.libraryelements = jar - org.gradle.usage = java-api Artifacts - build/libs/lib.jar (artifactType = jar) Secondary Variants (*) -------------------------------------------------- Secondary Variant classes -------------------------------------------------- Description = Directories containing compiled class files for main. Attributes - org.gradle.category = library - org.gradle.dependency.bundling = external - org.gradle.jvm.version = 11 - org.gradle.libraryelements = classes - org.gradle.usage = java-api Artifacts - build/classes/java/main (artifactType = java-classes-directory) -------------------------------------------------- Variant mainSourceElements (i) -------------------------------------------------- Description = List of source directories contained in the Main SourceSet. Capabilities - new-java-library:lib:unspecified (default capability) Attributes - org.gradle.category = verification - org.gradle.dependency.bundling = external - org.gradle.verificationtype = main-sources Artifacts - src/main/java (artifactType = directory) - src/main/resources (artifactType = directory) -------------------------------------------------- Variant runtimeElements -------------------------------------------------- Runtime elements for the 'main' feature. Capabilities - new-java-library:lib:unspecified (default capability) Attributes - org.gradle.category = library - org.gradle.dependency.bundling = external - org.gradle.jvm.version = 11 - org.gradle.libraryelements = jar - org.gradle.usage = java-runtime Artifacts - build/libs/lib.jar (artifactType = jar) Secondary Variants (*) -------------------------------------------------- Secondary Variant classes -------------------------------------------------- Description = Directories containing compiled class files for main. Attributes - org.gradle.category = library - org.gradle.dependency.bundling = external - org.gradle.jvm.version = 11 - org.gradle.libraryelements = classes - org.gradle.usage = java-runtime Artifacts - build/classes/java/main (artifactType = java-classes-directory) -------------------------------------------------- Secondary Variant resources -------------------------------------------------- Description = Directories containing the project's assembled resource files for use at runtime. Attributes - org.gradle.category = library - org.gradle.dependency.bundling = external - org.gradle.jvm.version = 11 - org.gradle.libraryelements = resources - org.gradle.usage = java-runtime Artifacts - build/resources/main (artifactType = java-resources-directory) -------------------------------------------------- Variant testResultsElementsForTest (i) -------------------------------------------------- Description = Directory containing binary results of running tests for the test Test Suite's test target. Capabilities - new-java-library:lib:unspecified (default capability) Attributes - org.gradle.category = verification - org.gradle.testsuite.name = test - org.gradle.testsuite.target.name = test - org.gradle.testsuite.type = unit-test - org.gradle.verificationtype = test-results Artifacts - build/test-results/test/binary (artifactType = directory) (i) Configuration uses incubating attributes such as Category.VERIFICATION. (*) Secondary variants are variants created via the Configuration#getOutgoing(): ConfigurationPublications API which also participate in selection, in addition to the configuration itself.
從這裡您可以看到 java 函式庫公開的兩個主要變體,apiElements
和 runtimeElements
。請注意,主要差異在於 org.gradle.usage
屬性,其值為 java-api
和 java-runtime
。正如它們所指示的,這是區分消費者 編譯 類別路徑上需要什麼與 執行時期 類別路徑上需要什麼的地方。
它還顯示了 次要 變體,這些變體專屬於 Gradle 專案,不會發布。例如,apiElements
中的次要變體 classes
允許 Gradle 在針對 java-library
專案 編譯時略過 JAR 建立。
可解析組態報告
Gradle 還提供了一個稱為 resolvableConfigurations
的補充報告任務,它顯示專案的 可解析 組態,這些組態可以新增相依性並加以解析。報告將列出它們的屬性以及它們延伸的任何組態。它還將列出在解析期間將受 相容性規則 或 消除歧義規則 影響的任何屬性摘要。
預設情況下,resolvableConfigurations
會列印有關所有純可解析組態的資訊。這些組態標記為可解析,但不標記為可消耗。儘管某些可解析組態也標記為可消耗,但這些是舊組態,不應該在建置指令碼中新增相依性。此報告提供選用參數 --configuration <configurationName>
來選取要顯示的單一組態。它也接受 --all
旗標來包含有關舊版和已棄用組態的資訊,或 --no-all
來排除此資訊。最後,它接受 --recursive
旗標,在延伸組態區段中列出以遞迴方式而非直接方式延伸的那些組態。或者,可以使用 --no-recursive
來排除此資訊。
以下是 resolvableConfigurations
任務在新產生的 java-library
專案上的輸出
> Task :resolvableConfigurations -------------------------------------------------- Configuration annotationProcessor -------------------------------------------------- Description = Annotation processors and their dependencies for source set 'main'. Attributes - org.gradle.category = library - org.gradle.dependency.bundling = external - org.gradle.jvm.environment = standard-jvm - org.gradle.libraryelements = jar - org.gradle.usage = java-runtime -------------------------------------------------- Configuration compileClasspath -------------------------------------------------- Description = Compile classpath for source set 'main'. Attributes - org.gradle.category = library - org.gradle.dependency.bundling = external - org.gradle.jvm.environment = standard-jvm - org.gradle.jvm.version = 11 - org.gradle.libraryelements = classes - org.gradle.usage = java-api Extended Configurations - compileOnly - implementation -------------------------------------------------- Configuration runtimeClasspath -------------------------------------------------- Description = Runtime classpath of source set 'main'. Attributes - org.gradle.category = library - org.gradle.dependency.bundling = external - org.gradle.jvm.environment = standard-jvm - org.gradle.jvm.version = 11 - org.gradle.libraryelements = jar - org.gradle.usage = java-runtime Extended Configurations - implementation - runtimeOnly -------------------------------------------------- Configuration testAnnotationProcessor -------------------------------------------------- Description = Annotation processors and their dependencies for source set 'test'. Attributes - org.gradle.category = library - org.gradle.dependency.bundling = external - org.gradle.jvm.environment = standard-jvm - org.gradle.libraryelements = jar - org.gradle.usage = java-runtime -------------------------------------------------- Configuration testCompileClasspath -------------------------------------------------- Description = Compile classpath for source set 'test'. Attributes - org.gradle.category = library - org.gradle.dependency.bundling = external - org.gradle.jvm.environment = standard-jvm - org.gradle.jvm.version = 11 - org.gradle.libraryelements = classes - org.gradle.usage = java-api Extended Configurations - testCompileOnly - testImplementation -------------------------------------------------- Configuration testRuntimeClasspath -------------------------------------------------- Description = Runtime classpath of source set 'test'. Attributes - org.gradle.category = library - org.gradle.dependency.bundling = external - org.gradle.jvm.environment = standard-jvm - org.gradle.jvm.version = 11 - org.gradle.libraryelements = jar - org.gradle.usage = java-runtime Extended Configurations - testImplementation - testRuntimeOnly -------------------------------------------------- Compatibility Rules -------------------------------------------------- Description = The following Attributes have compatibility rules defined. - org.gradle.dependency.bundling - org.gradle.jvm.environment - org.gradle.jvm.version - org.gradle.libraryelements - org.gradle.plugin.api-version - org.gradle.usage -------------------------------------------------- Disambiguation Rules -------------------------------------------------- Description = The following Attributes have disambiguation rules defined. - org.gradle.category - org.gradle.dependency.bundling - org.gradle.jvm.environment - org.gradle.jvm.version - org.gradle.libraryelements - org.gradle.plugin.api-version - org.gradle.usage
從這裡您可以看到用於解析相依性的兩個主要組態,compileClasspath
和 runtimeClasspath
,以及它們對應的測試組態。
從 Maven/Ivy 對應到 Gradle 變體
Maven 和 Ivy 皆沒有變體的概念,這僅由 Gradle 模組元資料原生支援。Gradle 仍可透過使用不同的變體衍生策略,與 Maven 和 Ivy 搭配使用。
Gradle 模組元資料是針對在 Maven、Ivy 和其他類型儲存庫上發佈的模組的元資料格式。它類似於 pom.xml
或 ivy.xml
元資料檔案,但此格式包含變體的詳細資料。
請參閱 Gradle 模組元資料規格 以取得更多資訊。
將 Maven POM 元資料對應到變體
在 Maven 儲存庫上發佈的模組會自動轉換成支援變體的模組。
Gradle 無法得知發佈的是哪種類型的元件
-
代表 Gradle 平台的 BOM
-
用作超級 POM 的 BOM
-
同時是平台和函式庫的 POM
Gradle 中 Java 專案所使用的預設策略是衍生 8 個不同的變體
-
兩個「函式庫」變體(屬性
org.gradle.category
=library
)-
compile
變體對應<scope>compile</scope>
相依性。此變體等同於 Java 函式庫外掛程式 的apiElements
變體。此範圍的所有相依性都被視為API 相依性。 -
runtime
變體對應<scope>compile</scope>
和<scope>runtime</scope>
相依性。此變體等同於 Java 函式庫外掛程式 的runtimeElements
變體。這些範圍的所有相依性都被視為執行時期相依性。-
在兩種情況下,
<dependencyManagement>
相依性不會轉換為約束
-
-
-
代表元件的來源 jar 的「來源」變體
-
代表元件的 javadoc jar 的「javadoc」變體
-
從
<dependencyManagement>
區塊衍生的四個「平台」變體(屬性org.gradle.category
=platform
)-
platform-compile
變體將<scope>compile</scope>
相依性管理相依性對應為相依性約束。 -
platform-runtime
變體將<scope>compile</scope>
和<scope>runtime</scope>
相依性管理相依性對應為相依性約束。 -
enforced-platform-compile
類似於platform-compile
,但所有約束都是強制的 -
enforced-platform-runtime
類似於platform-runtime
,但所有約束都是強制的
-
您可以透過查看手冊的導入 BOM區段,進一步了解平台和強制平台變異的使用方式。預設情況下,每當您宣告對 Maven 模組的依賴時,Gradle 都會尋找library
變異。然而,透過使用platform
或enforcedPlatform
關鍵字,Gradle 現在會尋找其中一個「平台」變異,這讓您可以導入 POM 檔案的約束,而不是依賴項。
Ivy 檔案對變異的對應
Gradle 沒有針對 Ivy 檔案實作內建的衍生策略。Ivy 是一種彈性的格式,讓您可以發佈任意檔案,而且可以高度自訂。
如果您想針對 Ivy 的編譯和執行時期變異實作衍生策略,您可以使用元件資料規則來執行。元件資料規則 API 讓您可以存取 Ivy 設定檔,並根據它們建立變異。如果您知道您使用的所有 Ivy 模組都是使用 Gradle 發佈的,而且沒有進一步自訂ivy.xml
檔案,您可以將下列規則新增到您的建置中
abstract class IvyVariantDerivationRule @Inject internal constructor(objectFactory: ObjectFactory) : ComponentMetadataRule {
private val jarLibraryElements: LibraryElements
private val libraryCategory: Category
private val javaRuntimeUsage: Usage
private val javaApiUsage: Usage
init {
jarLibraryElements = objectFactory.named(LibraryElements.JAR)
libraryCategory = objectFactory.named(Category.LIBRARY)
javaRuntimeUsage = objectFactory.named(Usage.JAVA_RUNTIME)
javaApiUsage = objectFactory.named(Usage.JAVA_API)
}
override fun execute(context: ComponentMetadataContext) {
// This filters out any non Ivy module
if(context.getDescriptor(IvyModuleDescriptor::class) == null) {
return
}
context.details.addVariant("runtimeElements", "default") {
attributes {
attribute(LibraryElements.LIBRARY_ELEMENTS_ATTRIBUTE, jarLibraryElements)
attribute(Category.CATEGORY_ATTRIBUTE, libraryCategory)
attribute(Usage.USAGE_ATTRIBUTE, javaRuntimeUsage)
}
}
context.details.addVariant("apiElements", "compile") {
attributes {
attribute(LibraryElements.LIBRARY_ELEMENTS_ATTRIBUTE, jarLibraryElements)
attribute(Category.CATEGORY_ATTRIBUTE, libraryCategory)
attribute(Usage.USAGE_ATTRIBUTE, javaApiUsage)
}
}
}
}
dependencies {
components { all<IvyVariantDerivationRule>() }
}
abstract class IvyVariantDerivationRule implements ComponentMetadataRule {
final LibraryElements jarLibraryElements
final Category libraryCategory
final Usage javaRuntimeUsage
final Usage javaApiUsage
@Inject
IvyVariantDerivationRule(ObjectFactory objectFactory) {
jarLibraryElements = objectFactory.named(LibraryElements, LibraryElements.JAR)
libraryCategory = objectFactory.named(Category, Category.LIBRARY)
javaRuntimeUsage = objectFactory.named(Usage, Usage.JAVA_RUNTIME)
javaApiUsage = objectFactory.named(Usage, Usage.JAVA_API)
}
void execute(ComponentMetadataContext context) {
// This filters out any non Ivy module
if(context.getDescriptor(IvyModuleDescriptor) == null) {
return
}
context.details.addVariant("runtimeElements", "default") {
attributes {
attribute(LibraryElements.LIBRARY_ELEMENTS_ATTRIBUTE, jarLibraryElements)
attribute(Category.CATEGORY_ATTRIBUTE, libraryCategory)
attribute(Usage.USAGE_ATTRIBUTE, javaRuntimeUsage)
}
}
context.details.addVariant("apiElements", "compile") {
attributes {
attribute(LibraryElements.LIBRARY_ELEMENTS_ATTRIBUTE, jarLibraryElements)
attribute(Category.CATEGORY_ATTRIBUTE, libraryCategory)
attribute(Usage.USAGE_ATTRIBUTE, javaApiUsage)
}
}
}
}
dependencies {
components { all(IvyVariantDerivationRule) }
}
此規則會根據每個 ivy 模組的compile
設定檔建立一個apiElements
變異,並根據default
設定檔建立一個runtimeElements
變異。對於每個變異,它會設定對應的Java 生態系統屬性。變異的依賴項和人工製品會從基礎設定檔中取得。如果並非所有使用的 Ivy 模組都遵循此模式,則可以調整規則或只將其套用至選定的模組組。
對於所有沒有變異的 Ivy 模組,Gradle 有備用選擇方法。Gradle 不會執行變異感知解析,而是選擇default
設定檔或明確命名的設定檔。