Introduction to MSBuild – Artur Dorochowicz – Inline tasks



Introduction to MSBuild – Artur Dorochowicz – Inline tasks

0 0


presentation-introduction-to-msbuild

Presentation: Introduction to MSBuild.

On Github ArturDorochowicz / presentation-introduction-to-msbuild

Introduction to MSBuild

Artur Dorochowicz

https://github.com/ArturDorochowicz/

Agenda

Building blocks Visual Studio solution Command line Debugging Demos

Building blocks

Project

  • DefaultTargets - optional, in VS it's usually "Build"
  • .targets - convention for projects for importing
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003"
         DefaultTargets="Foo; Bar"
         InitialTargets="Baz">
    <Import Project="MyCustom.targets" />
</Project>

Targets

  • Targets group tasks together and form the dependency tree
  • Build, Rebuild and Clean are targets
  • Target is only run once in a given build
<Target Name="MyTarget"
        AfterTargets="Foo"
        BeforeTargets="Bar"
        DependsOnTargets="Baz; Qux">
    <CallTargets Targets="Foobar" />
</Target>
Targets group tasks together in a particular order and allow the build process to be factored into smaller units.

Properties

  • Scalar values
  • No need to declare before use
  • Reference with $(property)
<PropertyGroup>
    <FirstName>John</FirstName>

    <LastName>Doe<LastName>

    <FullName>$(FirstName) $(LastName)<FullName>
</PropertyGroup>
Property names are not case sensitive.

Predefined Properties

  • $(MSBuildProjectDirectory)
  • $(MSBuildThisFileDirectory)
  • $(MSBuildLastTaskResult)
  • $(MSBuildBinPath)
  • $(MSBuildExtensionsPath)
  • $(MSBuildToolsPath)
  • Environment variables are available as properties

http://msdn.microsoft.com/en-us/library/vstudio/ms164309.aspx

Reserved properties - cannot be overwritten. Well-known properties - can be overwritten. Common VS projects properties: http://msdn.microsoft.com/en-us/library/vstudio/bb629394.aspx

Property Functions - .NET

System.String instance methods

