Building .NET Applications with NAnt

key tool in any software development arsenal is a structured build process. NAnt is a tool for building Visual Studio .NET applications that you can incorporate into your development process and that provides something greater than simply compiling code.

In teams of developers, there is always going to be a need for a structured build process. This can be a manual process, but most likely you’ll want to automate this process as much as possible. In today’s ultra-fast world, continuous integration is key to determining where you are in your development project. If multiple developers check in code at various times, it is always a good thing to have an “integration check”?something to make sure all the code gels together.

The idea behind continuous integration is that when a developer checks code in, a process is triggered to perform a system build to make sure the code doesn’t break the build. This action usually involves the execution of unit tests as well. If the build, along with the unit tests, succeeds, the developer has immediate feedback that the check-in didn’t break the build. No one wants to be the person who broke the build!

The typical build process involves actions like these:

  • Pulling source updates from the source code repository
  • Preparing the build directories
  • Compiling the source code
  • Running the unit tests
  • Creating the setup packages
  • Deploying the output binaries
  • Notifying the team that a new build is available

If you incorporated Visual Studio .NET into a build process such as this, you would create an elaborate batch file that calls out to Visual Studio .NET’s command-line (devenv.exe) along with the additional tools to handle the tasks that .NET couldn’t. Another way to attack it may be to write some hooks into the .NET IDE automation model to handle some of these tasks during a build, but who has the time? The good news is that there are tools available built specifically to handle these types of build process requirements. One of the more popular build tools in the .NET community is NAnt.

NAnt
NAnt is an open-source build automation tool that works off of an XML document to execute a sequence of defined tasks that build .NET applications. NAnt is a port of the popular Ant build tool from the Java community. Ant was created to address some of the deficiencies of older shell-based build tools such as make and nmake. If you’ve ever written make scripts, you will appreciate NAnt’s ease of use and its extensible architecture.

NAnt works well as an automated build tool. It supports compiling C#, Visual Basic .NET, C++, and J# files. It can compile these files against the .NET Framework platform [v1.x, V2.0 (Beta 1)] and Mono.

Installing NAnt
The first thing to incorporate NAnt into your build process is to get NAnt up and running on your computer. You can download the latest stable release or a recent nightly build from the project site. The nightly builds are typically very stable, but for the purposes of this article, I will work with the latest stable release at the time of this writing, NAnt v.0.85-rc1.

Once you’ve downloaded the zip package, unzip the contents into a directory on your file system. To make it easier for you to execute your NAnt build scripts, place the location of NAnt’s in directory into your system’s PATH environment variable. You can test your installation by opening a command shell and typing nant -help at the command prompt. If everything is successful, you will see a list of command-line options for the NAnt build tool.

The NAnt Build Script
Executing the build script is as simple as typing in “nant” at the command prompt. NAnt probes its current directory (the directory from which it was executed) for any file ending in .build, and attempts to execute it. If more than one file within the directory ends in .build, NAnt throws an exception unless one of the files is named default.build. You can also inform NAnt which script you wish to execute by specifying the -f flag:

   C:> nant -f:MyApp.build

The NAnt build script is an XML document comprised of one tag, and zero to many tags with each containing a set of tasks to execute. To make it a little easier to digest the terminology, you can think of a as a method call and a task as a command.

Each element type in a NAnt build script (the project, target, tasks, etc.) has a defined set of attributes associated with that particular type. Some of these attributes are required and others are optional. These attributes provide additional details about how to execute each particular type.

To better understand the build script, it is wise to get a better understanding of the main parts of any build script.

Properties
A build script can contain zero to many property definitions. A property in NAnt is analogous to a variable. You define a property by the use of a tag with a name and value attribute.

   

To access a property value, you place the name of the property between the identifiers ${“ and “}. For example, to access the src.dir property declared earlier, specify the following:

   

Default property values are defined within the build script. If you need to override any property value, you can specify the -D command-line flag and supply the new property value.

   C:> Nant ?D:src.dir=NotTheDefaultSourceDirectory

Properties can be set as read only by setting the Readonly attribute on the tag to True.

   

