Замените .sln на MSBuild и оберните содержащиеся проекты в цели - PullRequest
11 голосов
/ 18 марта 2010

Я хотел бы создать проект MSBuild, который отражает зависимости проекта в решении и оборачивает проекты VS в повторно используемые цели.

Проблема, которую мне нравится решать, заключается в том, чтобы выполнить svn-export, собрать и развернуть конкретную сборку (и ее зависимости) в приложении BizTalk.

Мой вопрос : Как я могу сделать цели для svn-экспорта, построения и развертывания повторно используемыми, а также повторно использовать упакованные проекты, когда они созданы для разных зависимостей?

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

Детали

Проект, который я хотел бы развернуть

<Project DefaultTargets="Deploy" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
    <PropertyGroup>
        <ExportRoot Condition="'$(Export)'==''">Export</ExportRoot>
    </PropertyGroup>

    <Target Name="Clean_Export">
        <RemoveDir Directories="$(ExportRoot)\My.Project.Dir" />
    </Target>

    <Target Name="Export_MyProject">
        <Exec Command="svn export svn://xxx/trunk/Biztalk2009/MyProject.btproj --force" WorkingDirectory="$(ExportRoot)" />
    </Target>

    <Target Name="Build_MyProject" DependsOnTargets="Export_MyProject">
        <MSBuild Projects="$(ExportRoot)\My.Project.Dir\MyProject.btproj" Targets="Build" Properties="Configuration=Release"></MSBuild>
    </Target>

    <Target Name="Deploy_MyProject" DependsOnTargets="Build_MyProject">
        <Exec Command="BTSTask AddResource -ApplicationName:CORE -Source:MyProject.dll" />
    </Target>
</Project>

Проекты, от которых это зависит, выглядят почти так же (другие .btproj и .csproj).

1 Ответ

16 голосов
/ 19 марта 2010

Ух ты, это загруженный вопрос для поста на форуме. Я написал около 20 страниц о создании многократно используемых файлов .targets в моей книге , но я начну с основ здесь. Я считаю, что ключ к созданию повторно используемых скриптов сборки (т.е. файлов .targets) состоит из трех элементов:

  • Поместить поведение (, т.е. цели ) в отдельные файлы
  • Поместите данные (, т.е. свойства и элементы, они называются .proj файлами ) в свои собственные файлы
  • Расширяемость
  • .targets файлы должны проверять предположения

Идея состоит в том, что вы хотите поместить все свои цели в отдельные файлы, и затем эти файлы будут импортированы файлами, которые будут управлять процессом сборки. Это файлы, которые содержат данные. Поскольку вы импортируете файлы .targets, вы получаете все цели, как если бы они были определены внутри строки. Между файлами .proj и .targets будет заключен молчаливый договор. Этот контракт определен в свойствах и предметах, которые оба используют. Это то, что должно быть проверено.

Идея здесь не нова. За этим шаблоном следует .csproj (и другие проекты, созданные Visual Studio). Если вы посмотрите свой файл .csproj, вы не найдете ни одной цели, только свойства и элементы. Затем в конец файла импортируется файл Microsoft.csharp.targets ( может отличаться в зависимости от типа проекта ). Этот файл проекта ( вместе с другими импортируемыми ) содержит все цели, которые фактически выполняют сборку.

Итак, это выложено так:

  • SharedBuild.targets
  • MyProduct.proj

Где MyProdcut.proj может выглядеть так:

<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <!-- This uses a .targets file to off load performing the build -->
  <PropertyGroup>
    <Configuration Condition=" '$(Configuration)'=='' ">Release</Configuration>
    <OutputPath Condition=" '$(OutputPath)'=='' ">$(MSBuildProjectDirectory)\BuildArtifacts\bin\</OutputPath>
  </PropertyGroup>

  <ItemGroup>
    <Projects Include="$(MSBuildProjectDirectory)\..\ClassLibrary1\ClassLibrary1.csproj"/>
    <Projects Include="$(MSBuildProjectDirectory)\..\ClassLibrary2\ClassLibrary2.csproj"/>
    <Projects Include="$(MSBuildProjectDirectory)\..\ClassLibrary3\ClassLibrary3.csproj"/>
    <Projects Include="$(MSBuildProjectDirectory)\..\WindowsFormsApplication1\WindowsFormsApplication1.csproj"/>
  </ItemGroup>

  <Import Project="SharedBuild.targets"/>
