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

Языки программирования, предназначенные для платформы .NET Framework, используют файлы проекта MSBuild для описания и контроля процесса построения приложения. Если для создания файла проекта MSBuild используется Visual Studio, соответствующий XML добавляется в файл автоматически. Тем не менее, понимание принципов организации XML и способов его изменения, позволяющих контролировать построение, может вам пригодиться.

Примечание.

Эта статья описывает основные принципы работы MSBuild независимо от пакетов SDK. Здесь не рассматривается сборка с помощью пакета SDK, например при использовании dotnet build или добавлении атрибута Sdk в корневой элемент проекта. См. Пакеты SDK для проектов .NET.

Сведения о создании файла проекта для проекта C++ см. в разделе MSBuild (C++).

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

  1. Расширение переменной среды PATH.

  2. Создание минимального исходного файла приложения.

  3. Создание минимального файла проекта MSBuild.

  4. Построение приложения с помощью файла проекта.

  5. Добавление свойств для управления построением.

  6. Управление построением с помощью изменений значений свойства.

  7. Добавление целей к построению.

  8. Управление построением путем указания целей.

  9. Инкрементная сборка.

В этом пошаговом руководстве показан способ построения проекта в командной строке и проверка результатов. Дополнительные сведения о платформе MSBuild и ее запуске из командной строки см. в статье Пошаговое руководство. Использование MSBuild.

Для выполнения пошагового руководства необходимо установить решение Visual Studio, которое включает MSBuild и компилятор C#.

Расширение пути

Прежде чем использовать MSBuild, необходимо расширить переменную среду PATH, чтобы включить все необходимые средства. Для этого можно использовать командную строку разработчика для Visual Studio. В Windows 10 ее можно найти в поле поиска на панели задач Windows. Чтобы настроить среду в обычной командой строке или в среде скриптов, запустите файл VSDevCmd.bat, находящийся в подпапке Common7/Tools каталога, в котором установлено решение Visual Studio.

Создание минимального приложения

Этот раздел описывает процедуру создания исходного файла минимального приложения C# с помощью текстового редактора.

  1. В командной строке перейдите к папке, в которой необходимо создать приложение, например \Мои документы\ или \Рабочий стол\.

  2. Создайте вложенную папку \HelloWorld\ и перейдите в нее.

  3. В текстовом редакторе создайте файл HelloWorld.cs, а затем скопируйте и вставьте следующий код:

    using System;
    
    class HelloWorld
    {
        static void Main()
        {
    #if DebugConfig
            Console.WriteLine("WE ARE IN THE DEBUG CONFIGURATION");
    #endif
    
            Console.WriteLine("Hello, world!");
        }
    }
    
  4. Создайте приложение, указав в командной строке csc helloworld.cs.

  5. Проверьте приложение, указав в командной строке helloworld.

    Должно появиться сообщение Hello, world!.

  6. Удалите исполняемый файл.

Создание минимального файла проекта MSBuild

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

  • Необходимый корневой узел Project.

  • Узел ItemGroup для хранения элементов.

  • Элемент, который ссылается на исходный файл приложения.

  • Узел Target для хранения задач, которые требуются для построения приложения.

  • Элемент Task для запуска компилятора C# для сборки приложения.

Создание файла минимального проекта MSBuild

  1. В текстовом редакторе создайте файл HelloWorld.csproj и введите следующий код:

    <Project>
      <ItemGroup>
        <Compile Include="helloworld.cs" />
      </ItemGroup>
    </Project>
    

    ItemGroup содержит элемент Compile и указывает один исходный файл в качестве элемента.

  2. Добавьте узел Target в качестве дочернего элемента узла Project. Назовите узел Build.

    <Target Name="Build">
    </Target>
    
  3. Вставьте следующий элемент задачи в качестве дочернего элемента узла Target.

    <Csc Sources="@(Compile)"/>
    
  4. Сохраните этот файл проекта и назовите его Helloworld.csproj.

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

