Пошаговое руководство. Использование MSBuild

MSBuild является платформой сборки для корпорации Майкрософт и Visual Studio. Это практическое руководство содержит вводную информацию о стандартных блоках MSBuild и описывает способы записи и отладки проектов MSBuild, а также управления ими. Здесь рассматриваются следующие вопросы:

  • создание файла проекта и работа с ним;

  • использование свойств сборки;

  • использование элементов сборки.

MSBuild можно запустить в Visual Studio или из командного окна. В этом пошаговом руководстве вы создадите файл проекта MSBuild с помощью Visual Studio. Вы отредактируете файл проекта в Visual Studio и с помощью командного окна выполните сборку проекта и просмотрите результаты.

Установка MSBuild

Если у вас есть Visual Studio, то MSBuild уже установлен. Чтобы установить MSBuild 15 в системе, не имеющей Visual Studio, перейдите на страницу загрузки более ранних версий Visual Studio, разверните пункт Visual Studio 2017 и нажмите кнопку Загрузить. Если у вас есть подписка Visual Studio, выполните вход и найдите ссылку для загрузки последней версии Build Tools для Visual Studio 2017. Если у вас нет подписки Visual Studio, вы по-прежнему можете установить последнюю версию средств сборки. На этой странице с помощью средства выбора версии переключитесь на страницу для версии 2019 и следуйте инструкциям по установке.

Если у вас есть Visual Studio, то MSBuild уже установлен. В Visual Studio 2019 средства сборки устанавливаются в папку установки Visual Studio. Для обычной установки по умолчанию в Windows 10 файл MSBuild.exe находится в папке установки MSBuild\Current\Bin.

Чтобы установить MSBuild в системе без Visual Studio, перейдите на страницу загрузки Visual Studio и прокрутите вниз до пункта Все загрузки, а затем разверните Средства для Visual Studio 2019. Установите Build Tools для Visual Studio 2019, которые включают в себя MSBuild, или установите пакет SDK для .NET Core.

Убедитесь, что в установщике выбраны средства MSBuild для используемых рабочих нагрузок, затем нажмите кнопку Установить.

Установка MSBuild

Создание проекта MSBuild

Система проектов Visual Studio основана на MSBuild. Это упрощает создание файла проекта с помощью Visual Studio. В этом разделе создается файл проекта Visual C#. Вместо него можно выбрать создание файла проекта Visual Basic. В контексте данного пошагового руководства различия между двумя файлами проекта незначительны.

Создание файла проекта

  1. Откройте Visual Studio и создайте проект.

    Нажмите клавишу ESC, чтобы закрыть окно запуска. Напечатайте Ctrl + Q, чтобы открыть поле поиска, введите winforms, затем выберите Create a new Windows Forms App (.NET Framework) (Создать новое приложение Windows Forms (.NET Framework)). В появившемся диалоговом окне выберите Создать.

    В поле Имя файла введите BuildApp. Введите расположение решения, например D:\ . Примите значения по умолчанию для Решение, Имя решения (BuildApp) и Платформа.

    В верхней строке меню последовательно выберите Файл  > Создать  > Проект. На левой панели диалогового окна Новый проект разверните узел Visual C# > Классическое приложение Windows и выберите Приложение Windows Forms (.NET Framework) . Затем нажмите ОК.

    В поле Имя файла введите BuildApp. Введите расположение решения, например D:\ . Примите параметры по умолчанию Создать каталог для решения (выбран), Добавить в систему управления версиями (не выбран) и Имя решения (BuildApp).

  2. Щелкните ОК или Создать, чтобы создать файл проекта.

Анализ файла проекта

В предыдущем разделе вы использовали Visual Studio для создания файла проекта Visual C#. Файл проекта представлен в обозревателе решений узлом проекта с именем BuildApp. Чтобы проанализировать файл проекта, можно использовать редактор кода Visual Studio.

Анализ файла проекта

  1. В обозревателе решений выберите узел проекта BuildApp.

  2. В браузере Свойства обратите внимание, что свойство Файл проекта имеет значение BuildApp.csproj. В именах всех файлов проектов указан суффикс proj. Если вы создали проект Visual Basic, файлу проекта будет задано имя BuildApp.vbproj.

  3. Еще раз щелкните правой кнопкой мыши узел проекта, а затем выберите Изменить BuildApp.csproj.

    Файл проекта откроется в редакторе кода.

Примечание

Для некоторых типов проектов, например C++, необходимо выгрузить проект, прежде чем можно будет открыть и изменить файл проекта. Чтобы выгрузить проект, щелкните правой кнопкой мыши файл проекта и выберите Выгрузить проект.

