Introduction to NAnt

Posted by buildmeister on May 9th, 2006
Filed under:  tools  .NET  build scripting 
There are 0 comments on this article.
Bookmark and Share

Introduction

NAnt is a Microsoft .NET build tool, although based on Apache Ant (the de-facto standard for building Java projects) it is Not Ant (hence the name) and has subsequently evolved in its own unique way. Where Ant is Java-centric, NAnt is .NET-centric and has built in support for compiling C#, VB.NET, J# languages as well as for building Visual Studio .NET solutions. Since NAnt is written for the .NET platform it is also extensible via use of any .NET languages, allowing you to build on its features and facilities to integrate it with all manner of tools and systems.

All NAnt builds are driven by an XML formatted build file (the equivalent of a make “makefile”). By default this is typically called NAnt.build and located in the project root directory. However, there is no reason why a project can’t contain a number of build files of any given name. NAnt allows you to call or chain these files together, if for example you want to build recursively down a directory structure containing multiple projects.

The build file always references a single project, i.e. an application. The project has a number of targets that can be called. These targets are the core parts of a build process, i.e. compile, test, generate distribution (.zip or .msi) files, deploy and so on. Each of the targets can be called individually or they can be "chained" together as dependencies to orchestrate an end-to-end build. For example, to build a release version of an application you could use the following command line invocation:

>nant release

Each of the targets can make reference to any of NAnt's built-in tasks. A task is basically an interface to a .NET class written to carry out a predefined operation, i.e. compile a set of source files, delete a directory structure and so on. Attributes are specified for the tasks, defining their exact invocation. There are a large number of built-in tasks (see the NAnt manual for details), however since the tasks are interfaces to .NET classes, you can quite easily extend NAnt by creating new tasks yourself.

An Example

A simple example of an NAnt build file to compile and test a Visual Studio .NET solution is given below:

<?xml version="1.0"?>

<project name="NAntDemo" default="build">
    <property name="project.name" value="NAntDemo"/>
    <property name="project.version" value="1.0.0"/>
    <property name="dir.nunit" value="C:\Program Files\NUnit 2.2\bin"/>
    <property name="configuration" value="debug"/>

    <!-- remove generated files -->
    <target name="clean" description="remove all generated files">
        <delete>
            <fileset>
                <include name="**/bin/**" />
                <include name="**/obj/**" />
                <include name="**/*.user/**" />
            </fileset>
        </delete>
    </target>

    <!-- execute a debug build -->
    <target name="debug" description="execute a debug build">
        <property name="configuration" value="debug"/>
        <call target="test"/>
    </target>

    <!-- execute a release build -->
    <target name="release" description="execute a release build">
        <property name="configuration" value="release"/>
        <call target="test"/>
    </target>

    <!-- compile source code -->
        <target name="build" depends="clean" description="compile the source code">
        <solution configuration="${configuration}" solutionfile="${project.name}.sln" />
    </target>

    <!-- execute unit tests -->
    <target name="test" depends="build" description="run unit tests.">
        <exec program="${dir.nunit}\nunit-console.exe"
            commandline="${project.name}.nunit /xml=${project.name}-test.xml /nologo" />
    </target>

    <!-- run the application -->
    <target name="run" depends="test">
        <exec program="${project.name}.exe"
            basedir="${project.name}\bin\${configuration}\"/>
    </target>

</project>

In this example we have have a project named NAntDemo, there are six targets: clean, debug, release, build, test and run. Sometimes a target will have a dependency on another target, for example before you test an application, you would obviously need to build the application first! These dependencies are easily specified via a depends attribute in the target. We can see this with the test target on line 40 (where the target requires the build target to be executed first). NAnt will automatically execute any dependencies.

You will see that in the example on lines 4-7 we also makes reference to property values, properties are equivalent to variables in NAnt. Here they are being used to define directory names or project settings. You make references to properties by using the ${property_name} syntax (see line 34 for an example). An interesting feature of properties is that they can be overridden from the command line. For example, if you wanted to override the dir.build property, you could use the following:

>nant -D:dir.nunit=c:\tools\bin debug

To built this example, we are using the Nant <solution> task, which will basically use the .NET solution file specified and built all its projects and dependencies. For more flexibility you can execute the individual .NET compilers (such as the C# compiler using the <csc> task).

NAnt for Ant users

If you have used Ant before than NAnt should feel comfortable but as the NAnt web-site says "NAnt is only compatible with Ant in spirit". Some of the differences between the two tools are as follows:

  • Tasks in Nant 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.
  • The nant.onsuccess and nant.onfailure properties can be defined as explicit target names in NAnt, these will be executed at the end of the build on success or failure.
  • NAnt looks for the first file ending in .build instead of build.xml.
  • NAnt properties are by default read-write, although they can be read-only if desired
  • NAnt supports global properties that are defined in a central file
  • Nant supports embedded scripts that are defined in any .NET language

There are more differences, these are just the most obvious ones that you will probably encounter.

Summary

This article was intended as a rapid introduction to some of NAnt's capabilities. NAnt is a powerful but sometimes complex tool. Fortunately, there are many references, books and articles describing NAnt, some of these are detailed below.

References

Bookmark and Share

Comments

There are no comments on this article.

Back to Top

Submit a new comment

All fields in bold are required.