<Project>
  <ItemGroup>
    <Compile Include="helloworld.cs"/>
  </ItemGroup>
  <Target Name="Build">
    <Csc Sources="@(Compile)"/>
  </Target>
</Project>

Задачи в целевом объекте сборки выполняются последовательно. В этом случае задача Csc компилятора C# является единственной. Она ожидает список исходных файлов для компилирования, который задается значением элемента Compile. Элемент Compile ссылается на единственный исходный файл Helloworld.cs.

Примечание.

В элементе можно использовать подстановочный знак "звездочка" (*) для ссылки на все файлы, которые имеют расширение имени файла .cs, как показано ниже:

<Compile Include="*.cs" />

Сборка приложения

Теперь используйте только что созданный файл проекта для построения приложения.

  1. В командной строке введите msbuild helloworld.csproj -t:Build.

    После этого для создания приложения "Helloworld" будет вызван компилятор C# и построен целевой объект построения файла проекта Helloworld.

  2. Протестируйте приложение, указав в командной строке helloworld.

    Должно появиться сообщение Hello, world!.

Примечание.

Чтобы получить более подробную информацию о построении, увеличьте уровень детализации. Чтобы задать "подробный" уровень детализации, введите в командной строке следующую команду:

msbuild helloworld.csproj -t:Build -verbosity:detailed

Добавление свойств построения

Для дальнейшего управления построением можно добавлять свойства построения к файлу проекта. Добавьте следующие свойства.

  • Свойство AssemblyName, чтобы указать имя приложения.

  • Свойство OutputPath, чтобы указать папку для хранения приложения.

Добавление свойств построения

  1. Удалите существующий исполняемый файл приложения (позже вы добавите целевой объект Clean для обработки удаления старых выходных файлов).

  2. В файле проекта вставьте этот элемент PropertyGroup сразу после начала элемента Project:

    <PropertyGroup>
      <AssemblyName>MSBuildSample</AssemblyName>
      <OutputPath>Bin\</OutputPath>
    </PropertyGroup>
    
  3. Добавьте задачу в целевой объект построения непосредственно перед задачей Csc:

    <MakeDir Directories="$(OutputPath)" Condition="!Exists('$(OutputPath)')" />
    

    Задача MakeDir создает папку, которой присваивается имя свойства OutputPath, при условии, что папка с таким именем не существует.

  4. Добавьте следующий атрибут OutputAssembly к задаче Csc:

    <Csc Sources="@(Compile)" OutputAssembly="$(OutputPath)$(AssemblyName).exe" />
    

    Он поручает компилятору C# создать сборку, присвоить ей имя свойства AssemblyName и вставить в папку, которой присвоено имя свойства OutputPath.

  5. Сохранение изменений.

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

<Project>
  <PropertyGroup>
    <AssemblyName>MSBuildSample</AssemblyName>
    <OutputPath>Bin\</OutputPath>
  </PropertyGroup>
  <ItemGroup>
    <Compile Include="helloworld.cs" />
  </ItemGroup>
  <Target Name="Build">
    <MakeDir Directories="$(OutputPath)" Condition="!Exists('$(OutputPath)')" />
    <Csc Sources="@(Compile)" OutputAssembly="$(OutputPath)$(AssemblyName).exe" />
  </Target>
</Project>

Примечание.

Мы рекомендуем добавить разделитель пути в виде обратной косой черты (\) в конце имени папки при его указании в элементе OutputPath, вместо добавления его в атрибут OutputAssembly задачи Csc. Таким образом,

<OutputPath>Bin\</OutputPath>

OutputAssembly="$(OutputPath)$(AssemblyName).exe" />

лучше, чем

<OutputPath>Bin</OutputPath>

OutputAssembly="$(OutputPath)\$(AssemblyName).exe" />

