为什么MSBuild ItemGroup条件条件不能在全局范围内工作 [英] Why doesn't MSBuild ItemGroup conditional work in a global scope
问题描述
我非常想知道为什么我无法基于在目标内部按预期工作的元数据条件在全局范围内创建项目.例如,这可以按预期工作:
<ItemGroup>
<TestItems Include="TestItem1">
<TestFlag>true</TestFlag>
</TestItems>
<TestItems Include="TestItem2">
<TestFlag>false</TestFlag>
</TestItems>
</ItemGroup>
<Target Name="Default">
<Message Text="@(TestItems)" />
<Message Text="@(TestItems)" Condition="'%(TestItems.TestFlag)'=='true'" />
<ItemGroup>
<FilteredTestItems Include="@(TestItems)" Condition="'%(TestItems.TestFlag)'=='true'" />
</ItemGroup>
<Message Text="@(FilteredTestItems)" />
<Message Text="@(FilteredTestItems)" Condition="'%(FilteredTestItems.TestFlag)'=='true'" />
</Target>
并产生以下输出:
TestItem1; TestItem2 测试项目1 测试项目1 TestItem1
这可以按预期工作:
<ItemGroup>
<TestItems Include="TestItem1">
<TestFlag>true</TestFlag>
</TestItems>
<TestItems Include="TestItem2">
<TestFlag>false</TestFlag>
</TestItems>
</ItemGroup>
<ItemGroup>
<FilteredTestItems Include="@(TestItems)" Condition="'false'=='true'" />
</ItemGroup>
<Target Name="Default">
<Message Text="@(TestItems)" />
<Message Text="@(TestItems)" Condition="'%(TestItems.TestFlag)'=='true'" />
<Message Text="@(FilteredTestItems)" />
<Message Text="@(FilteredTestItems)" Condition="'%(FilteredTestItems.TestFlag)'=='true'" />
</Target>
产生以下输出:
TestItem1; TestItem2 TestItem1
但是这个:
<ItemGroup>
<TestItems Include="TestItem1">
<TestFlag>true</TestFlag>
</TestItems>
<TestItems Include="TestItem2">
<TestFlag>false</TestFlag>
</TestItems>
</ItemGroup>
<ItemGroup>
<FilteredTestItems Include="@(TestItems)" Condition="'%(TestItems.TestFlag)'=='true'" />
</ItemGroup>
产生以下MSBuild错误:
temp.proj(13,45):错误MSB4090:在条件'%(TestItems.TestFlag)'=='true'"的位置2处发现意外字符'%'.
那有什么用呢?当然,我可以解决它,但是我对ItemGroup,元数据和/或全局作用域到底不了解什么?
项目组条件在目标外部有效,但批处理无效(这是%"运算符).批处理是在调用任务时使用的,并且由于只能从目标内部调用任务,因此批处理也只能在目标内部工作是很有意义的.
您可能会问,为什么该项目组在目标内有效,因为这不是一项任务.在MSBuild 3.5之前,根本不允许在目标内部包含项目组.您必须改为调用CreateItem
.在版本3.5和4.0中,允许使用这种方式使用项目组,但是我认为这只是调用CreateItem
任务的语法糖,因此您的条件有效,因为在后台有 个任务. /p>
I'm desperately curious why I am unable to create an item in a global scope based on a metadata condition which works as expected inside a target. For instance, this works as expected:
<ItemGroup>
<TestItems Include="TestItem1">
<TestFlag>true</TestFlag>
</TestItems>
<TestItems Include="TestItem2">
<TestFlag>false</TestFlag>
</TestItems>
</ItemGroup>
<Target Name="Default">
<Message Text="@(TestItems)" />
<Message Text="@(TestItems)" Condition="'%(TestItems.TestFlag)'=='true'" />
<ItemGroup>
<FilteredTestItems Include="@(TestItems)" Condition="'%(TestItems.TestFlag)'=='true'" />
</ItemGroup>
<Message Text="@(FilteredTestItems)" />
<Message Text="@(FilteredTestItems)" Condition="'%(FilteredTestItems.TestFlag)'=='true'" />
</Target>
and produces the following output:
TestItem1;TestItem2 TestItem1 TestItem1 TestItem1
And this works as expected:
<ItemGroup>
<TestItems Include="TestItem1">
<TestFlag>true</TestFlag>
</TestItems>
<TestItems Include="TestItem2">
<TestFlag>false</TestFlag>
</TestItems>
</ItemGroup>
<ItemGroup>
<FilteredTestItems Include="@(TestItems)" Condition="'false'=='true'" />
</ItemGroup>
<Target Name="Default">
<Message Text="@(TestItems)" />
<Message Text="@(TestItems)" Condition="'%(TestItems.TestFlag)'=='true'" />
<Message Text="@(FilteredTestItems)" />
<Message Text="@(FilteredTestItems)" Condition="'%(FilteredTestItems.TestFlag)'=='true'" />
</Target>
Producing the following output:
TestItem1;TestItem2 TestItem1
But this:
<ItemGroup>
<TestItems Include="TestItem1">
<TestFlag>true</TestFlag>
</TestItems>
<TestItems Include="TestItem2">
<TestFlag>false</TestFlag>
</TestItems>
</ItemGroup>
<ItemGroup>
<FilteredTestItems Include="@(TestItems)" Condition="'%(TestItems.TestFlag)'=='true'" />
</ItemGroup>
Produces the following MSBuild error:
temp.proj(13,45): error MSB4090: Found an unexpected character '%' at position 2 in condition "'%(TestItems.TestFlag)'=='true'".
So what gives? Certainly I can work around it, but what exactly am I not understanding about ItemGroup, metadata and/or the global scope?
The item group condition works outside a target, but batching doesn't (that's the "%" operator). Batching is used when you call a task, and since you can only call a task from inside a target, it makes sense for batching to also only work inside a target.
You might ask why the item group works inside the target since it's not a task. Prior to MSBuild 3.5, you weren't allowed item groups inside targets at all; you had to call CreateItem
instead. In versions 3.5 and 4.0, using item groups that way is allowed, but I think it's just syntactic sugar for calling the CreateItem
task, so your condition works because there is a task behind the scenes.
这篇关于为什么MSBuild ItemGroup条件条件不能在全局范围内工作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!