User Tools

Site Tools


notes:tools:msbuild

MSBuild

msbuild file.csproj /t:TargetA       # execute TargetA in file.csproj
msbuild file.sln                     # build all projects in sln
msbuild file.csproj /v:diag          # specify verbosity

Properties are key/values pairs used to configure builds. A property value can be changed by re-defining the property.

<PropertyGroup>
  <Prop1>PropValue</Prop1>
  <Prop2 Condition=" '$(Prop2)' == '' ">NewValue</Prop2>
</PropertyGroup>

Items are inputs into the build system. 'MyItem' is the item type (or item name).

<ItemGroup>
  <MyItem Include="file1.txt" />
  <MyItem Include="file2.txt" />
</ItemGroup>

Tasks are units of executable code. The logic of a task is mapped to MSBuild with the <UsingTask> element.

<PropertyGroup>
  <Dir>MyDirectory</Dir>
</PropertyGroup>
<Target Name="MyTargetCreateDir">
  <MakeDir Directories="$(Dir)" />
</Target>

Targets group tasks together in a particular order and expose sections of a proj file as entry points.

<ItemGroup>
  <File>File1.cs</File>
  <File>File2.cs</File>
  <File>File3.cs</File>
</ItemGroup>
<Target Name="MyTargetCompile">
  <Csc Sources="@(File)" />
</Target>

Creating properties - Properties outside of Target are assigned during the evaluation phase of a build. During the execution phase, properties can be created or modified as follows:

  • Emit a property using any Task: <Task><Output PropertyName=“…” … /></Task>
  • Embed a PropertyGroup in a Target: <Target><PropertyGroup>…</PropertyGroup></Target>
  • (depreciated) Use the CreateProperty task.
Element Reference Remarks
Property $(PropName) - used to pass values to tasks
- used to evaluate conditions
- used to store values in a proj file
Environment
Variable
$(Path) or $(PATH) - property names are not case sensitive
- values of environment variables are set at the beginning of a build and are not modified
Items @(ItemType) - a parameter for a task
- the task uses individual items
Case-sensitive Not case-sensitive
- Element Name
- Attribute Name
- Property Name
- Item Type
- Metadata Name

Example: Specify a DefaultTarget:

<Project DefaultTargets="MainTarget" Sdk="Microsoft.NET.Sdk">
  <Target Name="MainTarget">
    ...
  </Target>
</Project>

Example: .NET Core app:

<PropertyGroup>
  <OutputType>Exe</OutputType>
  <TargetFramework>netcoreapp2.0</TargetFramework>
</PropertyGroup>

Example: Include files and references:

<ItemGroup>
  <Compile Include="**\*.cs" />
  <EmbeddedResources Include="**\*.resx />
</ItemGroup>
 
<ItemGroup>
  <PackageReference Include="Microsoft.NETCore.App" Version="1.0.1" />
</ItemGroup>

Example: Default property values:

<PropertyGroup>
  <RestoreSuccess Condition=" '$(RestoreSuccess)' == '' ">True</RestoreSuccess>
  <RestoreTool Condition=" '$(RestoreTool)' == '' ">NuGet</RestoreTool>
  <NuGetPackageRoot Condition=" '$(NuGetPackageRoot)' == '' ">$(UserProfile)\.nuget\packages\</NuGetPackageRoot>
  <NuGetProjectStyle Condition=" '$(NuGetProjectStyle)' == '' ">PackageReference</NuGetProjectStyle>
  <NuGetToolVersion Condition=" '$(NuGetToolVersion)' == '' ">4.7.0</NuGetToolVersion>
</PropertyGroup>

Example: Import another MSBuild script if it exists:

<ImportGroup>
  <Import Project="C:\MyProject\Script.props" Condition="Exists('C:\MyProject\Script.props')" />
</ImportGroup>

Example: Store XML in a property:

<PropertyGroup>
  <MyProp>
    ... XML goes here; it may contain other $props
  </MyProp>
</PropertyGroup>

Example: Use a condition comparing to a bool value 'DoSomething' and another condition comparing to a string value 'SayHello':

<Project DefaultTargets="MainTarget" Sdk="Microsoft.NET.Sdk">
 
    <PropertyGroup>
        <OutputType>Exe</OutputType>
        <TargetFramework>netcoreapp2.0</TargetFramework>
    </PropertyGroup>
 
    <PropertyGroup>
        <DoSomething>true</DoSomething>
        <SayHello>hello</SayHello>
    </PropertyGroup>
 
    <Target Name="MainTarget">
        <CallTarget Targets="TestBool;TestStr" />
    </Target>
 
    <Target Name="TestBool" Condition="$(DoSomething)">
        <Message Text="Something" />
    </Target>
    <Target Name="TestStr" Condition="$(SayHello) == 'hello'">
        <Message Text="Hello" />
    </Target>
 
</Project>

Example: Display the names and the ModifiedTime attribute of files located in a specified folder. In this example, we assume there are three files d1.dat, d2.dat, and d3.dat in a subfolder 'data':

<Project DefaultTargets="ListDataFiles" Sdk="Microsoft.NET.Sdk">
 
    <PropertyGroup>
        <OutputType>Exe</OutputType>
        <TargetFramework>netcoreapp2.0</TargetFramework>
        <DataPath>$(MSBuildProjectDirectory)\data\*.dat</DataPath>
    </PropertyGroup>
 
    <ItemGroup>
        <DataFiles Include="$(DataPath)" />
    </ItemGroup>
 
    <Target Name="ListDataFiles">
        <Message Text="@(DataFiles)" />
        <Message Text="@(DataFiles->'%(ModifiedTime)')" />
    </Target>
 
</Project>

Output:

Project "C:\Temp\test.csproj" on node 1 (default targets).
ListDataFiles:
  C:\Temp\data\d1.dat;C:\Temp\data\d2.dat;C:\Temp\data\d3.dat
  2018-08-07 13:43:00.6470153;2018-08-07 13:43:00.6470153;2018-08-07 13:43:00.6470153

Example: Display values of an item's custom property 'Description':

<Project DefaultTargets="ListDescriptions" Sdk="Microsoft.NET.Sdk">
 
    <PropertyGroup>
        <OutputType>Exe</OutputType>
        <TargetFramework>netcoreapp2.0</TargetFramework>
    </PropertyGroup>
 
    <ItemGroup>
        <Mammals Include="Echidna">
            <Description>Echidna description</Description>
        </Mammals>
        <Mammals Include="Pangolin">
            <Description>Pangolin description</Description>
        </Mammals>
        <Mammals Include="Porpoise">
            <Description>Porpoise description</Description>
        </Mammals>
    </ItemGroup>
 
    <Target Name="ListDescriptions">
        <Message Text="@(Mammals)" />
        <Message Text="@(Mammals->'%(Description)')" />
    </Target>
 
</Project>

Output:

Project "C:\Temp\test.csproj" on node 1 (default targets).
ListDescriptions:
  Echidna;Pangolin;Porpoise
  Echidna description;Pangolin description;Porpoise description

Example: Use AfterTargets to enforce the order of targets' execution:

<Project DefaultTargets="MainTarget" Sdk="Microsoft.NET.Sdk">
 
    <PropertyGroup>
        <OutputType>Exe</OutputType>
        <TargetFramework>netcoreapp2.0</TargetFramework>
    </PropertyGroup>
 
    <Target Name="MainTarget">
        <CallTarget Targets="TargetZ" />
    </Target>
 
    <Target Name="TargetX" AfterTargets="TargetZ">
        <Message Text="X" />
    </Target>
    <Target Name="TargetY" AfterTargets="TargetZ">
        <Message Text="Y" />
    </Target>
    <Target Name="TargetZ">
        <Message Text="Z" />
    </Target>
 
</Project>

Output:

Project "C:\Temp\test.csproj" on node 1 (default targets).
TargetZ:
  Z
TargetX:
  X
TargetY:
  Y

Example: Use DependsOnTargets to enforce the order of targets' execution. Note that C is executed only once:

<Project DefaultTargets="MainTarget" Sdk="Microsoft.NET.Sdk">
 
    <PropertyGroup>
        <OutputType>Exe</OutputType>
        <TargetFramework>netcoreapp2.0</TargetFramework>
    </PropertyGroup>
 
    <Target Name="MainTarget">
        <CallTarget Targets="TargetA" />
    </Target>
 
    <Target Name="TargetA" DependsOnTargets="TargetC">
        <Message Text="A" />
        <CallTarget Targets="TargetB" />
    </Target>
    <Target Name="TargetB" DependsOnTargets="TargetC">
        <Message Text="B" />
    </Target>
    <Target Name="TargetC">
        <Message Text="C" />
    </Target>
 
</Project>

Output:

Project "C:\Temp\test.csproj" on node 1 (default targets).
TargetC:
  C
TargetA:
  A
TargetB:
  B

Example: Include targets and properties from separate *.props files:

<Project DefaultTargets="MainTarget" Sdk="Microsoft.NET.Sdk">
 
    <Import Project="Common.targets" />
    <Import Project="Common.props" />
 
    <Target Name="MainTarget" DependsOnTargets="TargetA">
        <Message Text="Hello, $(FullName)" />
    </Target>
 
</Project>
<Project>
    <!-- Shared targets -->
    <Target Name="TargetA">
        <Message Text="A" />
    </Target>
 
    <Target Name="TargetB">
        <Message Text="B" />
    </Target>
 
    <Target Name="TargetC">
        <Message Text="C" />
    </Target>
</Project>
<Project>
    <!-- Shared properties -->
    <PropertyGroup>
        <OutputType>Exe</OutputType>
        <TargetFramework>netcoreapp2.0</TargetFramework>
 
        <First>Leon</First>
        <Last>McPowell</Last>
        <FullName>$(First) $(Last)</FullName>
    </PropertyGroup>
</Project>

