What NAnt Is Not
NAnt is not a magical solution. If proper software engineering techniques are not applied, NAnt can actually complicate a project. However, this could be said of any software engineering tool (such as Software Configuration Management). Even though NAnt is a powerful tool, it still requires good communication and organization of the development team. Everyone on the team should know NAnt, but at least one person on the team should specialize in NAnt and be the coordinator for the automated build.NAnt is not an XML version of MAKE (http://www.gnu.org/software/make/makel). NAnt and MAKE have similar goals and even some similar nomenclature; however, they really are more different than alike. A NAnt target is closest to a MAKE ghost target. A MAKE target is assumed to reside in a separate file. A NAnt target (see Figure 4-1) is assumed to exist in the same file as the project. NAnt creates target dependencies and allows the tasks (Figure 4-1) to determine the file dependencies. This is much different in MAKE.
Figure 4-1. Conceptual View of a NAnt Build File.

Standard Build Goals
Before I get too deep into NAnt and building, I thought I should take the time to clarify some terminology and define some of the philosophy I use in build projects. First, terminology. A build is an automated way of retrieving source code from a repository (normally Source Control Management or SCM), versioning both the code and SCM, compiling the code into product, and creating a redistributable package. The need for this to be automated and repeatable is paramount. If a feature is added or a bug fixed, the entire build process has to be restarted. In order to create a reliable product, the redistributable package must be created in the exact same way each time for the functionality to remain the same, except for the intentionally changed functionality for the feature or bug fix. To the users of a build, there are configurations and targets. Configurations could include a Release build optimized for execution speed, a Release build optimized for package size, a Release build with checked debugging information, or possibly a Debug build for developmental testing. Each of these build configurations is useful to achieve a specific goal. For instance, if a bug is very reproducible in a Release build and a developer can not reproduce it in a Debug build, then a Checked Release build with some debugging information could be helpful in tracking down the cause of the error. Switching between configurations should be simple and intuitive. Targets give the build user callable functionality, allowing the user to operate upon the build. A "build" target, for example, will allow the user to build the project in the specified configuration. Another useful target is "clean," which removes any output from the build. Some builds may even have an "install" target to create redistributables for the product. Second, the philosophy I use when creating a build is to make the build useful to the developer. For instance, I do not require the developer to build the entire product just to build his specific project. On a large product, a build could take hours. If a developer is working on a simple fix or a small project, do not require him to build for the entire project. Just let him build only what he needs by using the proper configuration and targets.