尝试显示子项目foo的配置内容:
task foo {
project(':foo').configurations.compile.files.each {
println it.name
}
project(':foo').configurations.compileClasspath.files.each {
println it.name
}
}
错误
* What went wrong:
A problem occurred evaluating project ':foo'.
> Cannot change dependencies of configuration ':foo:compile' after it has been resolved.
我对configurations.compile和configurations.compileClasspath感到困惑。它们是一样的吗?两者都是FileCollection?
对于当前项目(不是:foo),它们包含相同的文件集。
答案 0 :(得分:1)
您的问题基于与StackOverflow上大多数Gradle问题相同的技术细节:配置阶段与执行阶段之间的差异。
如果您定义了一个任务(例如示例中的foo
),则以下闭包中的代码 NOT 定义任务在执行时将执行的操作。相反,它在任务定义之后立即执行,应该用于配置任务。这就是每次在项目上运行Gradle时执行代码的原因(在配置阶段中)。另一方面,您的示例中的任务在执行时(执行阶段)将执行绝对没有。在执行阶段期间,仅执行任务操作(由任务类型定义),doFirst
和doLast
闭包。另请注意,将为每个任务完成(任务)配置,但只会执行选定的任务(通过命令行或依赖项)。
了解上述内容后,我们可以理解代码中的问题:它尝试在根项目的配置阶段期间打印子项目配置的内容。子项目的配置阶段,在其中添加依赖项,在根项目的配置阶段之后,您将在其中解析配置(有必要显示内容)。但是您无法将依赖项添加到已经解析的配置中。
这意味着,您的代码将被执行,解析配置并且不打印任何内容,因为在执行时配置为空。之后,在子项目dependencies
闭包中,您尝试将依赖项添加到已解析的配置中,从而导致错误。注释掉子项目compile
中的所有(foo
)依赖项,错误应该消失。
但是,这不是你想要的。您希望在添加后列出配置文件。为此,您可以轻松地将任务代码移至doLast
(或doFirst
)闭包:
task foo {
doLast {
project(':foo').configurations.compile.files.each {
println it.name
}
}
}
现在,您的配置在根项目的执行阶段中得到解决,该阶段位于子项目的配置阶段之后,因此不会出现任何问题添加依赖项。请注意,只有在您指定任务时才会执行该任务(例如,在另一个将要执行的任务中调用gradle foo
/ gradle build foo
或使用dependsOn foo
)。
关于compile
和compileClasspath
配置之间的区别,您可以查看Gradle Java插件的the docs,它定义了两种配置:配置可以扩展其他配置,这意味着它们将包含其他配置包含的所有依赖项,但也可以包含其他依赖项。如果您仅使用compile
个相关性,则compile
和compileClasspath
将相同,但例如compileOnly
依赖关系仅列在compileClasspath
下。