MSBuild - Сравнение метаданных ItemGroups - PullRequest
1 голос
/ 02 февраля 2011

Я пытаюсь написать скрипт сборки для нашего дерева исходников.Это дерево состоит из (большого) числа решений с ссылками на сборки между ними.Я создал ItemGroup, содержащую все решения, и собираю эту ItemGroup для создания решений.

Мне также нужно скопировать некоторые выходные данные проекта в папку "exes output", каждый вих собственная папка.Я прикрепил некоторые метаданные к элементу решения, указывающие на проекты, из которых я хочу получить выходные данные.Поскольку у меня может быть потенциально более одного проекта для вывода из каждого решения, я делаю это, передавая метаданным значение, которое передается в группу объектов ItemGroup для создания группы элементов отдельно.Это работает успешно, и я могу выполнить групповую обработку этой динамически созданной ItemGroup.

Последний шаг, который я хочу сделать, который вызывает у меня головную боль, заключается в том, что для некоторых этих выходных проектовЯ хочу указать специальное имя папки.Теперь я могу сделать это, изменив метаданные внутри цели, которая выполняет работу, например:

<?xml version="1.0" encoding="utf-8"?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003"
         DefaultTargets="Build">

  <!-- Define all the solutions to build, and any projects we want to handle the output of -->
  <ItemGroup>

    <SolutionsToBuild Include="$(MSBuildProjectDirectory)\Solution1\Solution1.sln">
      <ProjectsToOutput>
        $(MSBuildProjectDirectory)\Solution1\Project1A\Project1A.csproj;
        $(MSBuildProjectDirectory)\Solution1\Project1B\Project1B.csproj;
      </ProjectsToOutput>
    </SolutionsToBuild>
    <SolutionsToBuild Include="$(MSBuildProjectDirectory)\Solution2\Solution2.sln">
      <ProjectsToOutput>
        $(MSBuildProjectDirectory)\Solution2\Project2A\Project2A.csproj;
        $(MSBuildProjectDirectory)\Solution2\Project2B\Project2B.csproj;
      </ProjectsToOutput>
    </SolutionsToBuild>

  </ItemGroup>

  <Target Name="Build">

    <CallTarget Targets="DoBuild" />

  </Target>

  <Target Name="DoBuild" Outputs="%(SolutionsToBuild.Identity)">

    <Message Text="Building project: %(SolutionsToBuild.FullPath)" />
    <!-- e.g. <MSBuild Projects="%(SolutionsToBuild.FullPath)" /> -->

    <PropertyGroup>
      <ProjectsToOutputIncludeMask>%(SolutionsToBuild.ProjectsToOutput)</ProjectsToOutputIncludeMask>
    </PropertyGroup>

    <ItemGroup>
      <OutputProjects Include="$(ProjectsToOutputIncludeMask)" />

      <!-- Now create the OutputTo metadata -->
      <!-- Default to the same name as the project file -->
      <OutputProjects>
        <OutputTo>%(OutputProjects.FileName)</OutputTo>
      </OutputProjects>

      <!-- Now override specific projects OutputTo metadata -->
      <OutputProjects Condition="'%(OutputProjects.FileName)' == 'Project1A'">
        <OutputTo>ArbitraryFolder1</OutputTo>
      </OutputProjects>
      <OutputProjects Condition="'%(OutputProjects.FileName)' == 'Project2B'">
        <OutputTo>ArbitraryFolder2</OutputTo>
      </OutputProjects>

    </ItemGroup>

    <Message Text=" Outputting project: %(OutputProjects.FullPath) -> %(OutputTo)" />

  </Target>      
</Project>

Однако этот сценарий сборки должен поддерживаться всеми разработчиками в команде, а не всемикого знакомы с MSBuild.Поэтому я хотел бы определить другую ItemGroup в верхней части скрипта, которая определяет любые специальные имена.Затем они могут игнорировать все цели и задачи и просто поддерживать группы элементов, например:

