In my last 7 years of my career, I mostly worked on Unix based builds. Now I got curious to explore Windows builds. I learnt the 2 prominent build assistants in Windows are MSBuild and Nant. In this blog, I will share my learning experience of MSBuild.
What is MSBuild?
MSBuild is the build platform for Microsoft and Visual Studio. Programming languages that target the .NET Framework, for example, Visual C# and Visual Basic, use MSBuild project files to describe and control the application build process. When you use Visual Studio to create an MSBuild project file, the appropriate XML is added to the file automatically.
Lets start by creating a simple C# file and compiling it through csc compiler. csc is a C# compiler, it comes along with .NET Framework (version 2.0, 3.5, or 4.0).
1) cd D:\HelloWorld
2) Create a file Helloworld.cs , with it's content as
using System;
class HelloWorld
{
static void Main()
{
#if DebugConfig
Console.WriteLine("WE ARE IN THE DEBUG CONFIGURATION");
#endif
Console.WriteLine("Hello, world!");
}
}
3) Very likely csc compiler location won't be in your path. Set it
set PATH=%PATH%;%WINDIR%\Microsoft.Net\Framework64\v2.0.50727
Alternatively, if you have Visual Studio installed, you can use the Visual Studio Command Prompt, which has a path that includes the MSBuild folder.
4) Compile it
csc Helloworld.cs
5) Test the application by typing Helloworld.exe at the command prompt
O/p: Hello, world!
6) Delete the application
del helloworld.exe
Now let's do the same thing using MSBuild project file. We are creating a minimal MSBuild project file and it's content will be saved in a file named "Helloworld.csproj".
<!-- root Project node -->
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<!--ItemGroup node contain item elements -->
<ItemGroup>
<!-- An item element that refers to the application source file. -->
<Compile Include="helloworld.cs" />
</ItemGroup>
<!-- A Target node to contain tasks that are required to build the application. -->
<Target Name="Build">
<!-- A Task element to start the Visual C# compiler to build the application. -->
<Csc Sources="@(Compile)"/>
</Target>
</Project>
Building the application using MSBuild project file
Command: msbuild Helloworld.csproj /t:Build
This builds the Build target of the Helloworld project file by invoking the Visual C# compiler to create the Helloworld application.
Output:
Microsoft (R) Build Engine Version 2.0.50727.42
[Microsoft .NET Framework, Version 2.0.50727.42]
Copyright (C) Microsoft Corporation 2005. All rights reserved.
Build started 2011-11-11 12:05:00 PM.
Project "D:\siddesh\learning-msbuild\HelloWorld\Helloworld.csproj" (Build target(s)):
Target Build:
C:\WINDOWS\Microsoft.NET\Framework64\v2.0.50727\Csc.exe /out:helloworld.exe helloworld.cs
Build succeeded.
0 Warning(s)
0 Error(s)
Time Elapsed 00:00:01.12
For detailed build, add flag
msbuild Helloworld.csproj /t:Build
/verbosity:detailed
Improving MSBuild project file - Properties
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<!-- PropertyGroup element is used to define variables/properties -->
<PropertyGroup>
<AssemblyName>MSBuildSample</AssemblyName>
<OutputPath>Bin\</OutputPath>
</PropertyGroup>
<ItemGroup>
<Compile Include="helloworld.cs" />
</ItemGroup>
<Target Name="Build">
<MakeDir Directories="$(OutputPath)" Condition="!Exists('$(OutputPath)')" />
<!-- The MakeDir task creates a folder that is named by the OutputPath property, provided that no folder by that name currently exists. -->
<Csc Sources="@(Compile)"
OutputAssembly="$(OutputPath)$(AssemblyName).exe" />
<!--This instructs the Visual C# compiler to produce an assembly that is named by the AssemblyName property and to put it in the folder that is named by the OutputPath property. -->
</Target>
</Project>
Improving MSBuild project file - Adding build targets
<Project
DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<!-- This sets the Build target as the default target. -->
<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>
<!-- The Clean target invokes the Delete task to delete the application. -->
<Target Name="Clean" >
<Delete Files="$(OutputPath)$(AssemblyName).exe" />
</Target>
<!-- The Rebuild target does not run until both the Clean target and the Build target have run. -->
<Target Name="Rebuild" DependsOnTargets="Clean;Build" />
</Project>
Testing:
1)
msbuild helloworld.csproj /p:AssemblyName=Greetings
MSBuild runs the default Build target. The /p switch overrides the AssemblyNameproperty and gives it the new value, Greetings. This causes a new application, Greetings.exe, to be created in the \Bin\ folder.
2) msbuild helloworld.csproj /t:clean
This runs the Clean task to remove the application that has the default AssemblyName property value, MSBuildSample.
3) msbuild helloworld.csproj /t:clean /p:AssemblyName=Greetings.
This runs the Clean task to remove the application that has the given AssemblyName property value, Greetings.
4) msbuild
Although a project file is not specified, MSBuild builds the helloworld.csproj file because there is only one project file in the current folder.
Reference: http://msdn.microsoft.com/en-us/library/dd576348.aspx