在构建依赖图之后,Gradle 可以在已解析的图上执行构件解析。
Gradle API 可用于影响构件选择的过程 — 将图映射到一组构件。
然后,Gradle 可以将构件选择的结果公开为 ArtifactCollection
。更常见的是,结果以 FileCollection
的形式公开,这是一个扁平的文件列表。
隐式构件选择
默认情况下,用于构件选择的属性与图解析期间用于变体选择的属性相同。 这些属性由 Configuration#getAttributes()
属性指定。
要使用这些默认属性执行构件选择(以及隐式地,图解析),请使用 FileCollection
和 ArtifactCollection
API。
也可以从配置的 ResolvedConfiguration 、LenientConfiguration 、ResolvedArtifact 和 ResolvedDependency API 访问文件。 但是,这些 API 处于维护模式,不建议在新开发中使用。 这些 API 使用默认属性执行构件选择。 |
解析文件
要解析文件,我们首先定义一个接受 ConfigurableFileCollection
作为输入的 task
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)
}
}
}
然后,我们可以将可解析配置的文件连接到 task 的输入。 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,我们可以看到输出是相同的
> 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
解析构件
我们可以消费构件,其中包含文件和元数据,而不是直接从隐式构件选择过程中消费文件。
此过程稍微复杂一些,因为为了保持配置缓存兼容性,我们需要将 ResolvedArtifactResult
的字段拆分为两个 task 输入
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}")
}
}
}
此 task 的初始化方式与文件解析 task 类似
tasks.register<ResolveArtifacts>("resolveIncomingArtifacts") {
from(configurations.runtimeClasspath.flatMap { it.incoming.artifacts.resolvedArtifacts })
}
tasks.register("resolveIncomingArtifacts", ResolveArtifacts) {
from(configurations.runtimeClasspath.incoming.artifacts.resolvedArtifacts)
}
运行此 task,我们可以看到文件元数据包含在输出中
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
允许您提取构件,而无需更改底层依赖解析逻辑或配置状态。
-
在以下示例中,生产者项目创建一个具有以下变体及其属性的库
下一步: 了解构件视图 >>