Целевые объекты и задачи

Файлы проекта представляют собой файлы в формате XML с корневым узлом Проект.

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

Более новые проекты .NET Core (в стиле SDK) имеют атрибут Sdk.

<Project Sdk="Microsoft.NET.Sdk">

Для проектов не в стиле SDK необходимо указать пространство имен xmlns в элементе "Проект". Если ToolsVersion присутствует в новом проекте, он должен иметь значение "15.0".

Создание приложения выполняется с помощью элементов Целевой объект и Задача.

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

  • Целевой объект представляет собой именованную последовательность задач. Дополнительные сведения см. в статье о целевых объектах.

  • [это может быть именованная последовательность задач, но крайне важно то, что она представляет собой что-то, что должно быть создано или выполнено, поэтому ее необходимо определить с помощью подхода, ориентированного на цели]

Целевой объект по умолчанию не определен в файле проекта. Вместо этого он задан в импортированных проектах. Элемент Import указывает импортированные проекты. Например, в проекте C# целевой объект по умолчанию импортируется из файла Microsoft.CSharp.targets.

<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />

Импортированные файлы вставляются в файл проекта везде, где на них указывает ссылка.

В проектах в стиле SDK вы не увидите этого элемента Import, так как атрибут SDK приводит к неявному импорту этого файла.

MSBuild отслеживает целевые объекты сборки и гарантирует, что каждый целевой объект будет построен не более одного раза.

Добавление целевого объекта и задачи

Добавьте целевой объект в файл проекта. Добавьте задачу в целевой объект, который выводит сообщение.

Добавление целевого объекта и задачи

  1. Добавьте следующие строки в файл проекта сразу после оператора Import:

    <Target Name="HelloWorld">
    </Target>
    

    Будет создан целевой объект с именем HelloWorld. Обратите внимание, что во время редактирования файла проекта доступна поддержка IntelliSense.

  2. Добавьте строки в целевой объект HelloWorld, чтобы в результате раздел выглядел следующим образом:

    <Target Name="HelloWorld">
      <Message Text="Hello"></Message>  <Message Text="World"></Message>
    </Target>
    
  3. Сохраните файл проекта.

Задача Message является одной из многих, входящих в комплект поставки MSBuild. Полный список доступных задач и сведения об их использовании см. в статье Справочные сведения о задачах MSBuild.

Задача Message принимает строковое значение атрибута Text в качестве входных данных и отображает его в устройстве вывода (или записывает его в один или несколько журналов, если применимо). Целевой объект HelloWorld выполняет задачу Message дважды: сначала для отображения Hello, а затем для отображения World.

Создание целевого объекта

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

Запустите MSBuild из командной строки разработчика для Visual Studio, чтобы создать целевой объект HelloWorld, определенный выше. Используйте параметр -target или -t для выбора целевого объекта.

Примечание

В следующих разделах мы будем называть командную строку разработчика командным окном.

Создание целевого объекта

  1. Откройте командное окно.

    (Windows 10) В поле поиска на панели задач начните вводить имя средства, например dev или developer command prompt. Откроется список установленных приложений, которые соответствуют вашему шаблону поиска.

    Если вам нужно найти средство вручную, найдите файл LaunchDevCmd.bat в папке <папка установки Visual Studio><version>\Common7\Tools.

  2. В командном окне перейдите в папку, содержащую файл проекта. В данном случае это D:\BuildApp\BuildApp.

  3. Выполните команду msbuild с параметром -t:HelloWorld. Будет выбран и создан целевой объект HelloWorld:

    msbuild buildapp.csproj -t:HelloWorld
    
  4. Изучите выходные данные в окне командной строки. Вы должны увидеть две строки — Hello и World:

    Hello
    World
    

Примечание

Если вместо них вы видите The target "HelloWorld" does not exist in the project, возможно, вы забыли сохранить файл проекта в редакторе кода. Сохраните файл и повторите попытку.

Переключаясь между редактором кода и командной строкой, можно изменять файл проекта и сразу же видеть результаты.

Свойства сборки

Свойства сборки являются парами "имя — значение", управляющими сборкой. В верхней части файла проекта уже определено несколько свойств сборки:

<PropertyGroup>
...
  <ProductVersion>10.0.11107</ProductVersion>
  <SchemaVersion>2.0</SchemaVersion>
  <ProjectGuid>{30E3C9D5-FD86-4691-A331-80EA5BA7E571}</ProjectGuid>
  <OutputType>WinExe</OutputType>
...
</PropertyGroup>

Все свойства являются дочерними элементами по отношению к элементам PropertyGroup. Имя свойства — это имя дочернего элемента, а значение свойства — это текстовый элемент дочернего элемента. Например, примененная к объекту директива

