You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何从Gradle模型中获取所有插件相关的完整依赖?

Gradle插件依赖收集问题

我正在开发一个Gradle插件,用于列出项目构建所用的所有依赖。针对简单的compile和buildscript依赖,实现起来较为容易:

val dependencies = project.allprojects.asSequence().flatMap { project ->
    (project.buildscript.configurations + project.configurations).asSequence()
        .filter { it.isCanBeResolved }
        .flatMap {
            val resolved = it.resolvedConfiguration
            resolved.rethrowFailure()
            resolved.firstLevelModuleDependencies.flatMap { dep -> dep.allModuleArtifacts }
        }
}

(随后可通过it.id.componentIdentifier as ModuleComponentIdentifier获取group、module和version,通过it.type和it.classifier获取对应属性)。

但这种方式会遗漏仅由插件使用的JAR包。例如,当应用Kotlin插件:

plugins {
    kotlin("jvm") version "1.6.10"
}

时,生成的依赖列表并不完整——仅包含org.jetbrains.kotlin:kotlin-gradle-plugin及其部分关联依赖,却未包含所需的org.jetbrains.kotlin.jvm:org.jetbrains.kotlin.jvm.gradle.plugin这一POM依赖。请问能否从Gradle模型中获取这些遗漏的依赖?


可以通过Gradle的插件管理模型获取这些插件标记依赖(即.gradle.plugin类型的POM依赖),具体可从以下方向实现:

1. 直接访问插件解析结果

Gradle在解析plugins块时会维护插件的解析信息,通过gradle.pluginResolutionManager可直接获取已解析的插件标记依赖:

// 遍历所有已解析的插件请求
gradle.pluginResolutionManager.resolvedPlugins.forEach { resolvedPlugin ->
    val moduleVersion = resolvedPlugin.moduleVersion
    // 输出格式:org.jetbrains.kotlin.jvm:org.jetbrains.kotlin.jvm.gradle.plugin:1.6.10
    println("Plugin marker dependency: ${moduleVersion.group}:${moduleVersion.name}:${moduleVersion.version}")
}

2. 从buildscript classpath补充依赖树

plugins块最终会将插件实现依赖注入到buildscript.classpath,但插件标记依赖本身不会直接加入classpath,可通过解析classpath的依赖树筛选出这类标记:

// 解析buildscript classpath的依赖树
project.buildscript.configurations.classpath.resolvedConfiguration.firstLevelModuleDependencies.forEach { dep ->
    checkAndAddPluginMarker(dep)
}

// 递归检查子依赖
fun checkAndAddPluginMarker(dep: ResolvedDependency) {
    if (dep.moduleName.endsWith(".gradle.plugin")) {
        println("Plugin marker: ${dep.group}:${dep.moduleName}:${dep.moduleVersion}")
    }
    dep.children.forEach { checkAndAddPluginMarker(it) }
}

3. 整合到现有依赖收集逻辑

将上述两种方式与原有代码结合,即可覆盖所有类型的依赖:

val allDependencies = mutableListOf<Any>()

// 原有逻辑收集compile和buildscript依赖
val projectDeps = project.allprojects.asSequence().flatMap { project ->
    (project.buildscript.configurations + project.configurations).asSequence()
        .filter { it.isCanBeResolved }
        .flatMap {
            val resolved = it.resolvedConfiguration
            resolved.rethrowFailure()
            resolved.firstLevelModuleDependencies.flatMap { dep -> dep.allModuleArtifacts }
        }
}
allDependencies.addAll(projectDeps)

// 收集插件标记依赖
val pluginMarkerDeps = gradle.pluginResolutionManager.resolvedPlugins.map { it.moduleVersion }
allDependencies.addAll(pluginMarkerDeps)

// 统一处理依赖信息
allDependencies.forEach { dep ->
    when (dep) {
        is ModuleVersionIdentifier -> {
            println("Plugin marker: ${dep.group}:${dep.name}:${dep.version}")
        }
        is ResolvedArtifact -> {
            val id = dep.id.componentIdentifier as ModuleComponentIdentifier
            println("Artifact: ${id.group}:${id.module}:${id.version} (${dep.type}, ${dep.classifier})")
        }
    }
}

插件标记artifact本质是用于定位插件实现的POM文件,本身不会进入构建classpath,但如果你的需求是收集构建全流程涉及的所有依赖,这种方式就能覆盖到这类遗漏项。


内容的提问来源于stack exchange,提问作者user8681

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.23 06:48:19