</Project>

И SharedBuild.targets может выглядеть так:

<Project  DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <!-- This represents a re-usable build file -->
  <Target Name="SharedBuild_Validate">
    <!-- See http://sedodream.com/2009/06/30/ElementsOfReusableMSBuildScriptsValidation.aspx for more info
         about this validation pattern
    -->
    <ItemGroup>
      <_RequiredProperties Include ="Configuration">
          <Value>$(Configuration)</Value>
      </_RequiredProperties>    
      <_RequiredProperties Include ="OutputPath">
          <Value>$(OutputPath)</Value>
      </_RequiredProperties>

      <_RequiredItems Include="Projects">
        <RequiredValue>%(Projects.Identity)</RequiredValue>
        <RequiredFilePath>%(Projects.Identity)</RequiredFilePath>
      </_RequiredItems>
    </ItemGroup>

    <!-- Raise an error if any value in _RequiredProperties is missing -->
    <Error Condition="'%(_RequiredProperties.Value)'==''"
           Text="Missing required property [%(_RequiredProperties.Identity)]"/>

    <!-- Raise an error if any value in _RequiredItems is empty -->
    <Error Condition="'%(_RequiredItems.RequiredValue)'==''"
           Text="Missing required item value [%(_RequiredItems.Identity)]" />

    <!-- Validate any file/directory that should exist -->
    <Error Condition="'%(_RequiredItems.RequiredFilePath)' != '' and !Exists('%(_RequiredItems.RequiredFilePath)')"
           Text="Unable to find expeceted path [%(_RequiredItems.RequiredFilePath)] on item [%(_RequiredItems.Identity)]" />
  </Target>

  <PropertyGroup>
    <BuildDependsOn>
      SharedBuild_Validate;
      BeforeBuild;
      CoreBuild;
      AfterBuild;
    </BuildDependsOn>
  </PropertyGroup>
  <Target Name="Build" DependsOnTargets="$(BuildDependsOn)"/>
  <Target Name="BeforeBuild"/>
  <Target Name="AfterBuild"/>
  <Target Name="CoreBuild">
    <!-- Make sure output folder exists -->
    <PropertyGroup>
      <_FullOutputPath>$(OutputPath)$(Configuration)\</_FullOutputPath>
    </PropertyGroup>
    <MakeDir Directories="$(_FullOutputPath)"/>
    <MSBuild Projects="@(Projects)"
             BuildInParallel="true"
             Properties="OutputPath=$(_FullOutputPath)"/>
  </Target>
</Project>

Не смотрите слишком много на цель SharedBuild_Validate. Я добавил это для полноты, но не зацикливался на этом. Вы можете найти больше информации об этом в моем блоге на http://sedodream.com/2009/06/30/ElementsOfReusableMSBuildScriptsValidation.aspx.

Важными частями, на которые следует обратить внимание, являются точки расширяемости. Несмотря на то, что это очень простой файл, он содержит все компоненты многократно используемого файла .targets. Вы можете настроить его поведение, передавая различные свойства и элементы для сборки. Вы можете расширить его поведение, переопределив цель (BeforeBuild, AfterBuild или даже CoreBuild), и вы можете добавить свои собственные цели в сборку с помощью:

<Project ...>
   ...
  <Import Project="SharedBuild.targets"/>
  <PropertyGroup>
    <BuildDependsOn>
      $(BuildDependsOn);
      CustomAfterBuild
    </BuildDependsOn>
  </PropertyGroup>
  <Target Name="CustomAfterBuild">
    <!-- Insert stuff here -->
  </Target>
</Project>

В вашем случае я бы создал файл SvnExport.targets, который использует необходимые свойства:

  • SvnExportRoot
  • SvnUrl
  • SvnWorkingDirectory Вы будете использовать эти свойства для экспорта.

Затем создайте еще один для сборки и развертывания Biztalk. Вы можете разделить это на 2, если это необходимо.

Затем внутри вашего .proj-файла вы просто импортируете оба и настраиваете цели для построения в правильном порядке, а затем выключаете.

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

UPDATE:

Опубликовано в блог на http://sedodream.com/2010/03/19/ReplacingSolutionFilesWithMSBuildFiles.aspx

...