<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>

определяет свойство с именем TargetFrameworkVersion, задавая ему строковое значение "v4.5".

Свойства сборки можно переопределить в любое время. If

<TargetFrameworkVersion>v3.5</TargetFrameworkVersion>

появляется далее в файле проекта или в файле, позже импортированном в файл проекта, свойство TargetFrameworkVersion принимает новое значение v3.5.

Анализ значения свойства

Чтобы получить значение свойства, используйте следующий синтаксис, где PropertyName — имя свойства:

$(PropertyName)

С помощью этого синтаксиса проанализируйте некоторые свойства в файле проекта.

Анализ значения свойства

  1. В редакторе кода замените целевой объект HelloWorld следующим кодом:

    <Target Name="HelloWorld">
      <Message Text="Configuration is $(Configuration)" />
      <Message Text="MSBuildToolsPath is $(MSBuildToolsPath)" />
    </Target>
    
  2. Сохраните файл проекта.

  3. В командном окне введите и выполните следующую строку:

    msbuild buildapp.csproj -t:HelloWorld
    
  4. Проанализируйте результат. Вы должны увидеть следующие две строки (ваша версия .NET Framework может быть другой):

    Configuration is Debug
    MSBuildToolsPath is C:\Program Files (x86)\Microsoft Visual Studio\2019\<Visual Studio SKU>\MSBuild\15.0\Bin
    
    Configuration is Debug
    MSBuildToolsPath is C:\Program Files (x86)\Microsoft Visual Studio\2017\<Visual Studio SKU>\MSBuild\15.0\Bin
    

Условные свойства

Многие свойства, например Configuration, определяются условно, то есть в элементе свойства отображается атрибут Condition. Условные свойства определяются или переопределяются только в том случае, если условие принимает значение true. Обратите внимание, что неопределенные свойства получают значение по умолчанию — пустую строку. Например, примененная к объекту директива

<Configuration   Condition=" '$(Configuration)' == '' ">Debug</Configuration>

означает: "Если свойство Configuration еще не определено, определите его и присвойте ему значение Debug".

Атрибут Condition может быть почти у всех элементов MSBuild. Дополнительные сведения об использовании атрибута Condition см. в статье об условиях.

Зарезервированные свойства

MSBuild резервирует некоторые имена свойств для хранения сведений о файле проекта и двоичных файлах MSBuild. Примером зарезервированного свойства является MSBuildToolsPath. Зарезервированные свойства указываются с символом $, как и любое другое свойство. Дополнительные сведения см. в разделе Практическое руководство. Использование ссылки на имя или расположение файла проекта и Зарезервированные и стандартные свойства MSBuild.

Переменные среды

Ссылаться на переменные среды в файлах проектов можно так же, как на свойства сборки. Например, чтобы использовать переменную среды PATH в файле проекта, примените $(Path). Если проект содержит определение свойства с тем же именем, что и у переменной среды, свойство в проекте переопределит значение переменной среды. Дополнительные сведения см. в разделе Практическое руководство. Использование переменных среды в построении.

Задание свойств из командной строки

Свойства можно определить в командной строке с помощью параметра -property или -p. Значения свойств, полученные из командной строки, переопределяют значения свойств, заданные в файле проекта и переменных среды.

Настройка значения свойства из командной строки

  1. В командном окне введите и выполните следующую строку:

    msbuild buildapp.csproj -t:HelloWorld -p:Configuration=Release
    
  2. Проанализируйте результат. Вы должны увидеть следующую строку:

    Configuration is Release.
    

MSBuild создает свойство Configuration и присваивает ему значение Release.

Специальные символы

Некоторые символы имеют особое значение в файлах проекта MSBuild. К ним относятся точка с запятой (;) и звездочка (*). Чтобы использовать эти специальные символы в качестве литералов в файле проекта, их необходимо задать с помощью синтаксиса %<xx>, где <xx> представляет шестнадцатеричное значение ASCII символа.

Измените задачу Message, чтобы отображать значение свойства Configuration со специальными символами для удобства чтения.

Использование специальных символов в задаче Message

  1. В редакторе кода замените обе задачи Message следующей строкой:

    <Message Text="%24(Configuration) is %22$(Configuration)%22" />
    
  2. Сохраните файл проекта.

  3. В командном окне введите и выполните следующую строку:

    msbuild buildapp.csproj -t:HelloWorld
    
  4. Проанализируйте результат. Вы должны увидеть следующую строку:

    $(Configuration) is "Debug"
    

Дополнительные сведения см. в статье Специальные символы в MSBuild.

