Gradle显示子项目的编译配置内容

时间:2017-07-07 22:06:42

标签: gradle configuration

尝试显示子项目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),它们包含相同的文件集。

1 个答案:

答案 0 :(得分:1)

您的问题基于与StackOverflow上大多数Gradle问题相同的技术细节:配置阶段执行阶段之间的差异。

如果您定义了一个任务(例如示例中的foo),则以下闭包中的代码 NOT 定义任务在执行时将执行的操作。相反,它在任务定义之后立即执行,应该用于配置任务。这就是每次在项目上运行Gradle时执行代码的原因(在配置阶段中)。另一方面,您的示例中的任务在执行时(执行阶段)将执行绝对没有。在执行阶段期间,仅执行任务操作(由任务类型定义),doFirstdoLast闭包。另请注意,将为每个任务完成(任务)配置,但只会执行选定的任务(通过命令行或依赖项)。

了解上述内容后,我们可以理解代码中的问题:它尝试在根项目的配置阶段期间打印子项目配置的内容。子项目的配置阶段,在其中添加依赖项,根项目的配置阶段之后,您将在其中解析配置(有必要显示内容)。但是您无法将依赖项添加到已经解析的配置中。

这意味着,您的代码将被执行,解析配置并且不打印任何内容,因为在执行时配置为空。之后,在子项目dependencies闭包中,您尝试将依赖项添加到已解析的配置中,从而导致错误。注释掉子项目compile中的所有(foo)依赖项,错误应该消失。

但是,这不是你想要的。您希望在添加后列出配置文件。为此,您可以轻松地将任务代码移至doLast(或doFirst)闭包:

task foo {
    doLast {
        project(':foo').configurations.compile.files.each { 
            println it.name
        }
    }
}

现在,您的配置在根项目的执行阶段中得到解决,该阶段位于子项目的配置阶段之后,因此不会出现任何问题添加依赖项。请注意,只有在您指定任务时才会执行该任务(例如,在另一个将要执行的任务中调用gradle foo / gradle build foo或使用dependsOn foo)。

关于compilecompileClasspath配置之间的区别,您可以查看Gradle Java插件的the docs,它定义了两种配置:配置可以扩展其他配置,这意味着它们将包含其他配置包含的所有依赖项,但也可以包含其他依赖项。如果您仅使用compile个相关性,则compilecompileClasspath将相同,但例如compileOnly依赖关系仅列在compileClasspath下。