<ItemGroup>

  <SolutionsToBuild Include="$(MSBuildProjectDirectory)\Solution1\Solution1.sln">
    <ProjectsToOutput>
      $(MSBuildProjectDirectory)\Solution1\Project1A\Project1A.csproj;
      $(MSBuildProjectDirectory)\Solution1\Project1B\Project1B.csproj;
    </ProjectsToOutput>
  </SolutionsToBuild>
  <SolutionsToBuild Include="$(MSBuildProjectDirectory)\Solution2\Solution2.sln">
    <ProjectsToOutput>
      $(MSBuildProjectDirectory)\Solution2\Project2A\Project2A.csproj;
      $(MSBuildProjectDirectory)\Solution2\Project2B\Project2B.csproj;
    </ProjectsToOutput>
  </SolutionsToBuild>

  <OutputNames Include="Project1A">
    <OutputFolder>ArbitraryFolder1</OutputFolder>
  </OutputNames>
  <OutputNames Include="Project2B">
    <OutputFolder>ArbitraryFolder2</OutputFolder>
  </OutputNames>

</ItemGroup>

Однако любой способ, которым я пытался заставить цель DoBuild обновить метаданные, падает на его лицо.Я думал, что смогу сделать это:

  <!-- Now override specific projects OutputTo metadata -->
  <OutputProjects Condition="'%(OutputProjects.FileName)' == '%(OutputNames.Identity)'">
    <OutputTo>%(OutputNames.OutputFolder)</OutputTo>
  </OutputProjects>

Но этот код группируется по группе элементов OutputProjects и затем по группе элементов OutputNames, поэтому условие никогда не выполняется (один из аргументовк сравнению всегда пусто).

Я, к сожалению, на данном этапе не могу изменить ни структуру решения, ни требования к структуре выходной папки.Есть ли какой-нибудь трюк с MSBuild, который мне не хватает, который мог бы помочь мне здесь?Я не против включения в эту задачу пользовательской задачи, но предпочел бы по возможности простое решение MSBuild.

Если это имеет значение, я использую MSBuild v4.

1 Ответ

4 голосов
/ 02 февраля 2011

Ах. Наткнулся на и ответ, играя с этим.

Во-первых, я исследовал этот пост на предмет пересечения двух групп предметов. Поэтому я изменил свою группу элементов OutputNames, чтобы иметь ту же идентичность, что и для группы элементов OutputProjects:

<OutputNames Include="$(MSBuildProjectDirectory)\Solution1\Project1A\Project1A.csproj">
  <OutputFolder>ArbitraryFolder1</OutputFolder>
</OutputNames>
<OutputNames Include="$(MSBuildProjectDirectory)\Solution2\Project2B\Project2B.csproj">
  <OutputFolder>ArbitraryFolder2</OutputFolder>
</OutputNames>

Это позволило мне дозировать% (Identity) и получить пересечение как это:

<Message Condition="'%(Identity)' != '' and
         '@(OutputProjects)' != '' and
         '@(OutputNames)' != ''"
         Text="Found a match for %(Identity)" />

Однако при обращении к метаданным OutputFolder в той же задаче, которая также стала частью пакетной обработки, в результате никогда не будет печататься следующее:

<Message Condition="'%(Identity)' != '' and
         '@(OutputProjects)' != '' and
         '@(OutputNames)' != ''"
         Text="Found a match for %(Identity): %(OutputNames.OutputFolder)" />

Но, используя преобразование над свойством вместо прямого доступа, оно не рассматривается как часть пакетирования:

<Message Condition="'%(Identity)' != '' and
         '@(OutputProjects)' != '' and
         '@(OutputNames)' != ''"
         Text="Found a match for %(Identity): @(OutputNames->'%(OutputFolder)')" />

Поэтому для обновления метаданных я могу сделать следующее:

  <!-- Now override specific projects OutputTo metadata -->
  <OutputProjects Condition="'%(Identity)' != '' AND
                             '@(OutputProjects)' != '' AND
                             '@(OutputNames)' != ''">
    <OutputTo>@(OutputNames->'%(OutputFolder)')</OutputTo>
  </OutputProjects>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...