首页 > 解决方案 > 将传递依赖转换为 compileOnly 依赖

问题描述

我正在尝试使用 OSGI 来允许我使用两个不同版本的传递依赖项。计划是一个版本(较新的版本)将隐藏在 OSGI 包中,另一个将像往常一样位于运行时类路径中。

我已经使用 Gradle(使用 Groovy DSL)构建了 bundle jar,但问题是其相关的运行时依赖项是错误的 - 它带来了较新的版本,该版本应该隐藏在 bundle 中。当我这样做时,这仍然是正确的,在build.gradle文件中:

compileOnly deps.diffx
runtimeOnly(deps.diffx) {
    exclude group: 'com.propensive', module: 'magnolia_' + versions.scala_v
}

如果我使用 Gradledependencies任务检查依赖关系,它显示 magnolia 已从runtimeOnly配置中排除,正如预期的那样 - 但未配置中排除runtimeClasspath

如果我随后./gradlew dependencyInsight --dependency magnolia_2.12 --configuration runtime尝试找出此依赖项的来源,它会告诉我较新的版本来自runtimeClasspath取决于diffx,并且这是通过冲突解决选择的。好吧,谢谢-我已经知道了。问题是,为什么我的排除不适用于派生配置?

基本上我想做与这个问题相反的事情。

我也尝试了约束版本,但它们表现出同样的问题:

compileOnly deps.diffx
runtimeOnly(deps.diffx) {
    constraints {
        implementation('com.propensive:magnolia_' + versions.scala_v + ':0.10.0') {
            because 'this version is required by our other dependencies'
        }
    }
}

标签: gradleosgidependency-managementbnd

解决方案


Gradle 文档中

从好的方面来说,与 Maven 相比,Gradle 的排除处理将整个依赖关系图考虑在内。因此,如果一个库上有多个依赖项,则只有在所有依赖项都同意它们时才会执行排除。例如,如果我们在上面的项目中添加 opencsv 作为另一个依赖项,它也依赖于 commons-beanutils,commons-collection 不再被排除,因为 opencsv 本身并不排除它。

因此,我们可以使用依赖解析规则

def magnoliaVersion = '0.10.0'

configurations.runtimeClasspath {
    resolutionStrategy.eachDependency { DependencyResolveDetails details ->
        if (details.requested.group == 'com.propensive' && details.requested.name.startsWith("magnolia_") && details.requested.version != magnoliaVersion) {
            details.useVersion magnoliaVersion
            details.because 'this version is required by our other dependencies'
        }
    }
}

然后将依赖项改回一个简单的单一的依赖项implementation

implementation deps.diffx

不幸的是,正如文档所述,此解析规则未发布,因此必须在任何依赖的 Gradle 模块中再次应用它。


推荐阅读