Building Multiple Projects
The simple CalcApp example isn't very reflective of many projects out in the real world. A number of today's applications are very complex in nature and are built by combining a number of componentized libraries. What happens when your entire application is spread across multiple solution files? With Visual Studio .NET, you would have to open each solution file and build it separately. With NAnt, you can define all of the build steps with a single build file!
With the simple CalcApp example, you have no doubt determined that the CalcLib class would be useful across multiple applications and you have probably decided to split them out into their own libraries. You then have two projects that comprise the application, CalcApp and CalcLib.
defines the build script for compiling both CalcApp and CalcLib, where CalcApp referencesand depends uponCalcLib. The dependency is defined by the depends
attribute on the <target>
tag. This tells NAnt that if it is instructed to execute the CalcApp task, it is guaranteed to execute the dependency task, which is, in this case, CalcLib.
In this build script, you separated the two projects into their own respective build tasks. Also, instead of relying upon a solution file, you have instructed NAnt to compile projects based upon their project definitions only (<project>
target tag). Another item of note is the reference to the assembly folders, designated by the <assemblyFolders>
target tag. In this case, CalcApp references the CalcLib library by file; therefore NAnt needs to be instructed where to pull this file from. If the <assemblyFolders>
is left out, NAnt attempts to locate the library from the HintPath
attribute in the Visual Studio .NET project file.
attribute within the Visual Studio project file specifies the location from which the referenced library was initially linked from. In most cases, the initial linked location isn't the proper place from which you want your libraries to be pulled, especially in an automated build scenario. The only way to change this value is to re-reference the library from its new location.
To execute the CalcAppWithLib.build
script, open a command prompt in the location of the build script and execute the following command:
C:\Code\CalcAppWithLib> nant build
In the output, you can see that the CalcLib target is executed first, followed by CalcApp, even though the configuration targets instruct NAnt to only build CalcApp. This is due to the depends
attribute defined on the CalcApp target to specify that CalcLib must be executed before CalcApp.
The NAntContrib Tasks
The NAntContrib project is another open-source effort that provides additional tasks for NAnt. The tasks provided through NAntContrib are the important tasks that haven't yet made it to the NAnt core tool. Some of these valuable tasks are defined in Table 6. Most notable of these are the administrative tasks, such as mkiisdir
, and gac-uninstall
, as well as several utility tasks for some of the more popular Source Control Management (SCM) tools such as Visual SourceSafe, Surround SCM, StarTeam, and PVCS.
Table 6: These are just some of the tasks available from NAntContrib.
Registers COM servers or type libraries
Installs assemblies into the global assembly cache
Uninstalls assemblies from the global assembly cache
Deletes a virtual directory from Internet Information Server (IIS)
Creates or modifies a virtual directory on Internet Information Server (IIS)
Registers an assembly for use from COM clients
Executes SQL statements against an OLEDB data source
Used to retrieve items from Visual SourceSafe
Used to apply a label to a Visual SourceSafe item
Generates code for XML Web service clients
Generates XML schemas or class files
To install the NAntContrib tasks, go to the NAntContrib project site
and download either the latest stable release or the latest nightly build. Extract the contents of the zip file onto your file system and copy the contents of the \bin
directory to NAnt's \bin
directory. From there, you can use any of the NAntContrib tasks in your build scripts.
Recommended Practices for NAnt
The following is a list of standard practices that I recommend for using NAnt in your build process:
Define a separate target for each major component of your application.
This allows you to build each piece independently.
Use properties to define a rich build script.
You can provide distinctly different build scripts (i.e., Debug vs. Release) with one .build file by modifying a few of your parameters. Create a target for each modification of these parameters.
Define a standard set of targets across your build scripts. I use the following common targets in my build scripts:
- Init: prepares the environment (creates directories, copies files, archives previous build directories, etc.)
- Clean: cleans the output directory
- Debug: sets up the property values for a debug build. These property values contain details such as the output directory (Debug vs. Release directory) and set the solution configuration to the appropriate environment.
- Release: sets up the property values for a release build
- All: calls all of the targets in a pre-defined order
- Docs: generates the application's documentation using NDoc
- vDist: distributes the compiled assemblies into the build server's distribution directory
NAnt is a great tool for automating the Visual Studio .NET build process. The open source efforts of the NAnt project provide a tool chest of tasks to create build scripts from the very simple to the exceptionally complex. It has certainly proved to a very valuable tool in my development process. With a little time invested, you will be able to institute an automated build process and free up the time to concentrate on what you want to be doingcoding.