MSBuild is an overcomplicated ripoff of NAnt, which is the open source .NET remake of Apache Ant which is a Java successor of Unix's Make, which is where the basic concepts came from.
Make’s concepts relevant to MSBuild
- command -- invokes a command-line tool
- target -- named sequence of commands
- dependency -- targets can depend on other targets
- Make is invoked on a make file with one or more target specified and it runs all dependencies recursively and then the target's commands.
- make files can include other make files for robust management of make structure
- make also supports creating named variables that will be substituted for parameters of commands
- also there are so called automatic variables that are assigned by the make itself (like current dir name/path etc.)
- A target will never run twice during a single build. Once run, a target is assumed to have completed its work and will not be run again, even if a subsequent target in the build depends on it.
Simplified example of make file:
target1: sub_target1
csc.exe a, b
copy b, c
sub_target1:
delete xyz
Ant’s concepts relevant to MSBuild
- Basically, Ant is an XML-based successor of Make, so most of Make concepts are still valid.
- The biggest difference (besides XML) is that commands are now called "tasks" and they not just invocations of command line processes, instead they execute actions built into the Ant itself.
- The variables are called "properties" (see NAnt section below for more details and example)
- The root of Ant build.xml file is <project> tag that specifies name and default target, the one executed if no target name was specified.
Simplified example of Ant build.xml file:
<?xml version="1.0"?>
<project name="Hello" default="compile">
<target name="clean" description="remove intermediate files">
<delete dir="classes"/>
</target>
<target name="clobber" depends="clean" description="remove all artifact files">
<delete file="hello.jar"/>
</target>
<target name="compile" description="compile the Java source code to class files">
<mkdir dir="classes"/>
<javac srcdir="." destdir="classes"/>
</target>
<target name="jar" depends="compile" description="create a Jar file for the application">
<jar destfile="hello.jar">
<fileset dir="classes" includes="**/*.class"/>
<manifest>
<attribute name="Main-Class" value="HelloProgram"/>
</manifest>
</jar>
</target>
</project>
NAnt concepts relevant to MSBuild
- NAnt files have .build extension
- Properties are referenced in task arguments like this: ${propertyname}
- Targets can have conditions that control their execution. The conditions are expressions that overlook properties.
- Expressions are formulas to be used in task arguments and conditions. Expressions can access properties and call built-in or user-defined functions.
- NAnt has global Nant.exe.config file where the global Properties are defined.
- Tasks do not have to be in a target. Tasks that appear directly in the project are executed in order before any tasks in targets are executed.
- NAnt can log the progress of build execution to a log file.
Sample NAnt .build file:
<?xml version="1.0"?>
<project name="Expression Test" default="test" basedir=".">
<property name="project.name" value="Expression Test"/>
<target name="test">
<echo message="Project name is ${project.name}."/>
</target>
</project>
Examples of tasks:
- call -- explicitly execute another target (different from dependency which only executes targets once and in no particular order)
- copy / delete / mkdir / move -- file system operations
- csc -- c# compiler
- exec -- executes an external program
- echo -- writes message to log
MSBuild concepts
- Main MSBuild file extension is .proj
- MSBuild tasks are similar to NAnt. For complete list look here: http://msdn.microsoft.com/en-us/library/7z253716(VS.80).aspx
- The tasks are actually imported from their CLR assemblies with UsingTask element like so:
<UsingTask TaskName="TaskName" AssemblyName = "AssemblyName"/>
- For those who feel the built-in tasks are not enough, there's a community project here: http://msbuildtasks.tigris.org/
- PropertyGroup -- allows properties to be defined using human-friendly format like so:
<PropertyGroup>
<ProductVersion>9.0.30729</ProductVersion>
</PropertyGroup>
- Compare this to NAnt syntax:
<property name="project.name" value="Expression Test"/>
- Item -- an object-oriented variant of property. While property is name/value, Item is name/object where object has multiple attributes.
- Properties are still referenced the Ant way, ${project.name} while Items are referenced via @(name)
- ItemGroups are NOT equivalents of Property groups for Items. Instead each ItemGroup is a collection of Items of one type -- e.g. it cannot have Items with different names.
<ItemGroup>
<Item1 Attribute1 = "file1" AnotherAttribue="x">
<Subitem1 abc="1"/>
</Item1>
<Item1 Attribute1 = "file2" AnotherAttribue="x"/>
</ItemGroup>
- Typical usage of ItemGroups is to list all files to be compiled. The collection of the file is then passed to CSC task using @{itemname} notation. Read the following link on using Items: http://msdn.microsoft.com/en-us/library/ms171453(VS.80).aspx
- There's a bunch of built-in properties. See this: http://msdn.microsoft.com/en-us/library/ms164309(VS.80).aspx
- For more conceptual info on MSBuild check this: http://msdn.microsoft.com/en-us/library/ms171451(VS.80).aspx
- For reference info, look here: http://msdn.microsoft.com/en-us/library/0k6kkbsd(VS.80).aspx
VS.NET-related MSBuild concepts
- VS.NET uses MSBuild 2.0 under the hood.
- MSBuild can also run VS .sln file, it generates .proj files from them. Using MSBuild 3.5 you can see that intermediate .proj file
- The C# project files .csproj are actually MSBuild .proj files but they also import Microsoft.CSharp.targets proj file to get most of functionality. (For a list of target files supplied with VS.NET, look here: http://msdn.microsoft.com/en-us/library/ms164312(VS.80).aspx)
- In fact MSBuild.exe recognizes any project file name extension matching the pattern .*proj ! (The .csproj files are also used by VS GUI to render the project items, so they are dual-purposed.)
- Clicking the Build command in Visual Studio will execute the default target in the project. Often, this target is also named Build. Choosing the Rebuild or Clean command will attempt to execute a target of the same name in the project. Clicking Publish will execute a target named PublishOnly in the project.
- To get IntelliSense support in Visual Studio before a build has generated an output assembly there must be a target named Compile w/ CSC task in it.
- When building inside Visual Studio, the property $(BuildingInsideVisualStudio) is set to true.
- Visual Studio attempts to execute targets with certain names when it loads a project. These targets include Compile, ResolveAssemblyReferences, ResolveCOMReferences, GetFrameworkPaths, and CopyRunEnvironmentFiles. Visual Studio runs these targets so that the compiler can be initialized to provide IntelliSense, the debugger can be initialized, and references displayed in Solution Explorer can be resolved. If these targets are not present, the project will load and build correctly but the design-time experience in Visual Studio will not be fully functional.
- Check out this page for more info on VS Integration: http://msdn.microsoft.com/en-us/library/ms171468(VS.80).aspx
TFS-related MSBuild concepts
- TFS uses MSBuild 3.5 under the hood.
- Check out this article on targets, properties and extensibility options: http://msdn.microsoft.com/en-us/library/ms400688(VS.80).aspx
- In TFS complete definition of a build is called "build type" (sort of like what "target" used to be back in Make days but now that it has become so overcomplicated we needed another abstraction that would symbolize one distinct use case)
- For each "build type" the following files control the build (the names are always the same, the differentiation works by pathname):
- TfsBuild.proj -- main MSBuild file
- TfsBuild.rsp -- the Response configuration file. Can be used to define custom loggers or override MSBuild properties.
- WorkspaceMapping.xml -- maps source control locations to local file system locations
- For detailed order in which targets are executed by TFS, check out this link: http://msdn.microsoft.com/en-us/library/aa337604(VS.80).aspx
That’s it for a quick catch-up, you’re on your own from now on. Happy catchupping!
Tags: