Общие сведения о процессе сборки

Джейсон Ли

В этом разделе представлено пошаговое руководство по сборке и развертыванию корпоративного масштаба. Подход, описанный в этом разделе, использует пользовательские файлы проекта Microsoft Build Engine (MSBuild) для обеспечения точного контроля над каждым аспектом процесса. В файлах проекта пользовательские целевые объекты MSBuild используются для запуска служебных программ развертывания, таких как средство веб-развертывания служб IIS (MSDeploy.exe) и служебная программа развертывания базы данных VSDBCMD.exe.

Замечание

В предыдущем разделе описаны основные компоненты файла проекта MSBuild и представлена концепция разделения файлов проекта для поддержки развертывания в нескольких целевых средах. Если вы еще не знакомы с этими понятиями, прежде чем работать с этим разделом, ознакомьтесь с разделом "Общие сведения о файле проекта ".

Этот раздел является частью серии учебников, основанных на требованиях к развертыванию предприятия вымышленной компании Fabrikam, Inc. В этой серии учебников используется пример решения — решение Contact Manager— для представления веб-приложения с реалистичным уровнем сложности, включая приложение MVC 3 ASP.NET MVC 3, службу Windows Communication Foundation (WCF) и проект базы данных.

Метод развертывания в центре этих учебников основан на подходе к разделенному файлу проекта, описанному в разделе "Общие сведения о файле проекта", в котором процесс сборки управляется двумя файлами проекта — одним из них содержит инструкции по сборке, которые применяются к каждой целевой среде, а также один из них содержит параметры сборки и развертывания для конкретной среды. Во время сборки файл проекта для конкретной среды объединяется в файл проекта, не зависящем от среды, чтобы сформировать полный набор инструкций по сборке.

Общие сведения о сборке и развертывании

В решении Диспетчера контактов три файла управляют процессом сборки и развертывания:

  • Универсальный файл проекта (Publish.proj). Это содержит инструкции по сборке и развертыванию, которые не изменяются между целевыми средами.
  • Файл проекта для конкретной среды (Env-Dev.proj). Это содержит параметры сборки и развертывания, относящиеся к определенной целевой среде. Например, можно использовать файл Env-Dev.proj для предоставления параметров для среды разработчика или тестирования и создания альтернативного файла с именем Env-Stage.proj для предоставления параметров промежуточной среды.
  • Файл команды (Publish-Dev.cmd). Это содержит команду MSBuild.exe, которая указывает, какие файлы проекта необходимо выполнить. Вы можете создать файл команд для каждой целевой среды, где каждый файл содержит команду MSBuild.exe, указывающую другой файл проекта для конкретной среды. Это позволяет разработчику развертывать в разных средах, просто выполнив соответствующий файл команды.

В примере решения эти три файла можно найти в папке "Публикация решения".

В примере решения можно найти три файла в папке

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

Как выглядит процесс сборки и развертывания на высоком уровне.

Первое, что происходит, заключается в том, что два файла проекта , содержащие универсальные инструкции по сборке и развертыванию, а также один, содержащий параметры среды, объединяются в один файл проекта. Затем MSBuild работает с инструкциями в файле проекта. Он создает каждый из проектов в решении, используя файл проекта для каждого проекта. Затем он вызывает другие средства, такие как веб-развертывание (MSDeploy.exe) и служебную программу VSDBCMD для развертывания веб-содержимого и баз данных в целевой среде.

С самого начала процесс сборки и развертывания выполняет следующие задачи:

  1. Он удаляет содержимое выходного каталога при подготовке к новой сборке.

  2. Он создает каждый проект в решении:

    1. Для веб-проектов (в данном случае веб-приложение ASP.NET MVC и веб-служба WCF) процесс сборки создает пакет веб-развертывания для каждого проекта.
    2. Для проектов базы данных процесс сборки создает манифест развертывания (файл.deploymanifest) для каждого проекта.
  3. Она использует программу VSDBCMD.exe для развертывания каждого проекта базы данных в решении, используя различные свойства из файлов проекта — целевую строку подключения и имя базы данных вместе с файлом deploymanifest.

  4. Она использует программу MSDeploy.exe для развертывания каждого веб-проекта в решении, используя различные свойства из файлов проекта для управления процессом развертывания.

Пример решения можно использовать для более подробной трассировки этого процесса.

Замечание

Инструкции по настройке файлов проекта конкретной среды для собственных серверных сред см. в разделе "Настройка свойств развертывания для целевой среды".

Вызов процесса сборки и развертывания

Чтобы развернуть решение Contact Manager в тестовой среде разработчика, разработчик запускает файл команды Publish-Dev.cmd . Это вызывает MSBuild.exe, указывая Publish.proj в качестве файла проекта для выполнения и Env-Dev.proj в качестве значения параметра.

