| < Day Day Up > |
|
Developers have recognized the benefits of build automation and daily builds for a long time. That’s one reason there are many build tools out there to choose from. Some are XML based, others graphical, and they range in price from free up to several hundred dollars. In this section, I’ll survey the build tools I’ve found that work with .NET applications. To give you a feel for how they work, I’ll implement a very stripped-down build process for Download Tracker with each tool:
Get the latest source code from Vault to a clean directory.
Compile all of the code in the various projects (DBLayer, DownloadEngine, DownloadEngineTests, DownloadTracker, DownloadTrackerTests, DTInterfaces, and DTLogic) in both debug and release mode.
Execute the unit tests in both DownloadEngineTests and DownloadTrackerTests.
Produce a report on the build.
I’ll cover the tools in alphabetical order so as not to play favorites:
Daily Build
FinalBuilder
Hippo.NET
NAnt
Visual Build Professional
I’m not including any Microsoft solutions in this list, even though Microsoft has tried several times to produce a build utility for .NET. That’s because the Microsoft offerings are not yet sufficiently flexible for most developers to use. One alternative is BuildIt, available from http://msdn.microsoft.com/library/en-us/dnbda/html/tdlg_app.asp. Unfortunately BuildIt can only use Microsoft Visual SourceSafe for source code control, which rules it out for many developers. There are also the .NET Solution Build & Deployment Process & Tools (www.gotdotnet.com/Community/UserSamples/Details.aspx?SampleGuid=2cb20e79-d7064706-9ea0-26188257ee7d), a Microsoft community effort that still has lots of rough edges. Microsoft should become a more credible player with the release of VS .NET “Whidbey” in late 2004, which is slated to include an integrated build tool as part of VS .NET. This tool, MSBuild, is apparently patterned closely on NAnt, which I’ll discuss later in the chapter. But since NAnt is an open-source tool, Microsoft refuses to even consider it as part of its officially endorsed process.
Note | Although I’m not impressed with the public Microsoft build tools, its advice on the build process is well worth reading. “Team Development with Visual Studio .NET and Visual SourceSafe,” from the Patterns & Practices group, is an excellent set of prescriptive processes for those using all-Microsoft tools, You can get it from http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnbda/html/tdlg_rm.asp. |
The tools I’m looking at here are the ones that I think are affordable for the single developer or small team. Other build tools are available that are aimed at much more complex projects. These enterprise build tools carry a price tag to match, typically thousands of dollars. Tools in this class include OpenMake (www.openmake.com), which uses a distributed architecture and a knowledge base server to handle builds of both Java and .NET applications, as well as many other types of software, and Merant Build (www.merant.com), which handles many software environments and integrates with Merant’s other software configuration management tools.
Daily Build, from Positive-g (www.positive-g.com/dailybuild/index.html) is the simplest of the graphical build tools I’ve seen. I’m including it in this list because it’s affordable ($85) and it can manage just about any build process. But it does this by letting you identify Windows executables and supply command lines for them. Much of what you could do with Daily Build you could also do with a well-written batch file. Figure 13.1 shows the Daily Build interface.
Figure 13.1: Daily Build
Of course, there are at least a few advances over batch files here. You can use indenting and grouping to organize your build as a tree, making it a bit easier to keep track of what’s going on. Daily Build can also collect the output from the entire build into a single log file, so you get a record of what went on. And it installs a command-line e-mail tool to allow you to hook up notifications (by authoring more command-line tasks, that is).
Daily Build works out to be a pretty solid automation tool for any sort of repetitive set of tasks, not just builds. However, plenty of other tools have more direct integration with .NET.
Atozed Computer Software’s FinalBuilder 2.0 (www.atozedsoftware.com/finalbuilder/) is a professional graphical build tool, with pricing starting at €299. Figure 13.2 shows the DownloadTracker build project open in FinalBuilder, displaying the results of a successful build.
Figure 13.2: FinalBuilder
To set up a build script with FinalBuilder, you drag and drop actions from the Action Types window to the Main window. An action might be as simple as copying a file, or checking something out of source code control, or calling a compiler. Each action has properties that dictate exactly what it does, which you can view with the Action Inspector. If you need further customization, FinalBuilder supports a rather complete scripting language. For example, I’ve used scripting to put custom messages into the build log, to calculate a version number based on information stored in an external file, or to construct the text of an e-mail to developers on my team.
Actions can be arranged into action lists and then called from other scripts (like adding subroutines to your build processes). You can set up variable watches to keep an eye on what’s happening inside of complex scripts.
FinalBuilder derives a lot of ease of use from its extensive selection of actions. When you’re using an action for something like a VS .NET build, you don’t have to work out the proper command line yourself; you just specify the solution file and the configuration and FinalBuilder does the rest. Version 2.0 includes 19 groups of actions:
CD Burning actions that can directly produce a CD-ROM at the end of the build process
Compiler actions for project types, including VS .NET, Visual Basic, Delphi, and Java
CVS actions for working with the CVS source code control system
File and directory actions for manipulating the file system
Help Compiler actions for building help files
Install Builder actions for building setup files
Internet actions that can automate FTP, HTTP, Telnet, and other protocols
Licensing Tools actions that use popular tools for applying licenses
Miscellaneous actions, including user prompting, looping, and XSLT transformations
Perforce actions for working with the Perforce source code control system
Registry and INI actions that can read and write to Registry and INI files
SourceSafe actions for working with the Visual SourceSafe source code control system
SQL Server actions for automating Microsoft SQL Server
StarTeam actions that work with the StarTeam source code control system
Team Coherence actions that work with the Team Coherence source code control system
Testing Tool actions that can launch a variety of tools from AutomatedQA
Vault actions that work with the Vault source code control system
Windows actions for executing programs, using WMI, controlling services, and other purposes
Zip actions for working with Zip-format archives
If that’s not enough, there’s an API for building further actions (though you’ll need to use Borland Delphi to do so) and some newsgroups that support users who are aiming for that level of customization. For example, if you use a help compiler that FinalBuilder doesn’t support natively, you could create an action to call that compiler. Your custom action will integrate with the user interface and the FinalBuilder engine just like native actions do. The Windows action group contains actions for running either DOS programs or Windows executables, so you don’t need a custom action if you want to call a new tool that has a command-line interface.
Overall, I’ve been quite impressed with FinalBuilder as a build tool. One nice touch is that it can produce XML log files, which are ideal for including as web output from your daily builds.
Hippo.NET is an open-source project (http://hipponet.sourceforge.net/) specifically for .NET projects. It uses a client/server model so that your entire team can share a single build machine. The developers are planning to add continuous integration features (I’ll discuss continuous integration later in the chapter). Unfortunately, I wasn’t able to test Hippo.NET with Download Tracker, because the tool assumes that you’re using Visual SourceSafe for your source code control system. Being focused strictly on building the software, it’s also less flexible than the other tools I’ve considered here. Still, the price is right, and the support for build machines could be useful if you’re using all-Microsoft tools.
NAnt is a well-developed open-source build tool for .NET applications. You’ll find its home page at http://nant.sourceforge.net/ and some additional content that hasn’t yet made it into the main project at http://nantcontrib.sourceforge.net/. NAnt is based on the similar Ant build tool for Java applications, and like Ant, it has no user interface. You create a NAnt build file by writing XML using the tool of your choice, and execute it from the command line. Here’s a build file for the parts of Download Tracker that I’ve been looking at in this chapter:
<project name="DownloadTracker" default="debug"> <target name="compile"> <vaultgetfile url="http://www.larkfarm.com" username="Mike" password="xxxx" repository="DownloadTracker" file="$\Code" /> <vaultgetfile url="http://www.larkfarm.com/" username="Mike" password="xxxx" repository="DownloadTracker" file="$\Tests /> <csc target="library" output="./DownloadEngine/bin/Debug/DownloadEngine.dll" debug="${debug}"> <sources> <includes name="./DownloadEngine/*.cs" /> </sources> </csc> <csc target="library" output="./DownloadEngineTests/bin/Debug/DownloadEngineTests.dll" debug="${debug}"> <sources> <includes name="./DownloadEngineTests/*.cs" /> </sources> <references> <includes name="E:/Program Files/NUnit V2.1/bin/nunit.framework.dll" /> <includes name="./DownloadEngine/bin/Debug/DownloadEngine.dll" /> </references> </csc> <csc target="library" output="./DTinterfaces/bin/Debug/DTInterfaces.dll" debug="${debug}"> <sources> <includes name="./DTInterfaces/*.cs" /> </sources> <references> <includes name="./DownloadEngine/bin/Debug/DownloadEngine.dll" /> </references> </csc> <csc target="library" output="./DTLogic/bin/Debug/DTLogic.dll" debug="${debug}"> <sources> <includes name="./DTLogic/*.cs" /> </sources> <references> <includes name="./DTinterfaces/bin/Debug/DTInterfaces.dll" /> <includes name="./DownloadEngine/bin/Debug/DownloadEngine.dll" /> </references> </csc> <csc target="library" output="./DBLayer/bin/Debug/DBLayer.dll" debug="${debug}"> <sources> <includes name="./DBLayer/*.cs" /> </sources> <references> <includes name="./DTinterfaces/bin/Debug/DTInterfaces.dll" /> <includes name="./DownloadEngine/bin/Debug/DownloadEngine.dll" /> </references> </csc> <csc target="exe" output="./DownloadTracker/bin/Debug/DownloadTracker.exe" debug="${debug}"> <sources> <includes name="./DownloadTracker/*.cs" /> </sources> <references> <includes name="E:/WINDOWS/Microsoft.NET/Framework/v1.1.4322/ Microsoft.VisualBasic.dll" /> <includes name="./DTinterfaces/bin/Debug/DTInterfaces.dll" /> <includes name="./DownloadEngine/bin/Debug/DownloadEngine.dll" /> <includes name="./DBLayer/bin/Debug/DBLayer.dll" /> <includes name="./DTLogic/bin/Debug/DTLogic.dll" /> </references> </csc> <csc target="library" output="./DownloadTrackerTests/bin/Debug/DownloadTrackerTests.dll" debug="${debug}"> <sources> <includes name="./DownloadTrackerTests/*.cs" /> </sources> <references> <includes name="./DTinterfaces/bin/Debug/DTInterfaces.dll" /> <includes name="./DownloadEngine/bin/Debug/DownloadEngine.dll" /> <includes name="E:/Program Files/NUnit V2.1/bin/nunit.framework.dll" /> <includes name="./DTLogic/bin/Debug/DTLogic.dll" /> </references> </csc> <nunit2> <formatter type="Plain" /> <test assemblyname= "./DownloadEngineTests/bin/Debug/DownloadEngineTests.dll" /> </nunit2> <nunit2> <formatter type="Plain" /> <test assemblyname= "./DownloadTrackerTests/bin/Debug/DownloadTrackerTests.dll" /> </nunit2> </target> <target name="debug"> <property name="debug" value="true" /> <call target="compile" /> </target> <target name="release"> <property name="debug" value="false" /> <call target="compile" /> </target> <target name="both"> <call target="debug" /> <call target="release" /> </target> </project>
Tip | NAnt does not support Vault out of the box, but there are Vault tasks for NAnt available from the public Vault server at http://vaultpub.sourcegear.com. |
NAnt uses tasks as a unit of work. A single NAnt task might invoke a compiler, send a mail message, or import a type library. NAnt supports dozens of tasks and NAntContrib adds dozens more, which makes it likely that this build tool can handle even your most complex projects. Table 13.1 shows the tasks that are included in NAnt 0.84, which is the current version as I write this.
Task | Summary |
---|---|
al | Invokes al.exe, the assembly linker. |
asminfo | Generates an AssemblyInfo file using the attributes given. |
attrib | Changes the file attributes of a file or set of files. |
available | Checks if a resource is available at runtime. |
call | Calls a NAnt target in the current project. |
cl | Compiles C/C++ programs using cl.exe. |
copy | Copies a file or set of files to a new file or directory. |
csc | Compiles C# programs. |
cvs-checkout | Checks out a CVS module to the required directory. |
cvs-update | Updates a CVS module in a local working directory. |
delay-sign | Signs delay-signed .NET Assemblies, or re-signs existing assemblies. |
delete | Deletes a file, fileset, or directory. |
description | A do-nothing task that lets you add comments to a build file. |
echo | Writes a message to the build log. |
exec | Executes a system command. |
fail | Exits the current build by throwing an exception. |
foreach | Loops over a set of items. |
get | Gets a particular file from a URL source. |
if | Allows conditional branching in a build file. |
ifnot | The opposite of the if task. |
include | Includes an external build file. |
jsc | Compiles JScript.NET programs. |
lib | Runs lib.exe, the Library Manager. |
license | Generates a .license file from a .licx file. |
link | Links files using link.exe. |
loadtasks | Loads tasks from a given assembly or all assemblies in a given directory or fileset. |
| Sends an SMTP message. |
mc | Compiles messages using mc.exe, the Win32 message compiler. |
midl | Runs the IDL compiler, MIDL.exe. |
mkdir | Creates a directory or directory hierarchy. |
move | Moves a file or set of files to a new file or directory. |
nant | Runs NAnt on a supplied build file. This can be used to build subprojects. |
nantschema | Creates an XSD file for all available tasks. |
ndoc | Runs NDoc to create documentation. |
nunit | Runs tests using the NUnit V1.0 framework. |
nunit2 | Runs tests using the NUnit V2.1 framework. |
property | Sets a property in the current project. |
rc | Invokes rc.exe, the Win32 resource compiler. |
readregistry | Reads a value or set of values from the Windows Registry into one or more NAnt properties. |
regex | Sets project properties based on a regular expression. |
regsvcs | Installs or removes .NET Services. |
resgen | Converts files from one resource format to another. |
script | Executes the code contained within the task. |
servicecontroller | Allows a Windows service to be controlled. |
sleep | Delays the build for a specified time. |
solution | Compiles VS .NET solutions (or sets of projects), automatically determining |
project | dependencies from inter-project references. |
style | Processes a document via XSLT. |
sysinfo | Sets properties with system information. |
tlbexp | Exports a .NET assembly to a type library that can be used from unmanaged code (wraps Microsoft’s tlbexp.exe). |
tlbimp | Importsa typelibraryto a.NET assembly (wraps Microsoft’s tlbimp.exe). |
touch | Touches a file or set of files to update their file time. |
tstamp | Sets properties with the current date and time. |
unzip | Extracts files from a zip file. |
vbc | Compiles Visual Basic .NET programs. |
vjc | Compiles Visual J# programs using vjc, the J# compiler. |
xmlpeek | Extracts text from an XML file at the location specified by an XPath expression. |
xmlpoke | Replaces text in an XML file at the location specified by an XPath expression. |
zip | Creates a zip file from a specified fileset. |
NAnt is extremely powerful, and it’s the closest thing there is to a standard build utility for open-source projects. On the downside, no good tools are available yet for writing NAnt build files. You need to be comfortable writing XML files by hand to make effective use of NAnt. Personally, I prefer using one of the graphical build tools. Then again, I like trackballs better than mice, too.
Kinook Software’s $295 Visual Build Professional 5.1 (www.kinook.com/index.html) offers another full IDE for managing complicated build processes, as shown in Figure 13.3.
Figure 13.3: Visual Build Professional
In addition to dozens of built-in actions (including the ability to run arbitrary Windows programs as part of your build process), Visual Build Professional has a full macro language for custom programming. A nice touch is the explicit provision of failure steps, to be executed if something goes wrong in the main build. For example, you could roll back any changes you made to a data file, or undo a checkout of a file you’d planned to update, as part of the failure steps.
Visual Build Professional supports nine broad groups of actions, each with several different actions:
Built-in actions include writing a log message, running an external program, and grouping actions together.
Borland actions let you build Delphi or JBuilder projects.
Files actions include copying files, transforming XML logs, writing to INI files, and managing zip files.
Installer actions let you invoke common setup applications, such as InstallShield or Wise.
Microsoft actions build a variety of project types, such as VB6 or VS .NET. SourceSafe integration is also included in this action group.
Miscellaneous actions include Help & Manual compilation, writing to the Registry, or pausing for a set interval.
Network actions can communicate with FTP, e-mail, or Telnet.
Server actions can register COM or COM+ applications, install an assembly to the GAC, work with SQL, or interact with Windows services.
Version Control actions interact with CVS, Perforce, Surround SCM, or Vault.
You customize individual actions by filling in dialog boxes, so you’re protected from the details of the underlying software.
Unlike the other tools I’ve covered, Visual Build Professional offers some level of integration with VS .NET. In version 5.1 this is limited to launching Visual Build Professional from within VS .NET, which automatically creates a new action for compiling the current solution.
With its flexible programming and macro capabilities and good support for a variety of tools, Visual Build Professional is an excellent choice if you’re prepared to spend the money for a graphical build tool.
TECHNOLOGY TRAP: The Dirty Build
When you’re setting up your daily build process, you also need to consider where the process will take place. The temptation is to set up the builds on the same computer you use for development, because that’s most convenient. Unfortunately, there’s a trap lurking in that convenience.
If you use a development machine for builds, you lower the reliability and repeatability of the process somewhat. Suppose you ship out a build to beta-test customers on January 1, and then use the computer where the build was performed for other purposes, including daily web surfing and installing new software. When a bug comes in on February 1, you might find it difficult or impossible to re-create the build environment, and you won’t know exactly which versions of which libraries were installed on the build machine when you tested the beta build. Most of the time this won’t matter, but the times when it does matter the bugs can be subtle and hard to find.
Ideally, you’ll set up a dedicated build machine, with a carefully controlled software environment, that does nothing but build the software. If you can’t dedicate a physical computer to nothing but builds, set up a virtual machine with VMware or VirtualPC, and use that as your build computer.
| < Day Day Up > |
|