在 Gradle 中,如何以编程方式排除然后强制依赖?
In Gradle, how programmatically to exclude then force a dependency?
最终目标是用不同的版本替换传递依赖的版本。需要注意的是,替换应该由那些依赖于正在构建的库的人来选择(我不知道它是标准 Gradle 还是插件,但如果我们 exclude
是传递依赖,则生成ivy.xml
文件将包含该信息)。
实现最终目标的一种可能方法是 exclude
有问题的依赖性,然后在以后强制该依赖性。
exclude
依赖的方法是:
dependencies {
compile 'org:name:version' {
exclude(group: 'group', module: 'module')
}
}
force
依赖的方法是这样的:
configurations.all {
resolutionStrategy {
eachDependency { DependencyResolveDetails dependencyResolveDetails ->
final requestedDependency = dependencyResolveDetails.requested
if (requestedDependency.group == 'org' && requestedDependency.name == 'name') {
force 'group:module:good_version'
}
}
}
}
为了将两者联系在一起,resolutionStrategy
必须知道哪些依赖实际上 exclude
d 是稍后将成为 force
d 的传递依赖。如何以通用方式完成此操作(假设有一种通用方式来执行 exclude
)?如果没有办法将两者联系在一起,是否有不同的方法来实现最终目标?
首先,抽象依赖关系,使它们看起来像:
dependencies {
compile dep('org:name')
}
dep
函数可以定义为自动排除的方式:
final rev = [
'group:module': 'good_version'
'org:name': 'version']
ext.rev = { m ->
rev[m]
}
final dep = { m ->
"${m}:${ext.rev(m)}"
}
final forcedTransitiveDeps = [
'org:name': [
dep('group:module')]].withDefault({[]})
ext.forcedTransitiveDeps = { m ->
forcedTransitiveDeps[m]
}
ext.dep = { m ->
if (!forcedTransitiveDeps.containsKey(m)) {
project.dependencies.create(dep(m))
} else {
project.configure(
project.dependencies.create(dep(m)),
{
forcedTransitiveDeps[m].each { dependency ->
final dependencyParts = dependency.split(':')
exclude(group: dependencyParts[0], module: dependencyParts[1])
}
})
}
}
最后,重新引入并强制依赖:
subprojects { subproject ->
subproject.afterEvaluate {
subproject.configurations.all { Configuration configuration ->
final dependencies = configuration.getDependencies()
final forcedDependencies = (dependencies.collect { dependency ->
forcedTransitiveDeps("${dependency.group}:${dependency.name}")
}).flatten()
if (!forcedDependencies.isEmpty()) {
logger.info("Forcing ${subproject} dependencies on ${forcedDependencies} as per `ext.forcedTransitiveDeps`.")
dependencies.addAll(forcedDependencies.collect { forcedDependency ->
subproject.dependencies.create(forcedDependency)
})
}
}
}
}
最终目标是用不同的版本替换传递依赖的版本。需要注意的是,替换应该由那些依赖于正在构建的库的人来选择(我不知道它是标准 Gradle 还是插件,但如果我们 exclude
是传递依赖,则生成ivy.xml
文件将包含该信息)。
实现最终目标的一种可能方法是 exclude
有问题的依赖性,然后在以后强制该依赖性。
exclude
依赖的方法是:
dependencies {
compile 'org:name:version' {
exclude(group: 'group', module: 'module')
}
}
force
依赖的方法是这样的:
configurations.all {
resolutionStrategy {
eachDependency { DependencyResolveDetails dependencyResolveDetails ->
final requestedDependency = dependencyResolveDetails.requested
if (requestedDependency.group == 'org' && requestedDependency.name == 'name') {
force 'group:module:good_version'
}
}
}
}
为了将两者联系在一起,resolutionStrategy
必须知道哪些依赖实际上 exclude
d 是稍后将成为 force
d 的传递依赖。如何以通用方式完成此操作(假设有一种通用方式来执行 exclude
)?如果没有办法将两者联系在一起,是否有不同的方法来实现最终目标?
首先,抽象依赖关系,使它们看起来像:
dependencies {
compile dep('org:name')
}
dep
函数可以定义为自动排除的方式:
final rev = [
'group:module': 'good_version'
'org:name': 'version']
ext.rev = { m ->
rev[m]
}
final dep = { m ->
"${m}:${ext.rev(m)}"
}
final forcedTransitiveDeps = [
'org:name': [
dep('group:module')]].withDefault({[]})
ext.forcedTransitiveDeps = { m ->
forcedTransitiveDeps[m]
}
ext.dep = { m ->
if (!forcedTransitiveDeps.containsKey(m)) {
project.dependencies.create(dep(m))
} else {
project.configure(
project.dependencies.create(dep(m)),
{
forcedTransitiveDeps[m].each { dependency ->
final dependencyParts = dependency.split(':')
exclude(group: dependencyParts[0], module: dependencyParts[1])
}
})
}
}
最后,重新引入并强制依赖:
subprojects { subproject ->
subproject.afterEvaluate {
subproject.configurations.all { Configuration configuration ->
final dependencies = configuration.getDependencies()
final forcedDependencies = (dependencies.collect { dependency ->
forcedTransitiveDeps("${dependency.group}:${dependency.name}")
}).flatten()
if (!forcedDependencies.isEmpty()) {
logger.info("Forcing ${subproject} dependencies on ${forcedDependencies} as per `ext.forcedTransitiveDeps`.")
dependencies.addAll(forcedDependencies.collect { forcedDependency ->
subproject.dependencies.create(forcedDependency)
})
}
}
}
}