等级:无法从另一个项目访问一个项目中定义的配置

时间:2015-01-10 22:29:57

标签: groovy gradle

我对gradle和groovy都很陌生。

问题

我有一个非常简单的多项目结构,如下所示:

Root project 'gradle_test'
+--- Project ':sub1'
\--- Project ':sub2'

这就是 sub1 项目的'build.grade'文件:

// build.gradle of sub1 project
task testConfiguration {
    println project(':sub2').configurations.sub2FooConfiguration
}

最后,这是 sub2 项目的'build.grade'文件:

// build.gradle of sub2 project
configurations {
    sub2FooConfiguration
}

非常简单。现在,如果我运行gradle :sub1:testConfiguration,我收到以下错误:

A problem occurred evaluating project ':sub1'.
> Could not find property 'sub2FooConfiguration' on configuration container.

但是,如果 sub1 项目中的testConfiguration任务被修改为这样,一切正常:

// notice the "<<" (I believe this is calling the 'doLast' method on the task instance)
task testConfiguration << {
    println project(':sub2').configurations.sub2FooConfiguration
}

问题

我假设'testConfiguration'任务的两个版本之间的区别在于,在第一个实例中,configuration closure被传递给任务,而在修改版本中,'正常'闭包被传递给'doLast'方法。

首先,我的假设是正确的吗?

其次,为什么我在第一个实例中无法访问'sub2'项目?

最后,是否可以在第一个实例中访问'sub2'项目(即在配置闭包中)?

[更新]进一步的问题

鉴于“Invisible Arrow”提供了接受的答案,我想问一个关于引用另一个项目配置的最佳实践的进一步问题(即sub1中的任务需要使用sub2项目生成的存档) 。

我应该在两个项目之间声明评估依赖关系吗?

或者我应该只在执行时引用sub2的配置(例如在doLast()中)?

或者,我应该在两个项目之间创建依赖关系配置吗?

1 个答案:

答案 0 :(得分:3)

是的,两者之间存在差异。 构建基本上有3个阶段,分别是初始化配置执行。这在Gradle文档的Build Lifecycle章节中详细描述。

在您的情况下,第一个实例属于配置阶段,无论任务是否执行,都会始终评估该阶段。这意味着在开始构建时,将执行闭包内的所有语句。

task testConfiguration {
    // This always runs during a build,
    // irrespective of whether the task is executed or not
    println project(':sub2').configurations.sub2FooConfiguration
}

第二个实例属于执行阶段。请注意<<doLast的简写,执行任务时会调用此闭包。

task testConfiguration << {
    // Called during actual execution of the task,
    // and called only if the task was scheduled to be executed.
    // Note that Configuration phase for both projects are complete at this point,
    // which is why :sub1 is able to access :sub2's configurations.sub2FooConfiguration
    println project(':sub2').configurations.sub2FooConfiguration
}

现在来看第一个实例给出错误的原因。这是因为sub2项目的配置阶段尚未评估。因此,sub2FooConfiguration尚未创建。

为什么呢?因为sub1sub2之间没有明确的评估依赖关系。在您的情况下,sub1需要sub2作为评估依赖项,因此我们可以在任务声明之前在sub1的{​​{1}}中添加该依赖项,如下所示:

build.gradle

这将确保始终在evaluationDependsOn(':sub2') task testConfiguration { println project(':sub2').configurations.sub2FooConfiguration } 之前评估sub2(评估意味着项目的配置阶段)。 sub1现在可以在任务声明关闭中访问sub1。这在Multi-project Builds章节中有详细解释。

在第二个实例中,configurations.sub2FooConfiguration是可访问的,因为调用是在任务的执行块中(在两个项目的配置阶段之后)。

PS :请注意,如果您颠倒了项目的名称,那么第一个实例可能确实有效,因为如果没有显式依赖项,Gradle会按字母顺序配置项目。但是,当然,您不应该依赖于此并确保明确声明项目之间的依赖关系。