Тестирование свойств построения

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

  1. В командной строке введите msbuild helloworld.csproj -t:Build.

    После этого программа создаст папку \Bin, вызовет компилятор C# для создания приложения MSBuildSample и разместит его в папку \Bin.

  2. Чтобы убедиться, что папка \Bin\ создана и содержит приложение MSBuildSample, введите dir Bin.

  3. Протестируйте приложение, введя Bin\MSBuildSample для запуска исполняемого файла.

    Должно появиться сообщение Hello, world!.

Добавление целей построения

Теперь добавьте к файлу проекта еще две цели.

  • Цель "Очистить", которая удаляет старые файлы.

  • Цель "Перестроить", которая использует атрибут DependsOnTargets для принудительного запуска задачи "Очистить" перед выполнением задачи "Построение".

Теперь, когда целей несколько, можно задать в качестве цели по умолчанию цель "Построение".

Добавление целей построения

  1. В файле проекта добавьте эти две цели сразу после цели "Построение":

    <Target Name="Clean" >
      <Delete Files="$(OutputPath)$(AssemblyName).exe" />
    </Target>
    <Target Name="Rebuild" DependsOnTargets="Clean;Build" />
    

    Цель "Очистить" вызывает задачу "Удалить", чтобы удалить приложение. Цель "Перестроить" не запускается, пока не будут выполнены цели "Очистить" и "Построение". Несмотря на то, что цель "Перестроить" не имеет задач, она вызывает выполнение цели "Очистить" до выполнения цели "Построение".

  2. Добавьте следующий атрибут DefaultTargets в начало элемента Project:

    <Project DefaultTargets="Build">
    

    Это сделает цель "Построение" целью по умолчанию.

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

<Project DefaultTargets="Build">
  <PropertyGroup>
    <AssemblyName>MSBuildSample</AssemblyName>
    <OutputPath>Bin\</OutputPath>
  </PropertyGroup>
  <ItemGroup>
    <Compile Include="helloworld.cs" />
  </ItemGroup>
  <Target Name="Build">
    <MakeDir Directories="$(OutputPath)" Condition="!Exists('$(OutputPath)')" />
    <Csc Sources="@(Compile)" OutputAssembly="$(OutputPath)$(AssemblyName).exe" />
  </Target>
  <Target Name="Clean" >
    <Delete Files="$(OutputPath)$(AssemblyName).exe" />
  </Target>
  <Target Name="Rebuild" DependsOnTargets="Clean;Build" />
</Project>

Тестирование целей построения

Для тестирования этих функций файла проекта можно запустить новые цели построения.

  • Построение по умолчанию.

  • Задание имени приложения в командной строке.

  • Удаление приложения перед построением другого приложения.

  • Удаление приложения без построения другого приложения.

Тестирование целей построения

  1. В командной строке введите msbuild helloworld.csproj -p:AssemblyName=Greetings.

    Так как параметр -t для задания цели напрямую не использовался, MSBuild запускает стандартную цель "Сборка". Параметр -p переопределяет свойство AssemblyName и присваивает ему новое значение Greetings. В результате в папке \Bin\ создается новое приложение Greetings.exe.

  2. Чтобы убедиться, что в папке \Bin\ содержатся приложение MSBuildSample и новое приложение Greetings, введите dir Bin.

  3. Протестируйте приложение Greetings (например, введя Bin\Greetings в Windows).

    Должно появиться сообщение Hello, world!.

  4. Удалите приложение MSBuildSample с помощью команды msbuild helloworld.csproj -t:clean.

    Это запустит задачу "Очистить" и позволит удалить приложение со значением свойства AssemblyName по умолчанию — MSBuildSample.

  5. Удалите приложение Greetings с помощью команды msbuild helloworld.csproj -t:clean -p:AssemblyName=Greetings.

    Это запустит задачу "Очистить" и позволит удалить приложение с заданным значением свойства AssemblyName по умолчанию — Greetings.

  6. Чтобы убедиться, что папка \Bin\ пуста, введите dir Bin.

  7. Введите команду msbuild.

    Несмотря на то что файл проекта не указан, MSBuild строит файл helloworld.csproj, поскольку в текущей папке присутствует только один файл проекта. В результате в папке \Bin\ создается новое приложение MSBuildSample.

    Чтобы убедиться, что в папке \Bin\ появилось приложение MSBuildSample, введите dir Bin.

