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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With