msbuild.exe Publish.proj /fl /p:TargetEnvPropsFile=EnvConfig\Env-Dev.proj

Замечание

Параметр /fl (short for /fileLogger) записывает выходные данные сборки в файл с именем msbuild.log в текущем каталоге. Дополнительные сведения см. в справочнике по командной строке MSBuild.

На этом этапе MSBuild запускается, загружает файл Publish.proj и начинает обработку инструкций в нем. Первая инструкция инструктирует MSBuild импортировать файл проекта, указанный параметром TargetEnvPropsFile.

<Import Project="$(TargetEnvPropsFile)" />

Параметр TargetEnvPropsFile указывает файл Env-Dev.proj , поэтому MSBuild объединяет содержимое файла Env-Dev.proj в файл Publish.proj .

Следующими элементами MSBuild, встречающимися в объединенном файле проекта, являются группы свойств. Свойства обрабатываются в порядке, в котором они отображаются в файле. MSBuild создает пару "ключ-значение" для каждого свойства, обеспечивая соблюдение всех указанных условий. Свойства, определенные позже в файле, перезаписывают все свойства с тем же именем, определенным ранее в файле. Например, рассмотрим свойства OutputRoot .

<OutputRoot Condition=" '$(OutputRoot)'=='' ">..\Publish\Out\</OutputRoot>
<OutputRoot Condition=" '$(BuildingInTeamBuild)'=='true' ">$(OutDir)</OutputRoot>

Когда MSBuild обрабатывает первый элемент OutputRoot и аналогичный именованный параметр не предоставлен, оно устанавливает значение свойства OutputRoot в ..\Publish\Out. При обнаружении второго элемента OutputRoot, если условие истинно true, оно заменяет значение свойства OutputRoot значением параметра OutDir.

Следующий элемент, с которыми сталкивается MSBuild, является одной группой элементов, содержащей элемент с именем ProjectsToBuild.

<ItemGroup>
   <ProjectsToBuild Include="$(SourceRoot)ContactManager-WCF.sln"/>
</ItemGroup>

MSBuild обрабатывает эту инструкцию путем создания списка элементов с именем ProjectsToBuild. В этом случае список элементов содержит одно значение — путь и имя файла решения.

На этом этапе остальные элементы являются целевыми объектами. Целевые объекты обрабатываются по-разному от свойств и элементов. По сути, целевые объекты не обрабатываются, если только они не заданы пользователем или вызваны другой конструкцией в файле проекта. Помните, что открывающий тег Project содержит атрибут DefaultTargets .

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

Это указывает MSBuild вызывать целевой объект FullPublish , если целевые объекты не указаны при вызове MSBuild.exe. Целевой объект FullPublish не содержит никаких задач; Вместо этого он просто задает список зависимостей.

<PropertyGroup>   
  <FullPublishDependsOn>
     Clean;
     BuildProjects;      
     GatherPackagesForPublishing;
     PublishDbPackages;
     PublishWebPackages;
  </FullPublishDependsOn>
</PropertyGroup>
<Target Name="FullPublish" DependsOnTargets="$(FullPublishDependsOn)" />

Эта зависимость сообщает MSBuild, что для выполнения целевого объекта FullPublish необходимо вызвать этот список целевых объектов в указанном порядке:

  1. Он должен вызывать целевой объект Clean .
  2. Он должен вызывать целевой объект BuildProjects .
  3. Он должен вызывать целевой объект GatherPackagesForPublishing .
  4. Он должен вызывать целевой объект PublishDbPackages .
  5. Он должен вызывать целевой объект PublishWebPackages .

Очищенная цель

Целевой объект Clean в основном удаляет выходной каталог и все его содержимое в качестве подготовки к новой сборке.

<Target Name="Clean" Condition=" '$(BuildingInTeamBuild)'!='true' ">
  <Message Text="Cleaning up the output directory [$(OutputRoot)]"/>
  <ItemGroup>
     <_FilesToDelete Include="$(OutputRoot)**\*"/>
  </ItemGroup>
  <Delete Files="@(_FilesToDelete)"/>
  <RemoveDir Directories="$(OutputRoot)"/>
</Target>

Обратите внимание, что целевой объект включает элемент ItemGroup . При определении свойств или элементов в элементе Target создается динамические свойства и элементы. Другими словами, свойства или элементы не обрабатываются, пока целевой объект не будет выполнен. Выходной каталог может не существовать или содержать файлы до начала процесса сборки, поэтому невозможно создать список _FilesToDelete как статический элемент; Необходимо ждать, пока выполняется выполнение. Таким образом, вы создаете список как динамический элемент в целевом объекте.

Замечание

В этом случае, так как целевой объект Clean является первым для выполнения, не требуется использовать динамическую группу элементов. Однако рекомендуется использовать динамические свойства и элементы в этом типе сценария, так как может потребоваться выполнить целевые объекты в другом порядке в какой-то момент.
Вы также должны стремиться избежать объявления элементов, которые никогда не будут использоваться. Если у вас есть элементы, которые будут использоваться только определенным целевым объектом, рассмотрите возможность размещения их внутри целевого объекта, чтобы удалить ненужные затраты на процесс сборки.

Динамические элементы в стороне, целевой объект Clean довольно прост и использует встроенные задачи Message, Delete и RemoveDir для:

  1. Отправьте сообщение средству ведения журнала.
  2. Создайте список файлов для удаления.
  3. Удалите файлы.
  4. Удалите выходной каталог.

Целевой объект BuildProjects

Целевой объект BuildProjects в основном создает все проекты в примере решения.

<Target Name="BuildProjects" Condition=" '$(BuildingInTeamBuild)'!='true' ">
   <MSBuild Projects="@(ProjectsToBuild)"
            Properties="OutDir=$(OutputRoot);
                        Configuration=$(Configuration);
                        DeployOnBuild=true;
                        DeployTarget=Package"
            Targets="Build" />
  </Target>

Этот целевой объект подробно описан в предыдущем разделе, в разделе "Общие сведения о файле проекта", чтобы иллюстрировать, как задачи и целевые объекты ссылаться на свойства и элементы. На этом этапе вы в основном заинтересованы в задаче MSBuild . Эту задачу можно использовать для создания нескольких проектов. Задача не создает новый экземпляр MSBuild.exe; он использует текущий запущенный экземпляр для сборки каждого проекта. Ключевыми моментами в этом примере являются свойства развертывания:

  • Свойство DeployOnBuild указывает MSBuild выполнить все инструкции по развертыванию в параметрах проекта при завершении сборки каждого проекта.
  • Свойство DeployTarget определяет целевой объект, который требуется вызвать после создания проекта. В этом случае целевой объект пакета создает выходные данные проекта в развертываемый веб-пакет.

Замечание

Целевой объект пакета вызывает конвейер веб-публикации (WPP), который обеспечивает интеграцию между MSBuild и веб-развертыванием. Если вы хотите просмотреть встроенные целевые объекты, которые предоставляет WPP, просмотрите файл Microsoft.Web.Publishing.targets в папке %PROGRAMFILES(x86)%\MSBuild\Microsoft\VisualStudio\v10.0\Web.

Целевой объект GatherPackagesForPublishing

Если вы изучаете целевой объект GatherPackagesForPublishing , вы заметите, что он фактически не содержит никаких задач. Вместо этого он содержит одну группу элементов, которая определяет три динамических элемента.

<Target Name="GatherPackagesForPublishing">
   <ItemGroup>
      <PublishPackages 
         Include="$(_ContactManagerDest)ContactManager.Mvc.deploy.cmd">
         <WebPackage>true</WebPackage>
         <!-- More item metadata -->  
      </PublishPackages>
      <PublishPackages 
         Include="$(_ContactManagerSvcDest)ContactManager.Service.deploy.cmd">
         <WebPackage>true</WebPackage>
         <!-- More item metadata -->
      </PublishPackages>
      <DbPublishPackages Include="$(_DbDeployManifestPath)">
         <DbPackage>true</DbPackage>
         <!-- More item metadata -->
      </DbPublishPackages>
   </ItemGroup>
</Target>

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

Элементы не используются в этом целевом объекте— этот целевой объект просто создает элементы и метаданные, связанные с каждым значением элемента. После обработки этих элементов элемент PublishPackages будет содержать два значения, путь к файлу ContactManager.Mvc.deploy.cmd и путь к файлу ContactManager.Service.deploy.cmd . Веб-развертывание создает эти файлы как часть веб-пакета для каждого проекта, и это файлы, которые необходимо вызвать на целевом сервере для развертывания пакетов. Если открыть один из этих файлов, вы в основном увидите команду MSDeploy.exe с различными значениями параметров для конкретной сборки.

Элемент DbPublishPackages будет содержать одно значение, путь к файлу ContactManager.Database.deploymanifest .

Замечание

Файл .deploymanifest создается при сборке проекта базы данных и использует ту же схему, что и файл проекта MSBuild. Она содержит все сведения, необходимые для развертывания базы данных, включая расположение схемы базы данных (DBschema) и подробные сведения о любых скриптах перед развертыванием и после развертывания. Дополнительные сведения см. в разделе "Общие сведения о сборке и развертывании базы данных".

Вы узнаете больше о том, как создаются и используются пакеты развертывания и манифесты развертывания баз данных в Создании и упаковке проектов веб-приложений и Развертывании проектов баз данных.

Целевой объект PublishDbPackages