<PropertyGroup>
    <Sample>FooBar</Sample>

    <Sub>$(Sample.Substring(0, 3))</Sub>

    <Contains>$(Sample.Contains("Bar")</Contains>
</PropertyGroup>

Property Functions - .NET

All static methods and properties on selected .NET types

<PropertyGroup>
    <NewGuid>$([System.Guid]::NewGuid())</NewGuid>
    <Today>$([System.DateTime]::Now.ToString("yyyy-MM-dd"))</Today>
    <Power>$([System.Math]::Pow(2,8))</Power>
    <TempFile>$([System.IO.Path]::GetTempFileName())</TempFile>
</PropertyGroup>

Selected methods and properties on: System.Environment, System.IO.Directory, System.IO.File

http://msdn.microsoft.com/en-us/library/dd633440.aspx

Property Functions - MSBuild

<PropertyGroup>
    <Value>
        $([MSBuild]::MakeRelative(
            $(FileOrFolderPath1), $(FileOrFolderPath2)))

        $([MSBuild]::GetRegistryValue(
            'HKEY_LOCAL_MACHINE\SOFTWARE\(SampleName)', '(SampleValue)'))

        $([MSBuild]::Add($(NumberOne), $(NumberTwo)))

        $([MSBuild]::BitwiseAnd(
            32, $([System.IO.File]::GetAttributes(tempFile))))
    </Value>
</PropertyGroup>

http://msdn.microsoft.com/en-us/library/dd633440.aspx

Items

Lists of values, usually files

<ItemGroup>
    <File Include="path\to\file.txt" />

    <Files Include="path\to\file.txt; path\to\another.txt" />

    <FilesWildcard Include="path\to\*.txt" />

    <FilesRecursiveWildcard Include="path\**\*.txt" />

    <SomeFilesButNotOthers Include="path\to\*.txt"
        Exclude="path\to\not-this-one.txt" />

    <FilesAdd Include="path\to\fileA.txt" />

    <FilesAdd Include="path\to\fileB.txt; fileC.xml"
        Exclude="**\*.txt" />
</ItemGroup>

Well-known item metadata

<!-- C:\MyProject\Source\Program.cs -->
<ItemGroup>
    <MyItem Include="Source\Program.cs" />
</ItemGroup>
  • %(FullPath) C:\MyProject\Source\Program.cs
  • %(RootDir) C:\
  • %(Filename) Program
  • %(Extension) .cs
  • %(RelativeDir) Source\
  • %(Directory) MyProject\Source\
  • %(RecursiveDir) here empty; path matched by ** wildcard
  • %(Identity) Source\Program.cs
  • %(ModifiedTime), %(CreatedTime), %(AccessedTime) e.g. 2004-08-14 16:52:36.3168743

http://msdn.microsoft.com/en-us/library/vstudio/ms164313.aspx

Custom item metadata

<ItemGroup>
    <Reference Include="MyAssembly">
        <Private>True</Private>
        <HintPath>..\lib\MyAssembly.dll</HintPath>
    </Reference>
</ItemGroup>

<ItemGroup>
    <Compile Include="Global.asax.cs">
        <DependentUpon>Global.asax</DependentUpon>
    </Compile>
</ItemGroup>

Custom item metadata

Item definition

<ItemDefinitionGroup>
    <MyItem>
        <Custom1>1</Custom1>
        <Custom2>2</Custom2>
    </MyItem>
</ItemDefinitionGroup>

<ItemGroup>
    <MyItem Include="file.txt">
        <Custom2>other</Custom2>
        <Custom3>3</Custom3>
    </MyItem>
</ItemGroup>

Tasks

<ItemGroup>
    <MySourceFiles Include="c:\MySourceTree\**\*.*" />
</ItemGroup>

<Target Name="CopyFiles">
    <Copy
        SourceFiles="@(MySourceFiles)"
        DestinationFiles="@(MySourceFiles->
            'c:\MyDestinationTree\%(RecursiveDir)%(Filename)%(Extension)')"
    />
</Target>
Tasks may only be used within targets.

Built-in tasks

AspNetCompiler CallTarget Copy CombinePath Delete Error Exec MakeDir Message Move MSBuild ReadLinesFromFile RemoveDir Touch Warning WriteLinesToFile XmlPeek XmlPoke XslTransformation

http://msdn.microsoft.com/en-us/library/7z253716(v=vs.100).aspx

External tasks

<UsingTask
  TaskName="Microsoft.TeamFoundation.Build.Tasks.GetBuildProperties"
  AssemblyFile="$(TeamBuildRefPath)\Microsoft.TeamFoundation.Build.ProcessComponents.dll"
/>

<Target Name="MyTarget">
  <GetBuildProperties
    TeamFoundationServerUrl="$(TeamFoundationServerUrl)"
    BuildUri="$(BuildUri)">
    <Output TaskParameter="BuildNumber"
      PropertyName="BuildNumber" />
    <Output TaskParameter="SourceGetVersion"
      PropertyName="SourceGetVersion" />
  </GetBuildProperties>
</Target>

Popular task collections

Inline tasks

Parameter type is optional and defaults to string. Full type name must be used (e.g. System.Boolean).
<UsingTask TaskName="FilterList" TaskFactory="CodeTaskFactory"
  AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.v4.0.dll">
  <ParameterGroup>
    <ListToFilter ParameterType="Microsoft.Build.Framework.ITaskItem[]"
      Required="true" />
    <Filter Required="true" />
    <FilteredList ParameterType="Microsoft.Build.Framework.ITaskItem[]"
      Output="true" />
  </ParameterGroup>
  <Task>
    <Using Namespace="System.Text.RegularExpressions" />
    <Code Type="Fragment" Language="cs">
      <![CDATA[
        var results = ListToFilter
          .Where(x => Regex.IsMatch(x.ItemSpec, Filter));
        FilteredList = results.ToArray();
      ]]>
    </Code>
  </Task>
