Gradle无法更改配置的依赖关系

时间:2017-05-13 14:06:26

标签: gradle configuration

Intellij Idea中的

“刷新所有gradle项目”给出了以下错误:

Error:(15, 0) Cannot change dependencies of configuration ':util:compile' after it has been included in dependency resolution.

当我将第二个if语句移动到子模块项目的build.gradle时,不会发生此问题。虽然我找到了解决方法,但我想了解为什么原始解决方案不正确。制造麻烦的路线是:

"Class-Path": (configurations.compile.collect {"$dependencyDir/$it.name"}.join(" "))

项目结构:

mcv-gradle-example
|__ submodule (gradle project)
|__ util (gradle project)
|__ build.gradle

的build.gradle:

allprojects {
    apply plugin: 'java'
}

subprojects {
    apply plugin: 'scala'

    repositories {
        mavenCentral()
    }

    def isSpecialProject = project.name in ["submodule"]

    dependencies {
        compile group: 'org.scala-lang', name: 'scala-library', version: '2.12.1'
        if (isSpecialProject) {
            compile project(':util')
        }
    }

    if (isSpecialProject) {
        def dependencyDir = "/deps"

        task setupJarManifest() {
            jar.manifest.attributes(
                    "Class-Path": (configurations.compile.collect {"$dependencyDir/$it.name"}.join(" ")))
        }

        jar.dependsOn setupJarManifest
    }
}

更新 我发现拥抱jar.manifest...afterEvaluate允许在main build.gradle中执行此任务。但是我仍然不确定gradle的问题是什么。

更新2: 似乎移动设置manifest.attributes到执行阶段解决了他的问题。我的最终解决方案是:

if (isSpecialProject) {
    def dependencyDir = "deps"

    jar {
        doFirst {
            manifest.attributes(
                "Class-Path": (configurations.compile.collect {"$dependencyDir/$it.name"}.join(" "))
            )
        }
    }
}

我的猜测是: 当子模块项目在配置阶段使用configurations.compile时,将解决所有依赖项。然后针对util项目评估子项目闭包。由于util是子模块的依赖,因此在不久前我们使用了它的所有依赖关系。这是合理的,但我仍然不知道configurations.compile的用法如何将util的依赖关系标记为已关闭。

解释

经过一些研究后,我终于知道发生了什么:

  1. 首先评估子项目submodule。它将scala和子项目util放入其依赖项中。
  2. 然后gradle评估configurations.compile.collect内部调用iterator方法调用DefaultConfiguration#getFiles。要查找为此配置指定的文件,它会解析图形和工件(锁定它的依赖项修改功能)。
  3. 然后针对子项目util评估子项目闭包。它试图将scala放在其依赖项中但由于第2点而被锁定,因此它会抛出错误。
  4. 在正确解析图形和工件后,将collect移动到afterEvaluationdoLast会执行它。它可以在执行阶段多次调用。

0 个答案:

没有答案