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

Jul*_*bin 6 configuration gradle

Intellij Idea中的“刷新所有gradle项目”给我以下错误:

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

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

"Class-Path": (configurations.compile.collect {"$dependencyDir/$it.name"}.join(" "))
Run Code Online (Sandbox Code Playgroud)

项目结构:

mcv-gradle-example
|__ submodule (gradle project)
|__ util (gradle project)
|__ build.gradle
Run Code Online (Sandbox Code Playgroud)

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
    }
}
Run Code Online (Sandbox Code Playgroud)

更新: 我发现拥抱jar.manifest...afterEvaluate允许其在主要的build.gradle这个任务。但是我仍然不确定gradle的问题是什么。

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

if (isSpecialProject) {
    def dependencyDir = "deps"

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

我的猜测是:当子模块项目configurations.compile在配置阶段使用时,所有依赖项都已解决。然后,为util项目评估子项目的关闭。由于util是子模块的依赖项,因此不能添加新的依赖项,因为不久前我们使用了所有依赖项。这是合理的,但我仍然不知道如何使用configuration.compile将utils的依赖项编译为“ marks”。

说明

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

  1. submodule首先评估子项目。它将scala和子项目util放入其依赖项中。
  2. 然后gradle评估configurations.compile.collect在内部调用iterator方法调用DefaultConfiguration#getFiles。要查找为此配置指定了哪些文件,它将解析图形和工件(锁定其依赖项修改功能)。
  3. 然后评估子项目的关闭情况util。它试图将scala置于其依赖项中,但由于第2点而被锁定,因此会引发错误。

移动collectafterEvaluationdoLast执行之后图形和文物的正确的分辨率。在执行阶段可以多次调用它。