在建構相依性圖形之後,Gradle 可以在已解析的圖形上執行構件解析。
Gradle API 可用於影響構件選擇的過程 — 將圖形映射到一組構件。
然後,Gradle 可以將構件選擇的結果公開為 ArtifactCollection
。更常見的是,結果以 FileCollection
的形式公開,這是一個檔案的平面列表。
隱式構件選擇
預設情況下,用於構件選擇的屬性與圖形解析期間用於變體選擇的屬性相同。這些屬性由 Configuration#getAttributes()
屬性指定。
若要使用這些預設屬性執行構件選擇(以及隱式地,圖形解析),請使用 FileCollection
和 ArtifactCollection
API。
也可以從配置的 ResolvedConfiguration 、LenientConfiguration 、ResolvedArtifact 和 ResolvedDependency API 存取檔案。但是,這些 API 處於維護模式,不建議在新開發中使用。這些 API 使用預設屬性執行構件選擇。 |
解析檔案
若要解析檔案,我們先定義一個接受 ConfigurableFileCollection
作為輸入的任務
abstract class ResolveFiles : DefaultTask() {
@get:InputFiles
abstract val files: ConfigurableFileCollection
@TaskAction
fun print() {
files.forEach {
println(it.name)
}
}
}
abstract class ResolveFiles extends DefaultTask {
@InputFiles
abstract ConfigurableFileCollection getFiles()
@TaskAction
void print() {
files.each {
println(it.name)
}
}
}
然後,我們可以將可解析配置的檔案連接到任務的輸入。Configuration
直接實作 FileCollection
,可以直接連接。或者,透過 Configuration#getIncoming()
連接是一種更明確的方法
tasks.register<ResolveFiles>("resolveConfiguration") {
files.from(configurations.runtimeClasspath)
}
tasks.register<ResolveFiles>("resolveIncomingFiles") {
files.from(configurations.runtimeClasspath.map { it.incoming.files })
}
tasks.register("resolveConfiguration", ResolveFiles) {
files.from(configurations.runtimeClasspath)
}
tasks.register("resolveIncomingFiles", ResolveFiles) {
files.from(configurations.runtimeClasspath.incoming.files)
}
執行這兩個任務,我們可以看見輸出是相同的
> Task :resolveConfiguration junit-platform-commons-1.11.0.jar junit-jupiter-api-5.11.0.jar opentest4j-1.3.0.jar > Task :resolveIncomingFiles junit-platform-commons-1.11.0.jar junit-jupiter-api-5.11.0.jar opentest4j-1.3.0.jar
解析構件
與其直接從隱式構件選擇過程中使用檔案,不如使用構件,其中包含檔案和 metadata。
此過程稍微複雜一些,因為為了維持配置快取的相容性,我們需要將 ResolvedArtifactResult
的欄位拆分為兩個任務輸入
data class ArtifactDetails(
val id: ComponentArtifactIdentifier,
val variant: ResolvedVariantResult
)
abstract class ResolveArtifacts : DefaultTask() {
@get:Input
abstract val details: ListProperty<ArtifactDetails>
@get:InputFiles
abstract val files: ListProperty<File>
fun from(artifacts: Provider<Set<ResolvedArtifactResult>>) {
details.set(artifacts.map {
it.map { artifact -> ArtifactDetails(artifact.id, artifact.variant) }
})
files.set(artifacts.map {
it.map { artifact -> artifact.file }
})
}
@TaskAction
fun print() {
assert(details.get().size == files.get().size)
details.get().zip(files.get()).forEach { (details, file) ->
println("${details.variant.displayName}:${file.name}")
}
}
}
class ArtifactDetails {
ComponentArtifactIdentifier id
ResolvedVariantResult variant
ArtifactDetails(ComponentArtifactIdentifier id, ResolvedVariantResult variant) {
this.id = id
this.variant = variant
}
}
abstract class ResolveArtifacts extends DefaultTask {
@Input
abstract ListProperty<ArtifactDetails> getDetails()
@InputFiles
abstract ListProperty<File> getFiles()
void from(Provider<Set<ResolvedArtifactResult>> artifacts) {
details.set(artifacts.map {
it.collect { artifact -> new ArtifactDetails(artifact.id, artifact.variant) }
})
files.set(artifacts.map {
it.collect { artifact -> artifact.file }
})
}
@TaskAction
void print() {
List<ArtifactDetails> allDetails = details.get()
List<File> allFiles = files.get()
assert allDetails.size() == allFiles.size()
for (int i = 0; i < allDetails.size(); i++) {
def details = allDetails.get(i)
def file = allFiles.get(i)
println("${details.variant.displayName}:${file.name}")
}
}
}
此任務的初始化方式與檔案解析任務類似
tasks.register<ResolveArtifacts>("resolveIncomingArtifacts") {
from(configurations.runtimeClasspath.flatMap { it.incoming.artifacts.resolvedArtifacts })
}
tasks.register("resolveIncomingArtifacts", ResolveArtifacts) {
from(configurations.runtimeClasspath.incoming.artifacts.resolvedArtifacts)
}
執行此任務,我們可以看見檔案 metadata 包含在輸出中
org.junit.platform:junit-platform-commons:1.11.0 variant runtimeElements:junit-platform-commons-1.11.0.jar org.junit.jupiter:junit-jupiter-api:5.11.0 variant runtimeElements:junit-jupiter-api-5.11.0.jar org.opentest4j:opentest4j:1.3.0 variant runtimeElements:opentest4j-1.3.0.jar
自訂構件選擇
ArtifactView
在已解析的相依性圖形(即 ResolutionResult
)之上運作,但允許您套用不同的屬性。
當您呼叫配置的 getFiles()
時,Gradle 會根據圖形解析期間使用的屬性選擇構件。但是,ArtifactView
更靈活。它允許您使用自訂屬性從圖形解析構件。
ArtifactView
允許您
-
使用不同的屬性查詢構件:
-
假設圖形解析了相依性的
runtime
變體。您可以使用ArtifactView
從其api
變體中提取構件,即使它們最初不是已解析圖形的一部分。
-
-
提取特定類型的構件:
-
您可以透過指定類似
artifactType
的屬性,僅請求.jar
檔案或特定的構件類型(例如,sources、Javadoc)。
-
-
避免副作用:
-
使用
ArtifactView
允許您提取構件,而無需變更底層的相依性解析邏輯或配置狀態。
-
在以下範例中,生產者專案建立一個具有以下變體及其屬性的函式庫
下一步: 了解構件視圖 >>