MSBuild

Minimal project template:

<?xml version="1.0" encoding="utf-8" ?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">  
  <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>  

Targets can be called explicitly (uncommon) with the CallTarget task
<CallTarget Target="TargetA;TargetB" />

Targets can have dependencies
<Target Name="TargetC" DependsOnTargets="TargetA;TargetB" />

Invoking TargetC will then be followed by TargetB
<Target Name="TargetB" AfterTargets="TargetC" />

Invoking TargetC will then be preceded by TargetA
<Target Name="TargetA" BeforeTargets="TargetC" />

Conditional invocation

<PropertyGroup>
  <DoIt>true</DoIt>
</PropertyGroup>
<Target Name="TargetC" Condition="$(DoIt)" />

Typically .proj imports .targets, and .targets imports .props
Import .tasks where needed
<Import Project="Common.props" />

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

Special targets defined in Microsoft.CSharp.targets
<Target Name="BeforeBuild" /> <Target Name="AfterBuild" />

Generate locale folders (cross join):

<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="CrossJoin" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <ItemGroup>
    <Locales Include="en;fr" />
    <Files Include="A.md;B.md" />
  </ItemGroup>

  <Target Name="CrossJoin">
    <ItemGroup>
      <OutputFiles Include="@(Files)">
        <Locale>%(Locales.Identity)</Locale>
      </OutputFiles>
    </ItemGroup>
    <Message Text="%(OutputFiles.Locale)\%(OutputFiles.Identity)" />
  </Target>
</Project>

Bring in custom task
<UsingTask AssemblyFile="file name" TaskName="task name" />

Custom tasks extend Task (recommended) or at implement ITask.

Consider using inline tasks.

Recursive list of files

<ItemGroup>
  <Compile Include=".\**\*.cs" />
</ItemGroup>

References