2010-07-16 32 views
6

我非常好奇为什么我无法在全局范围内创建基于元数据条件的项目,该元数据条件在目标中按预期工作。例如,该按预期工作:MSBuild ItemGroup为什么不在全局范围内有条件工作

<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 TestItem1 TestItem1 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:实测值意外字符 '%' 在位置2中的条件“%(TestItems.TestFlag) '==' 真'”。

那么是什么给?当然,我可以解决它,但我对ItemGroup,元数据和/或全局范围的理解到底是什么?

回答

4

项目组条件在目标外工作,但批处理没有(这是“%”运算符)。当您调用任务时会使用批处理,并且由于您只能从目标内部调用任务,所以批处理也仅适用于目标。

您可能会问为什么项目组在目标内工作,因为它不是一项任务。在MSBuild 3.5之前,你根本不允许项目组在目标内;您必须改为拨打CreateItem。在版本3.5和4.0中,允许使用项目组,但我认为这只是用于调用CreateItem任务的语法糖,因此您的条件将起作用,因为是幕后任务。

+0

当然,你不能在目标外使用配料。我认为这是因为解析器只能读取一次全局作用域(所以它不知道它在解析时定义了什么=>没有可能的配料)。至于ItemGroup和CreateItem之间的区别,你可以阅读这些主题:http://stackoverflow.com/questions/937681/createitem-vs-itemgroup和http://stackoverflow.com/questions/3891065/msbuild-itemgroup-include-排除模式问题 – 2011-01-06 10:19:40

+2

文档(现在?)说['CreateItem'已被弃用](http://msdn.microsoft.com/en-us/library/s2y3e43x%28v=vs.90%29),所以除非必要,否则我会避免使用它(我认为它比'ItemGroup'更加积极地扩展参数),因为在很远的将来,它可能不会包含在.net ;-)。因此,它可能不是“语法糖”。 – binki 2013-08-16 21:07:54

相关问题