MSBuild-4 :👈 👉:MSBuild-6

MSBuild Day 5 – Advanced Concepts

Day 5 – Advanced MSBuild: Property Functions, Conditions, Incremental Builds, Inputs/Outputs, Diagnostics

Today you will learn the advanced features of MSBuild that make automation powerful: Property Functions, Conditions, Incremental Builds, Inputs and Outputs, Build Graphs, and Diagnostic Logging. These are essential for writing efficient, maintainable build logic.

1. Property Functions

Property functions allow you to use .NET-like methods inside MSBuild properties. They work inside $() expressions.

Examples:

$(ProjectName.ToUpper())
$(Configuration.StartsWith('D'))
$([System.DateTime]::Now.ToString())
$([System.Guid]::NewGuid())

Combine strings:

$(BasePath)\bin\$(Configuration)

Create numbers:

$([MSBuild]::Add(3, 5))
$([MSBuild]::Multiply(4, 10))

Property functions are extremely powerful for dynamic build logic.

2. Conditions in MSBuild

Conditions exist on almost every MSBuild element: properties, items, targets, tasks. They use simple string comparison or numeric comparison.

Property example:

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

Item example:

<ItemGroup>
  <LogFiles Include="logs\*.txt" Condition="Exists('logs')" />
</ItemGroup>

Target example:

<Target Name="OnlyRunInRelease" Condition=" '$(Configuration)'=='Release' ">
    <Message Text="Running Release only logic..." />
</Target>

3. Incremental Builds

MSBuild supports incremental builds — tasks only run if needed. A target becomes incremental when you define:

  • Inputs – files or values checked for changes
  • Outputs – files produced

If all outputs are newer than inputs, MSBuild skips the target.

Example:

<Target Name="ProcessImages"
        Inputs="@(Images)"
        Outputs="@(Images->'processed\%(Filename).png')">

    <Message Text="Processing %(Images.Identity)..." />

</Target>

If none of the source images changed, the target will not run again.

4. Inputs and Outputs Logic

MSBuild compares timestamps of Inputs and Outputs. If output exists and is newer → skip target. If output missing or older → execute target.

Example of timestamp behavior:

Source.txt  -> modified today
Output.txt  -> modified yesterday

MSBuild will rerun the target because output is older.

5. Build Graph and Parallel Builds

MSBuild can build multiple projects at once using its dependency graph. This happens automatically when you build a solution.

To force parallel builds:

dotnet build -m

To visualize project build graph:

dotnet msbuild -graph

6. Diagnostic Logging

Diagnostics are crucial for understanding what MSBuild is doing.

Common verbosity levels:

  • q – quiet
  • m – minimal
  • n – normal
  • d – detailed
  • diag – diagnostic (very large output)

Enable diagnostic logging:

dotnet build -v:diag

This prints every imported file, target, task, property, and item.

Write logs to a file:

dotnet build -v:diag -fl -flp:LogFile=msbuild.log

7. Inspect Final Project After Imports

Useful for debugging Directory.Build files, SDK imports, and props/targets:

dotnet msbuild -pp:expanded.xml

Open the file to see exactly what MSBuild sees after all imports.

8. Hands-On Exercise (15 minutes)

Step 1 — Add a transform

<ItemGroup>
    <TxtFiles Include="data\*.txt" />
</ItemGroup>

<ItemGroup>
    <ProcessedFiles Include="@(TxtFiles->'output\%(Filename).out')" />
</ItemGroup>

Step 2 — Create an incremental target

<Target Name="ProcessText"
        Inputs="@(TxtFiles)"
        Outputs="@(ProcessedFiles)">

    <Message Text="Processing: %(TxtFiles.Identity)" />

</Target>

Step 3 — Run

dotnet build -t:ProcessText

Edit one text file → run again → MSBuild processes only the changed file.

9. Summary

  • Property functions let you perform dynamic string and logic operations.
  • Conditions allow selective execution of MSBuild elements.
  • Incremental builds avoid unnecessary work.
  • Inputs/Outputs determine whether a target runs.
  • The build graph enables parallel builds.
  • Diagnostic logging is essential for troubleshooting.

10. Day 6 Preview

Tomorrow you will learn:

  • Creating and reusing custom .props and .targets files
  • Overriding targets and imports safely
  • Shared company-wide MSBuild logic
  • Extending MSBuild without modifying individual projects
Back to Index
MSBuild-4 :👈 👉:MSBuild-6
*