Элементы сборки

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

Все элементы являются дочерними элементами по отношению к элементам ItemGroup. Именем элемента является имя дочернего элемента, а значением — значение атрибута Include дочернего элемента. Значения элементов с одинаковым именем собираются в типы элементов с таким именем. Например, примененная к объекту директива

<ItemGroup>
    <Compile Include="Program.cs" />
    <Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>

определяет группу элементов, содержащую два элемента. Тип элемента Compile имеет два значения: Program.cs и Properties\AssemblyInfo.cs.

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

<ItemGroup>
    <Compile Include="Program.cs;Properties\AssemblyInfo.cs" />
</ItemGroup>

Дополнительные сведения см. в разделе Элементы.

Примечание

Пути к файлам задаются относительно папки, содержащей файл проекта MSBuild, даже если файл проекта является импортированным. Существует несколько исключений, например при использовании элементов Import и UsingTask.

Анализ значений типа элемента

Чтобы получить значения типа элемента, используйте следующий синтаксис, где ItemType — это имя типа элемента:

@(ItemType)

С помощью этого синтаксиса проанализируйте тип элемента Compile в файле проекта.

Анализ значений типа элемента

  1. В редакторе кода замените целевую задачу HelloWorld следующим кодом:

    <Target Name="HelloWorld">
      <Message Text="Compile item type contains @(Compile)" />
    </Target>
    
  2. Сохраните файл проекта.

  3. В командном окне введите и выполните следующую строку:

    msbuild buildapp.csproj -t:HelloWorld
    
  4. Проанализируйте результат. Вы должны увидеть следующую строку:

    Compile item type contains Form1.cs;Form1.Designer.cs;Program.cs;Properties\AssemblyInfo.cs;Properties\Resources.Designer.cs;Properties\Settings.Designer.cs
    

По умолчанию значения типа элемента разделены точкой с запятой.

Чтобы изменить разделитель типа элемента, используйте следующий синтаксис, где ItemType — это тип элемента, а Separator — это строка из одного или нескольких разделительных символов:

@(ItemType, Separator)

Измените задачу Message для использования символов возврата каретки и перевода строки (%0A%0D) для отображения элементов Compile по одному в строке.

Отображение значений типов элементов по одному в строке

  1. В редакторе кода замените задачу Message следующей строкой:

    <Message Text="Compile item type contains @(Compile, '%0A%0D')" />
    
  2. Сохраните файл проекта.

  3. В командном окне введите и выполните следующую строку:

    msbuild buildapp.csproj -t:HelloWorld
    
  4. Проанализируйте результат. Должны отобразиться следующие строки:

    Compile item type contains Form1.cs
    Form1.Designer.cs
    Program.cs
    Properties\AssemblyInfo.cs
    Properties\Resources.Designer.cs
    Properties\Settings.Designer.cs
    

Атрибуты Include, Exclude и подстановочные знаки

Можно использовать подстановочные знаки "*", "**" и "?" с атрибутом Include, чтобы добавить элементы к типу элемента. Например, примененная к объекту директива

<Photos Include="images\*.jpeg" />

добавляет все файлы с расширением файла .jpeg в папке изображений к типу элемента Photos, тогда как

<Photos Include="images\**\*.jpeg" />

добавляет все файлы с расширением файла .jpeg в папке изображений и всех ее вложенных папках к типу элемента Photos. Дополнительные примеры см. в статье Практическое руководство. Выбор файлов для сборки.

Обратите внимание, что, так как элементы объявлены, они добавляются к типу элемента. Например, примененная к объекту директива

<Photos Include="images\*.jpeg" />
<Photos Include="images\*.gif" />

создает тип элемента Photo, содержащий все файлы в папке изображений с расширением .jpeg или .gif. Это эквивалентно следующей строке:

<Photos Include="images\*.jpeg;images\*.gif" />

С помощью атрибута Exclude можно исключить элемент из типа элемента. Например, примененная к объекту директива

<Compile Include="*.cs" Exclude="*Designer*">

добавляет все файлы с расширением .cs в тип элемента Compile, за исключением файлов, имена которых содержат строку Designer. Дополнительные примеры см. в статье Практическое руководство. Исключение файлов из сборки.

Атрибут Exclude применяется только к элементам, добавленным с помощью атрибута Include в элемент, содержащий их оба. Например, примененная к объекту директива

<Compile Include="*.cs" />
<Compile Include="*.res" Exclude="Form1.cs">

не исключит файл Form1.cs, добавленный в предыдущий элемент.

