MSBuild MSDN reference
Script everything but compile with MsBuild
File extension .build
Empty Build Script
="1.0"="utf-8"
<project xmlns="http://schemas.microsoft.com/developers/msbuild/2003"
ToolsVersion="4.0">
</project>
Setting the Default Target
="1.0"="utf-8"
<project xmlns="http://schemas.microsoft.com/developers/msbuild/2003"
ToolsVersion="4.0"
DefaultTargets="TargetName">
</project>
Add a DefaultsTargets
attribute to the project element with the TargetName
being the name of the target.
Dependencies
<Target Name="Clean">
<RemoveDir Directories=".\buildartifacts"/>
</Target>
<Target Name="Init" DependsOnTargets="Clean">
<MakeDir Directories=".\buildartifacts"/>
</Target>
Compiling a VS Project
<Target Name="Compile">
<MSBuild Projects=".\HelloCI.sln"
Targets="Rebuild" Properties="OutDir=C:\temp\"/>
</Target>
*Important note that the outdir
cannot be a relative path, it has to be an absolute path with a trailing /
.
Properties
<PropertyGroup>
<BuildDir>Build</BuildDir>
</PropertyGroup>
Reference the above property by using the following syntax: $(BuildDir)
You can have properties based off other properties.
<PropertyGroup>
<BuildDir>Build</BuildDir>
<BuildFile>$(BuildDir)FileName.txt</BuildFile>
</PropertyGroup>
Debugging
You can show values of parameters by using the Message Text:
<Target Name="ShowReservedProperties">
<Message Text=" MSBuildProjectDirectory = $(MSBuildProjectDirectory)" />
<Message Text=" MSBuildProjectFile = $(MSBuildProjectFile)" />
<Message Text=" MSBuildProjectExtension = $(MSBuildProjectExtension)" />
<Message Text=" MSBuildProjectFullPath = $(MSBuildProjectFullPath)" />
<Message Text=" MSBuildProjectName = $(MSBuildProjectName)" />
<Message Text=" MSBuildBinPath = $(MSBuildBinPath)" />
<Message Text=" MSBuildProjectDefaultTargets = $(MSBuildProjectDefaultTargets)" />
<Message Text=" MSBuildExtensionsPath = $(MSBuildExtensionsPath)" />
<Message Text=" MSBuildStartupDirectory = $(MSBuildStartupDirectory)" />
</Target>
Copying Files with Directory Structure
<ItemGroup>
<out_files Include='output_dir/**/*'/>
</ItemGroup>
<Target Name='copy_files'>
<Copy SourceFiles='@(out_files)'
DestinationFolder='deployment_dir/%(out_files.RecursiveDir)'/>
</Target>
Moving Files
<Target Name="MoveSomeFiles">
<Move
SourceFiles="c:\Temp\File1.txt"
DestinationFolder="@(TargetDirectory)"
/>
</Target>
Moving Files with Wildcards
You cannot use regular expression directly in task parameters. You need to create an item containing list of files to move and pass its content to the task:
<ItemGroup>
<FilesToMove Include="c:\source\App_Web_*.dll"/>
</ItermGroup>
<Target Name="Build">
<Move
SourceFiles="@(FilesToMove)"
DestinationFolder="C:\target"
/>
</Target>
Note the @
symbol is used to reference the item group compared to the $
to access properties.
See stack overflow for more information.
Exlcuding Files with WildCards
<ItemGroup>
<ReportFiles Include="MaxCut.Reports.*.dll"
Exclude="*.Interfaces.*;*.Tests.*"/>
</ItemGroup>
**Be aware of when the files are created that you are including in your Item Group - if they are being created dynamically, place the ItemGroup
as a child element to the element that is generating the files.
Read here for further explanation.
Overriding Parameters
There is a bug/feature in MSBuild which means that if you call CreateProperty
and CallTarget
in the same Target
, your new property will not be globally available to other targets.
<PropertyGroup>
<DeployPath_TEST>\\test-server-path\websites\mysite</DeployPath_TEST>
<DeployPath_LIVE>\\live-server-path\websites\mysite</DeployPath_LIVE>
<DeployPath></DeployPath>
</PropertyGroup>
<Target Name="SetDeployPath-TEST">
<CreateProperty Value="$(DeployPath_TEST)">
<Output TaskParameter="Value" PropertyName="DeployPath"/>
</CreateProperty>
</Target>
<Target Name="Deploy-TEST">
<CallTarget Targets="SetDeployPath-TEST"/>
<CallTarget Targets="Deploy-Sub"/>
</Target>
See the stack overflow notes.
Including Sub Files
<Import Project=".\Base.targets" />
Imports a base project, if you do imports multiple times of the same file, you will get a warning. To avoid this, do the following:
<Import Project=".\Base.targets" Condition=" '$(BaseImported)' == '' "/>
And then in the base file, add a property that is recognized:
<PropertyGroup>
<BaseImported>true</BaseImported>
</PropertyGroup>
For more information on this, read this link.
Executing a Build Script
Assume we had a build script called HelloCI.build
with a target inside it called compile.
To execute this specific target, you would use the following command:
msbuild HelloCI.build /target:Compile
Refactoring MsBuild Scripts