</UsingTask>
<ItemGroup>
  <Source Include="file.txt; file.cs" />
</ItemGroup>

<Target Name="MyTarget">
  <FilterList ListToFilter="@(Source)" Filter="\.cs$">
    <Output ItemName="_FilteredList" TaskParameter="FilteredList" />
  </FilterList>
</Target>

Conditions

<PropertyGroup Condition="'$(Configuration)' == 'Release'">
    <MvcBuildViews>true</MvcBuildViews>
</PropertyGroup>

<PropertyGroup>
    <OutDir Condition="'$(OutDir)' == ''">
        $(MSBuildProjectDirectory)\bin</OutDir>
</PropertyGroup>

Operators

  • ==   !=      strings
  • >    <    >=    <=      numbers
  • Exists()    HasTrailingSlash()      strings
  • !    And    Or

Visual Studio solutions

MSBuild vs SLN

  • .sln - not an MSBuild XML project file
  • Converted to a project on the fly
  • set MSBUILDEMITSOLUTION=1 - saves generated project to file

.sln extensibility

<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" DefaultTargets="Build" InitialTargets="ValidateSolutionConfiguration;ValidateToolsVersions;ValidateProjects">
 <Import
  Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\SolutionFile\ImportBefore\*"
  Condition="'$(ImportByWildcardBeforeSolution)' != 'false' and exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\SolutionFile\ImportBefore')" />
 <Import
  Project="$(MSBuildProjectDirectory)\before.MySln.sln.targets"
  Condition="exists('before.MySln.sln.targets')" />
<!-- Properties/Items/Targets here -->
 <Import
  Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\SolutionFile\ImportAfter\*"
  Condition="'$(ImportByWildcardBeforeSolution)' != 'false' and exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\SolutionFile\ImportAfter')" />
 <Import
  Project="$(MSBuildProjectDirectory)\after.MySln.sln.targets"
  Condition="exists('after.MySln.sln.targets')" />
</Project>
http://sedodream.com/2010/10/22/MSBuildExtendingTheSolutionBuild.aspx

Command line

Command line

msbuild.exe MySolution.sln
    /target:Rebuild
    /property:Configuration=Release /property:DeployOnBuild=True
    /verbosity:diagnostic
    /maxcpucount
    /nodereuse:false

Properties set on the command line become constants

http://msdn.microsoft.com/en-us/library/vstudio/ms164311(v=vs.100).aspx

Properties set from command line are constants. Percent encoding.
  • c:\Windows\Microsoft.NET\Framework\v2.0.50727\MSBuild.exe
  • c:\Windows\Microsoft.NET\Framework\v3.5\MSBuild.exe
  • c:\Windows\Microsoft.NET\Framework\v4.0.30319\MSBuild.exe
  • c:\Windows\Microsoft.NET\Framework64\v2.0.50727\MSBuild.exe
  • c:\Windows\Microsoft.NET\Framework64\v3.5\MSBuild.exe
  • c:\Windows\Microsoft.NET\Framework64\v4.0.30319\MSBuild.exe

Debugging

Debugging

C:\Windows\system32\reg add
  "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\MSBuild\4.0"
  /v DebuggerEnabled /d true

C:\Windows\SysWOW64\reg add
  "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\MSBuild\4.0"
  /v DebuggerEnabled /d true

and Turn on Enable Just My Code in VS Options/Debugging/General

Then

msbuild.exe ... /debug

or

SET MSBUILDDEBUGGING=1
http://blogs.msdn.com/b/visualstudio/archive/2010/07/06/debugging-msbuild-script-with-visual-studio.aspx http://blogs.msdn.com/b/visualstudio/archive/2010/07/09/debugging-msbuild-script-with-visual-studio-2.aspx http://blogs.msdn.com/b/visualstudio/archive/2010/07/09/debugging-msbuild-script-with-visual-studio-3.aspx

Demos

Introduction to MSBuild

Artur Dorochowicz

https://github.com/ArturDorochowicz/presentation-introduction-to-msbuild