Включение и исключение элементов

  1. В редакторе кода замените задачу Message следующей строкой:

    <Message Text="XFiles item type contains @(XFiles)" />
    
  2. Добавьте эту группу элементов сразу после элемента Import:

    <ItemGroup>
       <XFiles Include="*.cs;properties/*.resx" Exclude="*Designer*" />
    </ItemGroup>
    
  3. Сохраните файл проекта.

  4. В командном окне введите и выполните следующую строку:

    msbuild buildapp.csproj -t:HelloWorld
    
  5. Проанализируйте результат. Вы должны увидеть следующую строку:

    XFiles item type contains Form1.cs;Program.cs;Properties/Resources.resx
    

Метаданные элементов

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

Для объявления элементов в файле проекта создается элемент с именем метаданных, являющийся дочерним по отношению к элементу. Элемент может содержать нуль или более значений метаданных. Например, следующий элемент CSFile содержит метаданные Culture со значением Fr:

<ItemGroup>
    <CSFile Include="main.cs">
        <Culture>Fr</Culture>
    </CSFile>
</ItemGroup>

Чтобы получить значение метаданных типа элемента, используйте следующий синтаксис, где ItemType — это имя типа элементов, а MetaDataName — имя метаданных:

%(ItemType.MetaDataName)

Анализ метаданных элементов

  1. В редакторе кода замените задачу Message следующей строкой:

    <Message Text="Compile.DependentUpon: %(Compile.DependentUpon)" />
    
  2. Сохраните файл проекта.

  3. В командном окне введите и выполните следующую строку:

    msbuild buildapp.csproj -t:HelloWorld
    
  4. Проанализируйте результат. Должны отобразиться следующие строки:

    Compile.DependentUpon:
    Compile.DependentUpon: Form1.cs
    Compile.DependentUpon: Resources.resx
    Compile.DependentUpon: Settings.settings
    

Обратите внимание, что фраза Compile.DependentUpon появляется несколько раз. Использование метаданных с таким синтаксисом в целевом объекте приводит к пакетной обработке. Пакетная обработка означает, что задачи в целевом объекте выполняются один раз для каждого уникального значения метаданных. Это является эквивалентом скрипта MSBuild общей конструкции программирования for loop. Дополнительные сведения см. в статье Пакетная обработка.

Стандартные метаданные

Всякий раз, когда элемент добавляется в список элементов, ему назначаются некоторые стандартные метаданные. Например %(Filename) возвращает имя файла любого элемента. Полный список стандартных метаданных см. в статье Общеизвестные метаданные элементов MSBuild.

Анализ стандартных метаданных

  1. В редакторе кода замените задачу Message следующей строкой:

    <Message Text="Compile Filename: %(Compile.Filename)" />
    
  2. Сохраните файл проекта.

  3. В командном окне введите и выполните следующую строку:

    msbuild buildapp.csproj -t:HelloWorld
    
  4. Проанализируйте результат. Должны отобразиться следующие строки:

    Compile Filename: Form1
    Compile Filename: Form1.Designer
    Compile Filename: Program
    Compile Filename: AssemblyInfo
    Compile Filename: Resources.Designer
    Compile Filename: Settings.Designer
    

Сравнивая два приведенных выше примера, можно увидеть, что, хотя не у каждого элемента в типе элемента Compile имеются метаданные DependentUpon, у всех элементов есть стандартные метаданные Filename.

Преобразования метаданных

Списки элементов могут быть преобразованы в новые списки элементов. Чтобы преобразовать список элементов, используйте следующий синтаксис, где <ItemType> — это имя типа элементов, а <MetadataName> — имя метаданных:

@(ItemType -> '%(MetadataName)')

Например, список элементов исходных файлов можно преобразовать в коллекцию объектных файлов с помощью выражения @(SourceFiles -> '%(Filename).obj'). Дополнительные сведения см. в статье Преобразования.

Преобразование элементов с помощью метаданных

  1. В редакторе кода замените задачу Message следующей строкой:

    <Message Text="Backup files: @(Compile->'%(filename).bak')" />
    
  2. Сохраните файл проекта.

  3. В командном окне введите и выполните следующую строку:

    msbuild buildapp.csproj -t:HelloWorld
    
  4. Проанализируйте результат. Вы должны увидеть следующую строку:

    Backup files: Form1.bak;Form1.Designer.bak;Program.bak;AssemblyInfo.bak;Resources.Designer.bak;Settings.Designer.bak
    

Обратите внимание, что выраженные в этом синтаксисе метаданные не приводят к пакетной обработке.

Следующие шаги

Пошаговые инструкции по созданию файла простого проекта см. в статье Пошаговое руководство. Создание файла проекта MSBuild с нуля.

См. также