2010-07-16 3 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- exclude-pattern-issue –

+2

Документы (теперь?) говорят, что ['CreateItem' устарел] (http://msdn.microsoft.com/en-us/library/s2y3e43x%28v=vs.90%29), поэтому Я бы не стал использовать его, если это не было необходимо (я думаю, что он расширяет параметры более агрессивно, чем 'ItemGroup'), потому что в очень отдаленном будущем, возможно, он не будет включен в .net ;-). Таким образом, вероятно, это не «синтаксический сахар». – binki

Смежные вопросы