Gradle 多项目可选子项目的传递依赖应解析为现有子项目 [英] Gradle multiproject optional subproject's transitive dependency should be resolved to an existing subproject
问题描述
假设以下项目.主项目是一个多项目,但较大项目的每个部分都可以单独开发或混合开发:
suppose the following project. the master project is a multi-project, however every part of the larger project can be developed individually or mixed in:
/master/build.gradle
/m1/build.gradle
/m2/build.gradle
/m3/build.gradle
假设 m3
使用 m2
并且 m2
使用 m1
( m1 <- m2
- m3)
suppose m3
uses m2
and m2
uses m1
( m1 <- m2 <- m3 )
m2
的存在是可选的,多项目采用以下布局也是合理的
the presence of m2
is optional a multi-project with the following layout also reasonable
/master/build.gradle
/m1/build.gradle
/m3/build.gradle
但在这种情况下 m2
将从工件存储库中提取,这很好......但是 m1
是 m2
这很好,但是我如何告诉 gradle 使用本地版本的 m1
而不是烘焙的工件?
but in this case m2
would be pulled in from the artifact repository which is fine...however m1
was a transitive dependency of m2
which is good, but how can i tell gradle to use the local version of m1
instead of the baked artifact?
我坚持这一点,我有权覆盖这些东西的每个地方 gradle 都给了我只是" ModuleVersionSelector
级别的访问权限,我该如何添加 DefaultProjectDependency
根据到下载的工件传递依赖项?
I'm stuck with this, every place i have access to override these thing gradle gives me "just" ModuleVersionSelector
level access, how can i add a DefaultProjectDependency
according to the downloaded artifact transitive dependencies?
如果我可以访问存档工件的完整依赖关系图并放入一些覆盖/排除项,我可能会有替代方案.
i may have an alternative if i can access the full dependency graph of the archived artifacts, and put in some overrides/excludes.
我想出的最好的方法是使用使用 resolutionStrategy 的过滤器,我通过进一步开发elastic-deps"项目创建了一个示例
the best i've come up with is using a filter using resolutionStrategy, i've created an example by further developing the 'elastic-deps' project
https://github.com/kgyrtkirk/elastic-deps
推荐答案
从elastic-deps开始 并在 this answer 的帮助下(也来自 Peter) 我想出了下面的窍门.
Starting with elastic-deps and with the help of this answer (also from Peter) I came up with the trick below.
在顶层build.gradle()中:
In the top-level build.gradle():
// make sure we've parsed the subproject dependencies
evaluationDependsOnChildren()
def subprojectsByName = subprojects.collectEntries { it -> [it.name, it] }
subprojects.each { p ->
def hacks = [] // list of changes we're going to make
p.configurations.each { c ->
c.dependencies.each { d ->
if (d.group.startsWith("my.group.prefix")) {
def sub = subprojectsByName[d.name]
if (sub != null) {
hacks.add({
// can't do this immediately or we'll get ConcurrentModificationExceptions
c.dependencies.remove(d)
p.dependencies.add(c.name, sub)
})
}
}
}
}
// Now we can safely apply the changes
for (hack in hacks) {
hack()
}
}
这样做的好处是,与 elastic-deps 不同,您不必修改子项目.
The nice thing about this is that unlike elastic-deps you don't have to modify the subprojects.
这仍然存在一个问题,即一旦遇到二进制依赖项,任何纯传递依赖项都会被解析为二进制.例如,假设我有一个项目 cyan
直接依赖于 green
和 blue
并通过 green
传递,黄色
:
This still has the problem that once you hit a binary dependency, any purely transitive dependencies are resolved as binary. E.g., say I have a project cyan
which depends directly on green
and blue
and transitively, through green
, on yellow
:
compile - Compile classpath for source set 'main'.
+--- my.shared:blue:+ -> 2.0-SNAPSHOT
+--- my.shared:green:+ -> 2.0-SNAPSHOT
| +--- my.shared:yellow:+ -> 2.0-SNAPSHOT
| --- my.shared:blue:+ -> 2.0-SNAPSHOT
现在,如果我将 blue
和 yellow
添加到我的多模块项目中,而不是 green
,我会得到:
Now if I add blue
and yellow
to my multi-module project, but not green
, I get:
compile - Compile classpath for source set 'main'.
+--- com.iii.shared:green:+ -> 2.0-SNAPSHOT
| +--- com.iii.shared:yellow:+ -> 2.0-SNAPSHOT
| --- com.iii.shared:blue:+ -> project :blue
--- project :blue
请注意,即使是可传递的,blue
也可以正确解析为项目,但 yellow
不是.
Note that blue
is resolved correctly to the project even when it's transitive, but yellow
isn't.
我个人认为这是一个特性,而不是错误——它反映了分发时实际发生的情况.我可以对 yellow
进行所有我想要的更改,但如果我没有在我的存储库中放置新的 yellow
工件以及更新的 green
使用更新的依赖项,那么 cyan
的实际版本将不会获得这些更改.
Personally I think this is a feature, not a bug -- it reflects what would actually happen at distribution time. I can make all the changes to yellow
I want, but if I don't put a new yellow
artifact in my repository and also an updated green
with the updated dependency, then the actual release of cyan
isn't going to get those changes.
这篇关于Gradle 多项目可选子项目的传递依赖应解析为现有子项目的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!