A Build file is an XML file used to tell NAnt how to build a project. To see how NAnt processes build files, let's take a look at a very simple scenario -- building a small console application written in C#. Here is the program code:
public class HelloWorld
{
static void Main()
{
System.Console.WriteLine("Hello World!");
}
}
To produce the executable binary helloworld.exe, you can either use the C# command line compiler, or write a build file and let NAnt build it for you:
<?xml version="1.0"?>
<project
name="helloworld"
default="build">
<target name="build">
<csc
target="exe"
output="helloworld.exe">
<sources>
<include name="*.cs" />
</sources>
</csc>
</target>
</project>
NAnt will then parse the content of the build file and perform the specified tasks.
Of course, using NAnt for projects comprised of a single class like this is massive overkill. But what if you were interested in first building the executable, and then running it? Or what if you want to build one or more dependencies and then build the main executable? This is where NAnt can save loads of time.
A build file is primarily comprised of targets, tasks, and dependencies. A tasks is a single action you want NAnt to perform. Examples of tasks include running a compiler, copying or deleting files, sending emails, zipping up sets of files, etc. For a complete list of the tasks supported by NAnt, refer to the official user documentation.
A target represents a set of tasks you want NAnt to perform. Targets enable you to group tasks together logically. So if you want NAnt to delete the contents of the bin directory, compile five executables, and copy the result somewhere, these actions could be grouped together into a single target.
A dependency can be seen as a relationship between targets. For example, in the build file above there is a single target. Its name is build and it runs the compiler against a single source file. Setting the default attribute of the <project> tag to build causes the build target to be processed by default.
Now let's add a second target, one that will execute helloworld.exe after it is compiled:
<?xml version="1.0"?>
<project
name="helloworld"
default="run">
<target
name="build"
description="Builds HelloWorld">
<csc
target="exe"
output="helloworld.exe">
<sources>
<include name="*.cs" />
</sources>
</csc>
</target>
<target
name="run"
depends="build"
description="Runs HelloWorld">
<exec program="helloworld.exe" />
</target>
</project>
The new run target contains a single action, exec, which executes the program. It also contains a dependency on the build target. This means that before the run target will be executed, the build target must also be executed, and it must complete successfully. Note that the default attribute of the <project> tag has been changed to run. Because run depends on build, this ensures that the application will be built before it is run. If the build target fails, the run target won't be executed, and the compiler's error message is displayed to the console.
NAnt won't run the compiler if you have a compiled binary that's newer than the source code. In addition, if multiple dependencies exist in a build file, NAnt is smart enough to only build the dependent component once. But in some cases, you may want to wipe out all existing compiled binaries and perform a clean build:
<?xml version="1.0"?>
<project
name="helloworld"
default="run">
<target
name="build"
description="Builds HelloWorld">
<mkdir dir="bin" />
<csc
target="exe"
output="bin/helloworld.exe">
<sources>
<include name="*.cs" />
</sources>
</csc>
</target>
<target
name="clean"
description="Deletes compiled binaries">
<delete
dir="bin"
failonerror="false" />
</target>
<target
name="run"
depends="build"
description="Runs HelloWorld">
<exec program="bin/helloworld.exe" />
</target>
</project>
You probably don't want to run the clean target every time you build, but just every once in a while. To execute the clean target, type
nant clean
This causes NAnt to execute only the clean target. You can also see that in this version of the build file we have added a mkdir task to create a separate bin subdirectory, into which compiled binaries are deposited. To clean its contents and rebuild your project, type
nant clean build