问题描述
我正在尝试使用 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
}
如果我使用 Gradle dependencies
任务检查依赖项,它显示 magnolia 已按预期从 runtimeOnly
配置中排除 - 但未从 { {1}} 配置。
如果我然后使用 runtimeClasspath
尝试找出此依赖项的来源,它会告诉我较新的版本来自 ./gradlew dependencyInsight --dependency magnolia_2.12 --configuration runtime
,具体取决于 runtimeClasspath
,这是通过冲突解决选择。嗯,谢谢 - 我已经知道了。问题是,为什么我的排除没有应用于派生配置?
基本上我想做与this question相反的事情。
我也尝试过约束版本,但它们表现出同样的问题:
diffx
解决方法
从好的方面来说,与 Maven 相比,Gradle 的排除处理考虑了整个依赖关系图。因此,如果一个库有多个依赖项,则仅当所有依赖项都同意时才会执行排除。例如,如果我们将 opencsv 作为另一个依赖添加到我们上面的项目中,它也依赖于 commons-beanutils,则不再排除 commons-collection,因为 opencsv 本身不排除它。
因此,我们可以使用 dependency resolve rule:
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'
}
}
}
然后将依赖项改回简单的单个 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
不幸的是,如文档所述,此解析规则未发布,因此必须在任何依赖的 Gradle 模块中再次应用。