Build the Same Sources With Different Options
When you build projects, it is often necessary to compile the same components with different build options. For example, you can create a Debug build with symbol information or a Release build with no symbol information but with optimizations enabled. Or you can build a project to run on a specific platform such as x86 or x64. In all these cases, most of the build options stay the same; only a few options are changed to control the build configuration. With
MSBuild, you use properties and conditions to create the different build configurations.
In this example, the "Hello World" project contains two new property groups that can be used to create a Debug build and a Release build.
Property Element
The syntax of the
Property element is: <Name>Value</Name>, for example, <Flavor>DEBUG</Flavor>.
Property names are not case sensitive. All the following names are equivalent in an
MSBuild project file: $(File), $(FILE), and $(file).''
The
Property element can be used to define a variable that is referenced several times in the project file, such as the location of a temporary directory, or to set the values for properties that are used in several configurations, such as a Debug build and a Release build. For example, a project file contains the following properties:.
<Name>MyApp</Name> <Extension>.exe</Extension>
that are then referenced in the File property by using the syntax $(
*PropertyName*):
<File>$(Path)$(Name)$(Extension)</File>
When you build the project, the $(
*PropertyName*) syntax is replaced with the property value. If a property has not been defined, $(
*PropertyName*) resolves to an empty string. In this example, the Path property has not been defined, therefore
File=MyApp.exe.
Specifying Properties on the Command Line
Properties can be specified on the command line using the /property switch:
msbuild <file name>.proj /property:Flavor=Debug
The /property switch can be shortened to /p and can specify more than one property. For example, to set the value of the Flavor property and the value of the Platform property, type:
msbuild <file name>.proj /p:Flavor=Debug;Platform=x86
or
msbuild <file name>.proj /p:Flavor=Debug /p:Platform=x86
Specifying Properties Using Environment Variables
Environment variables are also treated as properties and are automatically incorporated by
MSBuild.
Order of Precedence for Properties
The property value that is specified on the command line takes precedence over any value that is set for the same property in the project file, and that value in the project file takes precedence over the value in an environment variable.
PropertyGroup Element
In the project file, a
PropertyGroup element is required as the container for properties, such as:
<PropertyGroup Condition="'$(Flavor)'=='DEBUG'">
<DebugType>full</DebugType> <Optimize>no</Optimize>
</PropertyGroup>
Condition Attribute
The
Condition attribute can be used with many elements in a project file. A condition can be used to enable or disable one property, for example, if the value of the Flavor property is DEBUG, the
DebugType property is defined:
<DebugType Condition="'$(Flavor)'=='DEBUG'">full</DebugType>
A condition can also be used at the
PropertyGroup level which enables or disables all the properties contained within it, for example:
<PropertyGroup Condition="'$(Flavor)'=='DEBUG'">
<DebugType>full</DebugType> <Optimize>off</Optimize>
</PropertyGroup> Property groups are especially useful when you want to apply the same condition to a large number of properties in a project file.
Four kinds of conditions can be used in a project file:
* equal
* not equal
* exists
* not exists
Condition Syntax
For all conditions, the evaluated text is enclosed in single quotes.
Evaluation of conditions is not case sensitive. The following conditions are equivalent in an MSBuild project file Condition="'$(Flavor)'=='DEBUG'"
and
Condition="'$(flavor)'=='debug'"
Equal Condition
Syntax:
Condition="'<some text>'=='<some text>'"
Example:
<DebugType Condition="'$(Flavor)'=='DEBUG'">full</DebugType>
Not Equal Condition
Syntax:
Condition="'<some text>'!='<some text>'"
Example:
<Optimize Condition="'$(Flavor)'!='DEBUG'">on</Optimize>
Exists Condition
Instead of evaluating text, the exists and not exists conditions use the file system to determine whether a file exists. The <text> must refer to an actual file location and name; otherwise the condition equals false.
Syntax:
Condition="Exists('<text>')"
Example:
<MyAppHasBuilt Condition="Exists('MyApp.exe')">yes</MyAppHasBuilt>
Not Exists Condition
Syntax:
Condition="!Exists('<text>')"
Example:
<MyAppHasBuilt Condition="!Exists('MyApp.exe')">no</MyAppHasBuilt>
Building a Project
To build the DEBUG version of this project, type:
msbuild consolehwcs1.proj /p:flavor=debug
To build the RETAIL version of this project, use:
msbuild consolehwcs1.proj /p:flavor=retail
Project Files
Download Code - C#Download Code - VB
Visual C# example
<Project [MSBuildVersion] = "2.0" [DefaultTargets] = "Compile" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<!-- The default flavor if an environment variable called Flavor is not set, or if the flavor is not specified on the command line -->
[<PropertyGroup>]
<Flavor Condition="'$(Flavor)'==''">DEBUG</Flavor>
[</PropertyGroup>]
<!-- Define the DEBUG settings -->
[<PropertyGroup] Condition="'$(Flavor)'=='DEBUG'">
[<DebugType>full</DebugType>]
<Optimize>no</Optimize>
[</PropertyGroup>]
<!-- Define the RETAIL settings -->
[<PropertyGroup] Condition="'$(Flavor)'=='RETAIL'">
[<DebugType>pdbonly</DebugType>]
<Optimize>yes</Optimize>
[</PropertyGroup>]
<!-- Set the application name as a property -->
[<PropertyGroup>]
[<appname>HelloWorldCS</appname>]
[</PropertyGroup>]
<!-- Specify the inputs by type and file name -->
[<ItemGroup>]
[<CSFile] Include = "consolehwcs1.cs"/>
[</ItemGroup>]
<Target Name = "Compile">
<!-- Run the Visual C# compilation using input files of type [CSFile] -->
<CSC Sources = "@(CSFile)"
DebugType="$(DebugType)"
Optimize="$(Optimize)"
OutputAssembly="$(appname).exe" >
<!-- Set the [OutputAssembly] attribute of the CSC task to the name of the executable file that is created -->
<Output [TaskParameter] = "OutputAssembly" [ItemName] = "EXEFile" />
</CSC>
<!-- Log the file name of the output file -->
<Message Text="The output file is @(EXEFile)"/>
</Target>
</Project>
Visual Basic example
<Project MSBuildVersion="2.0" [DefaultTargets] = "Compile" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" >
<!-- The default flavor if an environment variable called Flavor is not set, or if the flavor is not specified on the command line -->
[<PropertyGroup>]
<Flavor Condition="'$(Flavor)'==''">DEBUG</Flavor>
[</PropertyGroup>]
<!-- Define the DEBUG settings -->
[<PropertyGroup] Condition="'$(Flavor)'=='DEBUG'">
[<DebugType>full</DebugType>]
<Optimize>no</Optimize>
[</PropertyGroup>]
<!-- Define the RETAIL settings -->
[<PropertyGroup] Condition="'$(Flavor)'=='RETAIL'">
[<DebugType>pdbonly</DebugType>]
<Optimize>yes</Optimize>
[</PropertyGroup>]
<!-- Set the application name as a property -->
[<PropertyGroup>]
[<appname>HelloWorldVB</appname>]
[</PropertyGroup>]
<!-- Specify the inputs by type and file name -->
[<ItemGroup>]
[<VBFile] Include = "consolehwvb1.vb"/>
[</ItemGroup>]
<Target Name = "Compile">
<!-- Run the Visual Basic compilation using input files of type [VBFile] -->
<VBC Sources = "@(VBFile)"
DebugType = "$(DebugType)"
Optimize = "$(Optimize)"
OutputAssembly="$(appname).exe" >
<!-- Set the [OutputAssembly] attribute of the VBC task to the name of the executable file that is created -->
[<OutputItem] [TaskParameter] = "OutputAssembly" Type = "EXEFile" />
</VBC>
<!-- Log the file name of the output file -->
<Message Text="The output file is @(EXEFile)"/>
</Target>
</Project>