You can create property values that are global to all build scripts on your computer by defining the property definitions in NAnt’s configuration file (nant.exe.config, found in the NAnt in directory) under the configuration section as shown below.

            ...               ...                                                

NAnt has a few built-in properties that can be used within your build script; a sampling of these properties can be found in Table 1.

Table 1: These are a sampling of built-in NAnt properties.

Property

Description

nant.project.basedir

The absolute path of the project’s basedir

nant.project.buildfile

The absolute path of the buildfile

nant.settings.currentframework

The current target framework

nant.settings.currentframework.sdkdirectory

The SDK directory of the current target framework

Tasks
Tasks define a command to be executed. Tasks are XML elements with a set of defined attributes and child elements that prescribe the options for the task. For example, if you want to execute a command to delete a directory, use the task.

   

The dir attribute is specific to the task and sets the option for the task to delete the directory named bin. The Failonerror attribute is common to all tasks. If the task fails, the build also fails, although there are some cases where a failed task doesn’t necessarily mean the build fails. The default value is True.

If you want your build script to send an e-mail to the development team when the build completes, you could use the task.

                                          

Tasks define the power of NAnt. There are over 70 tasks included in the NAnt core tool. A small sampling of some the available tasks is listed in Table 2. Additional tasks are available through external libraries, such as NAntContrib. If the available tasks don’t quite get the job done, you can create custom tasks through the extensible architecture.

The NantContrib project provides an assortment of additional tasks for NAnt build scripts.

Table 2: These are just some of the tasks available in the NAnt core tool.

File System Tasks

Description

Copies a file or set of files to a new file or directory

Deletes a file, a set of files or a directory

Creates a directory

Modifies file attributes

?.NET Tasks

Description

Compiles Visual Basic .NET files

Compiles C# files

Compiles Visual Studio .NET solutions (or sets of projects). Determines project dependencies from inter-project references

Imports a type-library to a .NET assembly

Installs or removes .NET Services

?Misc Tasks

Description

Sends an STMP message

Creates a zip file from the specified file list

Extracts a zip package

Runs NDoc to create the documentation

Runs tests using the NUnit v2.2 framework

Although each task has its own custom attributes defined to support its execution, every task has a common set of attributes. These are listed in Table 3.

Table 3: These are task common attributes.

Attributes

Description

failonerror

If set to True, stops the build if this task fails. Otherwise, it just reports.

if

An expression that should evaluate to True for this target to execute

unless

An expression that causes the target to be skipped when it evaluates to True

verbose

Determines whether the task will report detailed log messages

Targets
The tag defines a collection of tasks to execute. They usually represent a particular step in the build process and can have dependencies on other targets. The If and Unless attributes allow for conditional target execution. When the If attribute is defined, the target only executes if the expression evaluates to True. If the Unless attribute is defined, the target is skipped when the Unless expressions evaluates to True.

Targets can be dependent on other targets. For example, if within the build script you want to clean out the output directory before the build, you might define something like this:

                           

By specifying a dependency with the Depends attribute, the target will not execute until all of its dependency targets have executed first. One of the nice features of NAnt is that it executes a target only once. So if multiple targets have a dependency on the same target, that dependent target executes only once.

                                       ...   

Table 4 lists the attributes and the descriptions for the tag. Only the Name attribute is required.

Table 4: Here’s a list of attributes.

Attributes

Description

name

The name of the target

depends

A comma-separated list of names and targets on which the target depends

if

An expression that should evaluate to True for this target to execute

unless

An expression that causes the target to be skipped when it evaluates to True

description

A short description of the target’s purpose

Projects
The tag is the main container for the build script. The important element of the tag (other than allowing you to define a well-formed XML document) is the use of the Default attribute. When no target is specified on the command line execution of the build script, NAnt executes the target specified in the Default attribute. Table 5 lists the attributes and their descriptions for the tag. None of the attributes are required.

                                                      ...         ...   

Table 5: Here’s a list of attributes.

Attributes

Description

name

The name of the project

default

An expression that should evaluate to True for this target to execute

basedir

The base directory from which all paths are determined. If it isn’t specified, the build script’s parent directory is used.

Share the Post:
Share on facebook
Share on twitter
Share on linkedin

Overview

Recent Articles: