Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why doesn't MSBuild ItemGroup conditional work in a global scope

Tags:

msbuild

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?

like image 816
Amandalishus Avatar asked Jul 16 '10 14:07

Amandalishus


1 Answers

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.

like image 159
Rory MacLeod Avatar answered Nov 15 '22 12:11

Rory MacLeod