Кратко говоря, целевой объект PublishDbPackages вызывает служебную программу VSDBCMD для развертывания базы данных ContactManager в целевой среде. Настройка развертывания базы данных включает в себя множество решений и нюансов, и вы узнаете больше об этом в развертывании проектов баз данных и настройке развертываний баз данных для нескольких сред. В этом разделе мы сосредоточимся на том, как этот целевой объект фактически функционирует.

Сначала обратите внимание, что открывающий тег содержит атрибут Outputs .

<Target Name="PublishDbPackages" Outputs="%(DbPublishPackages.Identity)">

Это пример целевой пакетной обработки. В файлах проекта MSBuild пакетная обработка — это способ итерации по коллекциям. Значение атрибута Outputs"%(DbPublishPackages.Identity)", ссылается на свойство метаданных Identity списка элементов DbPublishPackages. Эта нотация, Outputs=%(ItemList.ItemMetadataName), преобразуется как:

  • Разделите элементы в DbPublishPackages на партии элементов, содержащих одно и то же значение метаданных идентификатор.
  • Выполните цель один раз на каждую партию.

Замечание

Идентификатор — это одно из встроенных значений метаданных, назначенных каждому элементу при создании. Он ссылается на значение атрибута Include в элементе Item , другими словами, путь и имя файла элемента.

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

Вы можете увидеть аналогичную нотацию в свойстве _Cmd , которое создает команду VSDBCMD с соответствующими коммутаторами.

<_Cmd>"$(VsdbCmdExe)" 
   /a:Deploy 
   /cs:"%(DbPublishPackages.DatabaseConnectionString)" 
   /p:TargetDatabase=%(DbPublishPackages.TargetDatabase)             
   /manifest:"%(DbPublishPackages.FullPath)" 
   /script:"$(_CmDbScriptPath)" 
   $(_DbDeployOrScript)
</_Cmd>

В этом случае %(DbPublishPackages.DatabaseConnectionString),%(DbPublishPackages.TargetDatabase) и %(DbPublishPackages.FullPath) ссылаются на значения метаданных коллекции элементов DbPublishPackages. Свойство _Cmd используется задачей Exec , которая вызывает команду.

<Exec Command="$(_Cmd)"/>

В результате этой нотации задача Exec создаст пакеты на основе уникальных сочетаний значений метаданных DatabaseConnectionString, TargetDatabase и FullPath , а задача будет выполняться один раз для каждого пакета. Это пример пакетной обработки задач. Однако, поскольку пакетная обработка на уровне целевого уровня уже разделила коллекцию элементов на пакеты с одним элементом, задача Exec будет выполняться один раз и только один раз для каждой итерации целевого объекта. Другими словами, эта задача вызывает служебную программу VSDBCMD один раз для каждого пакета базы данных в решении.

Замечание

Дополнительные сведения о пакетной обработке целей и задач см. в статье MSBuild Batching, Метаданные элементов в пакетной обработке целей и метаданные элементов в пакетной обработке задач.

Целевой объект PublishWebPackages

К этому моменту вы вызвали целевой объект BuildProjects , который создает пакет веб-развертывания для каждого проекта в примере решения. Сопровождающий каждый пакет представляет собой файл deploy.cmd, содержащий команды MSDeploy.exe , необходимые для развертывания пакета в целевой среде, и файл SetParameters.xml , который указывает необходимые сведения о целевой среде. Вы также вызвали цель GatherPackagesForPublishing, которая создает коллекцию элементов с файлами deploy.cmd, которые вас интересуют. По сути, целевой объект PublishWebPackages выполняет следующие функции:

  • Он управляет файломSetParameters.xml для каждого пакета, чтобы включить правильные сведения для целевой среды с помощью задачи XmlPoke .
  • Он вызывает файл deploy.cmd для каждого пакета с помощью соответствующих коммутаторов.

Как и целевой объект PublishDbPackages , целевой объект PublishWebPackages использует пакетную обработку целевого объекта, чтобы убедиться, что целевой объект выполняется один раз для каждого веб-пакета.

<Target Name="PublishWebPackages" Outputs="%(PublishPackages.Identity)">

В целевом объекте задача Exec используется для запуска файла deploy.cmd для каждого веб-пакета.

<PropertyGroup>
   <_Cmd>
      %(PublishPackages.FullPath) 
      $(_WhatifSwitch) 
      /M:$(MSDeployComputerName) 
      %(PublishPackages.AdditionalMSDeployParameters)
   </_Cmd>
</PropertyGroup>
<Exec Command="$(_Cmd)"/>

Дополнительные сведения о настройке развертывания веб-пакетов см. в разделе "Создание и упаковка проектов веб-приложений".

Conclusion

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

Дальнейшее чтение

Более полное введение в файлы проектов и WPP смотрите в книге "Внутри ядра сборки Microsoft: использование MSBuild и Team Foundation Build", авторы Сайед Ибрагим Хашими и Уильям Бартоломью, ISBN: 978-0-7356-4524-0.