Двойной цикл в msbuild? - PullRequest
       17

Двойной цикл в msbuild?

13 голосов
/ 24 января 2011

Я пишу скрипт для msbuild, который должен делать две партии за один шаг.
Пример: 2 ItemGroups

<ItemGroup>
 <GroupOne Include="1" />
 <GroupOne Include="2" />
</ItemGroup>

<ItemGroup>
 <GroupTwo Include="A" />
 <GroupTwo Include="B" />
</ItemGroup>

Эти две группы должны быть соединены друг с другом:

<Message Text="%(GroupOne.Identity) %(GroupTwo.Identity)" />

Я надеялся, что msbuild сделает результат из обеих партий, давая

1 A  
2 A  
1 B  
2 B  

как результат.
Но этого не произошло. Вместо этого он вернул следующее бесполезное дерьмо:

1  
2  
  A  
  B  

Делаем так, как предлагает блог из ссылки ниже (используя локальную группу свойств), как

<PropertyGroup>
  <GroupOneStep>%(GroupOne.Identity)</GroupOneStep>
</PropertyGroup>
<Message Text="$(GroupOneStep) %(GroupTwo.Identity)" />

делает

2 A   
2 B

Есть намеки? Я схожу с ума. : - (

PS: Вот пост в блоге на эту тему - к сожалению, он не работает так, как там сказано: http://blogs.msdn.com/b/giuliov/archive/2010/04/30/gotcha-msbuild-nested-loops-double-batching.aspx

Ответы [ 4 ]

13 голосов
/ 03 августа 2013

Это гораздо более простое решение.

<Target Name="Default">
    <ItemGroup>
        <Combined Include="@(GroupOne)">
            <GroupTwo>%(GroupTwo.Identity)</GroupTwo>
        </Combined>
    </ItemGroup>

    <Message Text="%(Combined.Identity) %(Combined.GroupTwo) " />
</Target>

Использование группы промежуточных элементов Combined для создания группы промежуточных элементов, в которую входит задача «Сообщение».

Если вы ссылаетесь на две группы элементов в одной задаче, Msbuild выполнит пакетную обработку на них обоих по отдельности. что НЕ то, что вы хотите

Если у вас есть больше ItemMetaData, вам необходимо явно обработать это для второй ItemGroup. ItemGroup, включенная в символ ссылки @, автоматически включает ItemMetaData, поэтому вам просто нужно создать дополнительные метаданные из второй группы: ссылка явно. Вот пример:

<ItemGroup>
    <GroupOne Include="1">
        <Name>One</Name>
    </GroupOne>
    <GroupOne Include="2">
        <Name>Two</Name>
    </GroupOne>
</ItemGroup>

<ItemGroup>
    <GroupTwo Include="A">
        <Name>Andrew</Name>
    </GroupTwo>
    <GroupTwo Include="B">
        <Name>Bob</Name>
    </GroupTwo>
</ItemGroup>

<Target Name="Default">
    <ItemGroup>
        <Combined Include="@(GroupOne)">
            <GroupTwo>%(GroupTwo.Identity)</GroupTwo>
            <GroupTwoName>%(GroupTwo.Name)</GroupTwoName>
        </Combined>
    </ItemGroup>

    <Message Text="%(Combined.Identity) %(Combined.Name) %(Combined.GroupTwoName) %(Combined.GroupTwo) " />
</Target>
12 голосов
/ 25 января 2011

Попробуйте создать новую ItemGroup, используя идентификатор из группы 1 и назначив метаданные новой группе элементов из идентификатора (или любых других метаданных) группы 2. Затем используйте пакетную обработку для перебора новой группы.

<CreateItem Include="@(GroupOne)" AdditionalMetadata="Option1=%(GroupTwo.Identity)">
    <Output ItemName="_Group_Merged" TaskParameter="Include"/>
</CreateItem>

<Message Text="%(_Group_Merged.Identity)-%(_Group_Merged.Option1)" />

Если у вас более двух групп, вы можете добавить записи CreateItem, чтобы объединить третью группу с _Group_Merged и затем выполнить итерацию по этой объединенной группе.

<CreateItem Include="@(_Group_Merged)" AdditionalMetadata="Option2=%(GroupThree.Identity)">
    <Output ItemName="_Group_Merged2" TaskParameter="Include"/>
</CreateItem>

<Message Text="%(_Group_Merged2.Identity)-%(_Group_Merged2.Option1)-%(_Group_Merged2.Option2)" />
4 голосов
/ 18 февраля 2014

Можно также сделать тройные вложенные петли в технике Собачьи уши .

  <Target Name="Test">
    <ItemGroup>
      <Loop1 Include="L11" />
      <Loop1 Include="L12" />
      <Loop2 Include="L21" />
      <Loop2 Include="L22" />
      <Loop3 Include="L31" />
      <Loop3 Include="L32" />
      <Loop12 Include="@(Loop1)">
        <!-- Combine Loop1 and Loop2: Inherit each meta data of Loop1 and add some of Loop2. -->
        <Loop2Identity>%(Loop2.Identity)</Loop2Identity>
      </Loop12>
      <Loop123 Include="@(Loop12)">
        <!-- Combine Loop12 and Loop3: Inherit each meta data of Loop12 and add some of Loop3. -->
        <Loop3Identity>%(Loop3.Identity)</Loop3Identity>
      </Loop123>
    </ItemGroup>
    <!-- Show all entries of Loop1 and Loop2 combined -->
    <Message Text="Loop12.Identity=%(Loop12.Identity), Loop12.Value1=%(Loop12.Value1), Loop12.Loop2Identity=%(Loop12.Loop2Identity)"/>
    <!-- Show all entries of Loop1, Loop2 and Loop3 combined -->
    <Message Text="Loop123.Identity=%(Loop123.Identity), Loop123.Loop2Identity=%(Loop123.Loop2Identity) Loop123.Loop2Identity=%(Loop123.Loop3Identity)"/>
  </Target>
0 голосов
/ 04 декабря 2017

Для двух вложенных циклов это работает:

<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

    <ItemGroup>
        <GroupOne Include="1" />
        <GroupOne Include="2" />
    </ItemGroup>

    <ItemGroup>
        <GroupTwo Include="A" />
        <GroupTwo Include="B" />
    </ItemGroup>

    <Target Name="Exec"
        Outputs="%(GroupOne.Identity)">
        <Message Text="Building @(GroupOne->'%(Identity)') %(GroupTwo.Identity)"/>
    </Target>  

</Project>

Результат:

Project "D:\tmp\msbuildtest\test.xml" on node 0 (default targets).
  Building 1 A
  Building 1 B
Exec:
  Building 2 A
  Building 2 B
Done Building Project "D:\tmp\msbuildtest\test.xml" (default targets).
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...