在某些情況下,客製化 Artifact 解析流程是必要的。ArtifactView
API 是在 Gradle 中影響 Artifact 選擇的主要機制。
ArtifactView
在已解析的圖形之上運作,但允許您套用不同的屬性。它讓您能夠檢索符合一組新標準的 Artifact,即使它們不是原始圖形解析的一部分。
ArtifactView
可以
-
選擇替代變體,例如 sources 或 javadoc,用於整個解析:通常,Artifact 必須同時符合圖形的屬性和
ArtifactView
的屬性。透過withVariantReselection
,您可以從組件內任何可用的變體中選擇 Artifact。 -
執行寬鬆的 Artifact 選擇 和解析:使用
ArtifactView
並設定lenient=true
允許您忽略遺失的相依性和其他錯誤。 -
過濾選取的 Artifact:使用
ArtifactView
和componentFilter
讓您可以從選取的 Artifact 中排除特定的組件。 -
觸發轉換:觸發
ArtifactTransform
以將 Artifact 從一種類型變更為另一種類型。
ArtifactView 可以產生 FileCollection 和 ArtifactCollection 兩種形式的結果。以下範例僅示範使用 FileCollection 作為輸出。 |
1. 執行變體重新選擇
標準 Artifact 選擇只能在圖形選擇結果所選組件的變體之間進行選擇。但是,在某些情況下,可能需要從與所選圖形節點平行的變體中選擇 Artifact。
請考慮以下範例組件結構,描述一個典型的本地 Java 函式庫,其中包含 sources 和 javadoc
variant 'apiElements'
artifact set 'jar'
artifact set 'classes'
artifact set 'resources'
variant 'runtimeElements'
artifact set 'jar'
artifact set 'classes'
artifact set 'resources'
variant 'javadocElements'
artifact set 'jar'
variant 'sourcesElements'
artifact set 'jar'
解析 Java 運行時類別路徑將從上述範例組件中選擇 runtimeElements
變體。在標準 Artifact 選擇期間,Gradle 將僅從 runtimeElements
下的 Artifact 集合中選擇。
然而,通常會希望為圖形中的每個節點選擇所有 sources 或所有 javadoc。請考慮以下範例,該範例為給定的運行時類別路徑選擇所有 sources
此範例使用孵化中的 API。 |
tasks.register<ResolveFiles>("resolveSources") {
files.from(configurations.runtimeClasspath.map {
it.incoming.artifactView {
withVariantReselection()
attributes {
attribute(Usage.USAGE_ATTRIBUTE, objects.named(Usage.JAVA_RUNTIME));
attribute(Category.CATEGORY_ATTRIBUTE, objects.named(Category.DOCUMENTATION));
attribute(Bundling.BUNDLING_ATTRIBUTE, objects.named(Bundling.EXTERNAL));
attribute(DocsType.DOCS_TYPE_ATTRIBUTE, objects.named(DocsType.SOURCES));
}
}.files
})
}
tasks.register("resolveSources", ResolveFiles) {
files.from(configurations.runtimeClasspath.incoming.artifactView {
withVariantReselection()
attributes {
attribute(Usage.USAGE_ATTRIBUTE, objects.named(Usage, Usage.JAVA_RUNTIME));
attribute(Category.CATEGORY_ATTRIBUTE, objects.named(Category, Category.DOCUMENTATION));
attribute(Bundling.BUNDLING_ATTRIBUTE, objects.named(Bundling, Bundling.EXTERNAL));
attribute(DocsType.DOCS_TYPE_ATTRIBUTE, objects.named(DocsType, DocsType.SOURCES));
}
}.files)
}
使用 ArtifactView.withVariantReselection()
API,Gradle 將選擇性地在對新選取的變體執行 Artifact 選擇之前,再次執行圖形變體選擇。當 Gradle 為 runtimeElements
節點選擇 Artifact 時,它將使用 ArtifactView
上指定的屬性重新選擇圖形變體,因此選擇 sourcesElements
變體。然後,將在 sourcesElements
變體上執行傳統 Artifact 選擇,以選擇 jar
Artifact 集合。
因此,每個節點都會解析 sources jar
junit-platform-commons-1.11.0-sources.jar junit-jupiter-api-5.11.0-sources.jar opentest4j-1.3.0-sources.jar
當使用此 API 時,用於變體重新選擇的屬性僅由 ArtifactView.getAttributes()
方法指定。在變體重新選擇期間,組態上指定的圖形解析屬性將完全被忽略。
2. 執行寬鬆的 Artifact 選擇和解析
ArtifactView
API 也可用於執行寬鬆的 Artifact 解析。這允許在包含失敗的圖形上執行 Artifact 解析 — 例如,當找不到請求的模組、請求的模組版本不存在或衝突未解決時。此外,當圖形已成功解析,但無法下載相應的 Artifact 時,可以使用寬鬆的 Artifact 解析來解析 Artifact。
請考慮以下範例,其中某些相依性可能不存在
dependencies {
implementation("does:not:exist")
implementation("org.junit.jupiter:junit-jupiter-api:5.11.0")
}
dependencies {
implementation("does:not:exist")
implementation("org.junit.jupiter:junit-jupiter-api:5.11.0")
}
寬鬆解析是透過使用 ArtifactView.lenient()
方法執行的
tasks.register<ResolveFiles>("resolveLenient") {
files.from(configurations.runtimeClasspath.map {
it.incoming.artifactView {
isLenient = true
}.files
})
}
tasks.register("resolveLenient", ResolveFiles) {
files.from(configurations.runtimeClasspath.incoming.artifactView {
lenient = true
}.files)
}
我們可以看到任務成功執行,並省略了失敗的 Artifact
> Task :resolveLenient junit-platform-commons-1.11.0.jar junit-jupiter-api-5.11.0.jar opentest4j-1.3.0.jar BUILD SUCCESSFUL in 0s
3. 過濾選取的 Artifact
ArtifactView
API 可用於從產生的 FileCollection
或 ArtifactCollection
中過濾特定的 Artifact。
ArtifactViews
允許以每個組件為基礎過濾結果。使用 ArtifactView.componentFilter(Action)
方法,可以從已解析的結果中過濾選定變體的 Artifact。該操作會傳遞組件的 ComponentIdentifier
,該組件擁有正在為其選擇 Artifact 的變體。
請考慮以下範例,其中我們有一個專案相依性和一個外部相依性
dependencies {
implementation(project(":other"))
implementation("org.junit.jupiter:junit-jupiter-api:5.11.0")
}
dependencies {
implementation(project(":other"))
implementation("org.junit.jupiter:junit-jupiter-api:5.11.0")
}
使用 componentFilter
方法,我們可以指定僅選擇特定類型 Artifact 的過濾器
tasks.register<ResolveFiles>("resolveProjects") {
files.from(configurations.runtimeClasspath.map {
it.incoming.artifactView {
componentFilter {
it is ProjectComponentIdentifier
}
}.files
})
}
tasks.register<ResolveFiles>("resolveModules") {
files.from(configurations.runtimeClasspath.map {
it.incoming.artifactView {
componentFilter {
it is ModuleComponentIdentifier
}
}.files
})
}
tasks.register("resolveProjects", ResolveFiles) {
files.from(configurations.runtimeClasspath.incoming.artifactView {
componentFilter {
it instanceof ProjectComponentIdentifier
}
}.files)
}
tasks.register("resolveModules", ResolveFiles) {
files.from(configurations.runtimeClasspath.incoming.artifactView {
componentFilter {
it instanceof ModuleComponentIdentifier
}
}.files)
}
請注意我們如何分別解析專案相依性和模組相依性
> Task :resolveProjects other.jar > Task :resolveModules junit-platform-commons-1.11.0.jar junit-jupiter-api-5.11.0.jar opentest4j-1.3.0.jar
4. 觸發 Artifact 轉換
ArtifactView
可以用來使用與用於解析圖形的屬性不同的屬性來觸發 Artifact 選擇。
對於圖形中的每個節點,都會為該節點執行 Artifact 選擇。最常見的是,此 API 用於請求在選取的 Artifact 上不存在的屬性。當 Gradle 無法從相關節點找到一組相符的 Artifact 時,它將嘗試透過使用專案上註冊的 Artifact 轉換來轉換可用的 Artifact,以滿足請求。
以下,我們使用 Artifact 轉換 章節中的 unzip 範例,示範如何使用 ArtifactView
API 來請求觸發轉換的屬性
tasks.register<ResolveFiles>("resolveTransformedFiles") {
files.from(configurations.runtimeClasspath.map {
it.incoming.artifactView {
attributes {
attribute(LibraryElements.LIBRARY_ELEMENTS_ATTRIBUTE, objects.named(LibraryElements.CLASSES_AND_RESOURCES))
attribute(ArtifactTypeDefinition.ARTIFACT_TYPE_ATTRIBUTE, ArtifactTypeDefinition.DIRECTORY_TYPE)
}
}.files
})
}
tasks.register("resolveTransformedFiles", ResolveFiles) {
files.from(configurations.runtimeClasspath.incoming.artifactView {
attributes {
attribute(LibraryElements.LIBRARY_ELEMENTS_ATTRIBUTE, objects.named(LibraryElements, LibraryElements.CLASSES_AND_RESOURCES))
attribute(ArtifactTypeDefinition.ARTIFACT_TYPE_ATTRIBUTE, ArtifactTypeDefinition.DIRECTORY_TYPE)
}
}.files)
}
Gradle 使用在組態上指定的圖形解析屬性,以及在 ArtifactView
的 attributes
區塊中指定的屬性串聯,來執行 Artifact 選擇。
任務輸出顯示 Artifact 已轉換
junit-platform-commons-1.11.0.jar-unzipped junit-jupiter-api-5.11.0.jar-unzipped opentest4j-1.3.0.jar-unzipped
用於解壓縮 JAR 檔案 (從 ZIP
到 UNZIP
) 的轉換程式碼 (ArtifactTransform
) 可以在下一章中看到。
下一步: 了解 Artifact 轉換 >>