NAnt and Visual Studio .NET Project Files
Visual Studio .NET does a great job in maintaining the complexities of your application definitions and configuration: the library references, the global imports and, of course, the source files. It would be a shame to have to recreate those configuration items in your build script. Thankfully the NAnt development team has created the <solution>
task to allow for the use of Visual Studio .NET solution files in your build scripts.
task (see Listing 1
) can be used to wrap a number of separate projects into the same task for compiling or use an already defined solution file and its configuration details. NAnt can use the solution file to determine project dependencies. If the projects aren't necessarily part of the same solution, NAnt is able to determine the project dependencies based on the output file name.
It's important to note that the <solution>
task does not shell out to the Visual Studio .NET command line compile tool (devenv.exe) but uses the command-line compilers. With that, your build server doesn't require an installed instance of Visual Studio .NET, yet you're still able to use your project and solution definitions.
You're not limited to using a particular solution file in using the <solution>
task. You are able to define a set of projects to compile by specifying the <projects>
element. If you want to use a solution file that was already defined but don't necessarily want to compile every project, you can define which projects to skip by defining the <excludeprojects>
element. Use the <assemblyfolders>
element to provide hints to the compiler where it might find the reference DLLs. This is where you define the path(s) to your build server's output directory.
If your <solution>
task contains a Web project, you are required to define a mapping between the project URL and the project's file path. It's important to remember that the <map>
definition is case-sensitive. Be sure the URL
attribute value matches exactly (case for case) with what's defined in your Visual Studio .NET project file. I've been bitten by this one a number of times.
Pulling It All Together
To showcase the usefulness of a NAnt build script, I have created a simple WinForms project in Visual Studio .NET to add two digits together and display the result. The application consists of two source files defined within a Visual Studio .NET project file (CalcApp.vbproj
). Although the application itself isn't that exciting, the process of building it with NAnt is!
To define the build script for the CalcApp application, the first thing to do is create a text file with a .build extension, such as CalcApp.build
. Open the build file in your favorite text editor and define the <project>
<?xml version="1.0" encoding="utf-8" ?>
From there, you need to define a target responsible for building the WinForms application. Because you are using a Visual Studio .NET project to develop the application, you can use one of the core NAnt tasks, <solution>
, to compile the application.
<?xml version="1.0" encoding="utf-8" ?>
NAnt now has enough information to compile the application.
To kick off the NAnt build, open a command prompt in the location of your build script and execute the following command:
C:\Code\CalcApp> nant build
parameter on the NAnt command line tells Nant that you wish to execute the build target.
This particular build script is sufficient but it really doesn't bring out the power of NAnt. What happens if you want to pass in the option of performing a Release
build instead of a Debug
build? Or what if you want to compile the application into a different output directory than what's defined in the Visual Studio .NET project file?
improves on the simple build script by defining two additional tasks (Release and Build) that define property settings to let NAnt know how you wish to build the application. You've defined a variable named config
to store the configuration setting along with output.dir
to define the location of build output. Now you have the ability to perform a debug build and a release build without having to define two different build scripts.