Инкрементная сборка

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

Последовательное построение

  1. В файле проекта добавьте к открытой цели "Построение" следующие два атрибута:

    Inputs="@(Compile)" Outputs="$(OutputPath)$(AssemblyName).exe"
    

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

    Полученная цель "Построение" должна выглядеть следующим образом:

    <Target Name="Build" Inputs="@(Compile)" Outputs="$(OutputPath)$(AssemblyName).exe">
      <MakeDir Directories="$(OutputPath)" Condition="!Exists('$(OutputPath)')" />
      <Csc Sources="@(Compile)" OutputAssembly="$(OutputPath)$(AssemblyName).exe" />
    </Target>
    
  2. Протестируйте цель "Сборка" с помощью команды msbuild -v:d.

    Помните, что helloworld.csproj является файлом проекта по умолчанию, а построение — целью по умолчанию.

    Параметр -v:d — это сокращенное обозначение -verbosity:detailed, которое вы использовали ранее.

    Если вы уже создали выходные данные, эти строки должны отображаться:

    Целевой объект "Сборка" пропускается, так как все выходные файлы актуальны по отношению к входным.

    MSBuild пропускает цель "Построение", так как с последнего построения приложения ни один из исходных файлов не изменился.

Пример C#

В следующем примере показан файл проекта, который компилирует приложение C# и записывает сообщение, содержащее имя файла вывода.

Код

<Project DefaultTargets = "Compile">

    <!-- Set the application name as a property -->
    <PropertyGroup>
        <appname>HelloWorldCS</appname>
    </PropertyGroup>

    <!-- Specify the inputs by type and file name -->
    <ItemGroup>
        <CSFile Include = "*.cs"/>
    </ItemGroup>

    <Target Name="Compile">
        <!-- Run the C# compilation using input files of type CSFile -->
        <CSC
            Sources = "@(CSFile)"
            OutputAssembly = "$(appname).exe">
            <!-- Set the OutputAssembly attribute of the CSC task
            to the name of the executable file that is created -->
            <Output
                TaskParameter = "OutputAssembly"
                ItemName = "EXEFile" />
        </CSC>
        <!-- Log the file name of the output file -->
        <Message Text="The output file is @(EXEFile)"/>
    </Target>
</Project>

Пример в Visual Basic

В следующем примере показан файл проекта, который компилирует приложение Visual Basic и записывает сообщение, содержащее имя файла вывода.

Код

<Project DefaultTargets = "Compile">

    <!-- Set the application name as a property -->
    <PropertyGroup>
        <appname>HelloWorldVB</appname>
    </PropertyGroup>

    <!-- Specify the inputs by type and file name -->
    <ItemGroup>
        <VBFile Include = "consolehwvb1.vb"/>
    </ItemGroup>

    <Target Name = "Compile">
        <!-- Run the Visual Basic compilation using input files of type VBFile -->
        <VBC
            Sources = "@(VBFile)"
            OutputAssembly= "$(appname).exe">
            <!-- Set the OutputAssembly attribute of the VBC task
            to the name of the executable file that is created -->
            <Output
                TaskParameter = "OutputAssembly"
                ItemName = "EXEFile" />
        </VBC>
        <!-- Log the file name of the output file -->
        <Message Text="The output file is @(EXEFile)"/>
    </Target>
</Project>

Дальнейшие действия

Visual Studio может выполнять большую часть работы, описанной в этом пошаговом руководстве, автоматически. Сведения об использовании Visual Studio для создания, изменения, сборки и тестирования файлов проекта MSBuild см. в разделе Пошаговое руководство. Использование MSBuild.