Output:

Project "C:\Temp\test.csproj" on node 1 (default targets).
TargetA:
  A
MainTarget:
  Hello, Leon McPowell

Example: Compress files using the MSBuild.ExtensionPack.Compression.DNZip task from MSBuild.Extension.Pack. You need to download the extension pack files (dlls) first and point MSBuild to their location (here: a 'tools' subfolder):

<Project DefaultTargets="ZipFilesTarget" Sdk="Microsoft.NET.Sdk">
 
    <PropertyGroup>
        <OutputType>Exe</OutputType>
        <TargetFramework>netcoreapp2.0</TargetFramework>
    </PropertyGroup>
 
    <Import Project="MSBuild.Extension.Pack.targets" />
 
    <Target Name="ZipFilesTarget">
        <ItemGroup>
            <FilesToZip Include="data\*.*" />
        </ItemGroup>
 
        <MSBuild.ExtensionPack.Compression.DNZip
            TaskAction="Create"
            CompressFiles="@(FilesToZip)"
            ZipFileName="files.zip" />
    </Target>
 
</Project>

The MSBuild.Extension.Pack.targets file generated automatically:

<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
    <PropertyGroup>
        <ExtensionTasksPath>tools\</ExtensionTasksPath>
    </PropertyGroup>
    ...
    <!-- ============== Framework ============== -->
    <UsingTask AssemblyFile="$(ExtensionTasksPath)MSBuild.ExtensionPack.dll" TaskName="MSBuild.ExtensionPack.CodeQuality.FxCop"/>
    <UsingTask AssemblyFile="$(ExtensionTasksPath)MSBuild.ExtensionPack.dll" TaskName="MSBuild.ExtensionPack.CodeQuality.NUnit"/>
    <UsingTask AssemblyFile="$(ExtensionTasksPath)MSBuild.ExtensionPack.dll" TaskName="MSBuild.ExtensionPack.CodeQuality.NUnit3"/>
    <UsingTask AssemblyFile="$(ExtensionTasksPath)MSBuild.ExtensionPack.dll" TaskName="MSBuild.ExtensionPack.Communication.Email"/>
    <UsingTask AssemblyFile="$(ExtensionTasksPath)MSBuild.ExtensionPack.dll" TaskName="MSBuild.ExtensionPack.Communication.Ftp"/>
    <UsingTask AssemblyFile="$(ExtensionTasksPath)MSBuild.ExtensionPack.dll" TaskName="MSBuild.ExtensionPack.Communication.MSMQ"/>
    <UsingTask AssemblyFile="$(ExtensionTasksPath)MSBuild.ExtensionPack.dll" TaskName="MSBuild.ExtensionPack.Compression.Cab"/>
    <UsingTask AssemblyFile="$(ExtensionTasksPath)MSBuild.ExtensionPack.dll" TaskName="MSBuild.ExtensionPack.Compression.DNZip"/>
    <UsingTask AssemblyFile="$(ExtensionTasksPath)MSBuild.ExtensionPack.dll" TaskName="MSBuild.ExtensionPack.Compression.Zip"/>
    <UsingTask AssemblyFile="$(ExtensionTasksPath)MSBuild.ExtensionPack.dll" TaskName="MSBuild.ExtensionPack.Computer.ActiveDirectory"/>
    <UsingTask AssemblyFile="$(ExtensionTasksPath)MSBuild.ExtensionPack.dll" TaskName="MSBuild.ExtensionPack.Computer.ComponentServices"/>
    <UsingTask AssemblyFile="$(ExtensionTasksPath)MSBuild.ExtensionPack.dll" TaskName="MSBuild.ExtensionPack.Computer.EnvironmentVariable"/>
    <UsingTask AssemblyFile="$(ExtensionTasksPath)MSBuild.ExtensionPack.dll" TaskName="MSBuild.ExtensionPack.Computer.EventLog"/>
    ...
</Project>

Output:

Project "C:\Temp\test.csproj" on node 1 (default targets).
ZipFilesTarget:
  Creating ZipFile: files.zip

Example: Remove an output folder and build a VS solution:

<Project DefaultTargets="BuildSolution" Sdk="Microsoft.NET.Sdk">
    <PropertyGroup>
        <OutputType>Exe</OutputType>
        <TargetFramework>netcoreapp2.0</TargetFramework>
        <OutputPath>$(MSBuildThisFileDirectory)Output</OutputPath>
        <SolutionFileName>C:\Projects\DoSomething.sln</SolutionFileName>
    </PropertyGroup>
 
    <Target Name="CleanDir">
        <RemoveDir Directories="$(OutputPath)" Condition="Exists($(OutputPath))" />
    </Target>
 
    <Target Name="BuildSolution" DependsOnTargets="CleanDir">
        <MSBuild Projects="$(SolutionFileName)"
                 Properties="Configuration=Release;OutputPath=$(OutputPath)" />
    </Target>
</Project>
notes/tools/msbuild.txt · Last modified: 2018/11/29 by leszek