等级:无法从另一个项目访问一个项目中定义的配置
Grade: Can't access configuration defined in one project from another project
我对 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
被传递给任务,而在修改版本中 'normal' 闭包传递给 'doLast' 方法。
那么,首先,我的假设是否正确?
其次,为什么我一开始就无法访问'sub2'项目?
最后,是否可以在第一个实例中(即在配置闭包中)访问 'sub2' 项目?
[更新]进一步的问题
鉴于 "Invisible Arrow" 提供的公认答案,我想再问一个关于引用另一个项目配置的最佳实践的问题(即 sub1 中的任务需要使用由子 2 项目)。
我是否应该声明两个项目之间的评估依赖关系?
或者我应该只在执行时引用 sub2 的配置(例如在 doLast() 中)吗?
或者,我应该在两个项目之间创建依赖配置吗?
是的,两者是有区别的。
构建基本上有 3 个阶段,即 初始化、配置 和执行。 Gradle 文档中的 Build Lifecycle 章节对此进行了详细描述。
在您的情况下,第一个实例属于 Configuration 阶段,无论任务是否执行,都会对其进行评估。这意味着闭包中的所有语句都会在您开始构建时执行。
task testConfiguration {
// This always runs during a build,
// irrespective of whether the task is executed or not
println project(':sub2').configurations.sub2FooConfiguration
}
第二个实例属于执行阶段。注意<<
是doLast
的shorthand,这个闭包是在任务执行的时候调用的
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
项目的 Configuration 阶段。因此 sub2FooConfiguration
尚未创建。
为什么?因为 sub1
和 sub2
之间没有明确的求值依赖关系。在您的情况下,sub1
需要 sub2
作为评估依赖项,因此我们可以在任务声明之前在 sub1
的 build.gradle
中添加该依赖项,如下所示:
evaluationDependsOn(':sub2')
task testConfiguration {
println project(':sub2').configurations.sub2FooConfiguration
}
这将确保 sub2
始终在 sub1
之前评估(评估意味着项目的 配置 阶段)。 sub1
现在可以在任务声明闭包中访问 configurations.sub2FooConfiguration
。这在 Multi-project Builds 章节中有详细解释。
在第二个实例中,configurations.sub2FooConfiguration
是可访问的,因为调用是在任务的执行块中(在两个项目的 配置 阶段之后) .
PS:请注意,如果您颠倒了项目名称,那么第一个实例实际上可能有效,因为 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
被传递给任务,而在修改版本中 'normal' 闭包传递给 'doLast' 方法。
那么,首先,我的假设是否正确?
其次,为什么我一开始就无法访问'sub2'项目?
最后,是否可以在第一个实例中(即在配置闭包中)访问 'sub2' 项目?
[更新]进一步的问题
鉴于 "Invisible Arrow" 提供的公认答案,我想再问一个关于引用另一个项目配置的最佳实践的问题(即 sub1 中的任务需要使用由子 2 项目)。
我是否应该声明两个项目之间的评估依赖关系?
或者我应该只在执行时引用 sub2 的配置(例如在 doLast() 中)吗?
或者,我应该在两个项目之间创建依赖配置吗?
是的,两者是有区别的。 构建基本上有 3 个阶段,即 初始化、配置 和执行。 Gradle 文档中的 Build Lifecycle 章节对此进行了详细描述。
在您的情况下,第一个实例属于 Configuration 阶段,无论任务是否执行,都会对其进行评估。这意味着闭包中的所有语句都会在您开始构建时执行。
task testConfiguration {
// This always runs during a build,
// irrespective of whether the task is executed or not
println project(':sub2').configurations.sub2FooConfiguration
}
第二个实例属于执行阶段。注意<<
是doLast
的shorthand,这个闭包是在任务执行的时候调用的
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
项目的 Configuration 阶段。因此 sub2FooConfiguration
尚未创建。
为什么?因为 sub1
和 sub2
之间没有明确的求值依赖关系。在您的情况下,sub1
需要 sub2
作为评估依赖项,因此我们可以在任务声明之前在 sub1
的 build.gradle
中添加该依赖项,如下所示:
evaluationDependsOn(':sub2')
task testConfiguration {
println project(':sub2').configurations.sub2FooConfiguration
}
这将确保 sub2
始终在 sub1
之前评估(评估意味着项目的 配置 阶段)。 sub1
现在可以在任务声明闭包中访问 configurations.sub2FooConfiguration
。这在 Multi-project Builds 章节中有详细解释。
在第二个实例中,configurations.sub2FooConfiguration
是可访问的,因为调用是在任务的执行块中(在两个项目的 配置 阶段之后) .
PS:请注意,如果您颠倒了项目名称,那么第一个实例实际上可能有效,因为 Gradle 按字母顺序配置项目,如果没有明确的依赖关系。但是,当然,你永远不应该依赖它并确保明确声明项目之间的依赖关系。