Build Tools Roundup For .NET Systems
It seems there is not shortage of build tools that are available for the .NET developer these days. Of course I’m quite partial to the Ruby + Rake + Albacore solution, being the big tuna behind albacore and all… but quite honestly that amount of choice makes me very happy. It seems there is a good tool for just about every different comfort zone in the .NET developer world. At this point in time, there’s not one right answer of which build tool to use. You don’t need to choose which tool to use based on what features and functionality it supports anymore. Rather, you can make the choices based on what your comfortable with – be it the runtime environment, the language to create build steps, the data specification, etc. Choice is good. Understanding what each choice offers is even better. Here’s my take on the current set of tools that I’m aware of and what the comfort zone of these tools are.
Nant: The Godfather Of .NET Build Systems
Runtime: .NET
Build Configuration Language: XML with extensions written in .NET
URL: http://nant.sourceforge.net/
Nant is the old-school guy on the .NET block, having grown up over on Java road. This is the original .NET build tool that so many others wanted to be or wanted to be better than. If you’ve used any build tools for more than a few years in .NET, you’ve probably used Nant at least once. There are a lot of extensions and add-ons to Nant, including a user contributions project, several visual tools designed to abstract away the xml, some conventions based add-ons that make nant easier, etc. If you need to do it in your build process, chances are there is a plugin or a blog post that tells you how to do it with Nant.
Nant was originally a copy of the Java Ant build tool but quickly took its own directions in implementation becoming the defacto build tool in .NET for several years. With it’s heavy reliance on xml and its roots tracing back to java, most “enterprise” developers chose Nant because of it’s familiarity from the Java world.
Example: Build a solution
1: <target name="compile">
2: <echo message="Build my solution!" />
3: <msbuild project="src/mysolution.sln">
4: <arg value="/property:Configuration=release" />
5: <arg value="/t:Rebuild" />
6: </msbuild>
7: </target>
</div> </div>
UppercuT: You Won’t Know What Hit You
Runtime: .NET (Nant) with extensions to call out to other platforms such as Ruby/Rake.
Build Configuration Language: None for simple builds. XML/Nant, Ruby, and Powershell for extended scenarios
URL: http://code.google.com/p/uppercut/
If you’re going to use Nant and you don’t need to do anything “unusual”, then you should be using UppercuT. This is an add-on that makes Nant so easy to use, you don’t even need to know how to use Nant. UppercuT makes good on it’s promises, too. It really is that easy to get a build up and running because you don’t need to know anything other than the basic conventions that it uses to find your solutions, tests, etc.
From the project’s homepage:
UppercuT is targeted at those who want all of the power and stability that Nant provides, but don’t want to deal with a ton of XML and build script definitions.
Example: No, really… this project makes building with Nant so easy, you don’t need to configure any tasks for most things. Check out the website for more information.
MSBuild: Bringing ‘One Microsoft Way’ To Your Build System
Runtime: .NET
Build Configuration Language: XML with extensions written in .NET
URL: http://msdn.microsoft.com/en-us/library/0k6kkbsd.aspx
Microsoft’s own build tool – if you’re using visual studio, you’re already using MSBuild. Unless you’re calling directly into the compiler for your language – such as csc.exe for c# – you are probably using MSBuild in your build process. With VS2005 and later, all .sln and .proj files are msbuild files… or, at least they can be interpreted by msbuild. MSBuild is more than just a solution builder for visual studio, though. It is a complete build system in the same vein as Nant. As much as I love to hate msbuild and it’s associated tools (such as Team Foundation Server and MSTest) I have to give Microsoft credit for getting a build tool into the hands of every .NET developer on the planet.
In recent years, MSBuild has become the standard build tool for shops that are not allowed to use open source, or want to stick with paid-for-support tools from Microsoft.
Example: Clean and build your solution (“borrowed” from RhysC)
1: <Project DefaultTargets="Clean" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="3.5">
2: <Import Project="$(MSBuildExtensionsPath)MSBuildCommunityTasksMSBuild.Community.Tasks.Targets"/>
3:
4: <PropertyGroup>
5: <ApplicationName>MySolutionApplicationName>
6: <SolutionFile>..$(ApplicationName).slnSolutionFile>
7: PropertyGroup>
8: <Target Name="Clean">
9: <MSBuild Targets="Clean" Projects="$(SolutionFile)"/>
10: Target>
11: <Target Name="Build" DependsOnTargets="Clean;" >
12: <MSBuild Targets="Rebuild" Projects="$(SolutionFile)" Properties="Configuration=Release;" />
13: Target>
14: </Project>
</div> </div>
Psake: The PowerShell Drink Of Choice
Runtime: Powershell / .NET
Build Configuration Language: Powershell Script (C#)
URL: https://github.com/JamesKovacs/psake
Psake (pronouced like the Japanese rice wine alcohol) is a suite of PowerShell scripts that lets you write .NET code as powershell scripts (.ps1 files) and modules. Since powershell is built into current versions of windows server and desktop operating systems, it is quick and mostly painless to get up and running. It leverages the existing command line knowledge and code writing capabilities of developers by integrating both of those skillsets into one solution. If you want a native windows command line that provides power and capbilties along the lines of a bash shell in *nix, with a build system geared toward the power user, powershell and Psake are your solution.
Example: Clean your solution then build it (“borrowed” from Alan Bradley)
1: task default -depends Build
2:
3: task Build -depends Clean{
4: msbuild "C:UsersAlanCodePowerShellpsakeHelloWorldHelloWorld.sln"
5: }
6:
7: task Clean {
8: msbuild "C:UsersAlanCodePowerShellpsakeHelloWorldHelloWorld.sln" /t:clean
9: }
</div> </div>
Rake: The ‘Cool’ Kid
Runtime: Ruby, IronRuby for .NET, JRuby for Java, etc
Build Configuration Language: Ruby / Rake DSL
URL: http://rake.rubyforge.org/
… I’ll be the first to tell you that I can’t give an objective opinion about ruby… so keep that in mind. 🙂
Ruby and Rake have been shaking up the .NET world for a few years now, with many of .NET’s best and brightest jumping ship away from the classic .NET build systems for this one. It seems that all the ‘alt’ kids and cool cats are heading for these green pastures and with Microsoft having released IronRuby v1.0 recently, there is even more potential for the popularity of this system in .NET. With the flexibility of the Ruby language, the built in gem system and the thousands of available libraries, the potential functionality within a rake build script is staggering.
Rake, like Psake, is targeted at the command-line-junky that wants to get things done quickly but doesn’t feel constrained to the Microsoft-only tools.
Example: Calling out to MSBuild to build a solution
1: task :default do
2: msbuild = "C:/Windows/Microsoft.NET/Framework/v3.5/msbuild.exe"
3: return_code = system "#{msbuild} src/example.sln /p:configuration=release /target:clean;build /asdfasdf"
4: fail "msbuild failed!" unless return_code == 0
5: end
</div> </div>
Albacore: Dolphin-Safe Rake Tasks For .NET Systems
Runtime: Ruby / Rake + various command line tools
Build Configuration Language: Ruby / Rake Tasks
… Do I really need to say anything, here? I suppose I should, being the big tuna behind this project. 🙂
Albacore is a suite of Rake tasks that targets the most common needs for .NET systems at build-time, including some configuration management and package & deployment tools. What started as a “hey wouldn’t it be cool if…” conversation has quickly turned into a growing community of contributors and users around the world. There’s a lot of cooperation between the albacore tasks and the other popular build systems, too, with tasks that call out to nant and msbuild for example. The UppercuT project even has rake / albacore integration built into it. This cooperation with other systems makes the choice of which tool to use less important, as you can use the right tool for the job at hand, all from one central location.
Albacore is targeted at the Rake users that want to get their .NET system builds up and running quickly, while still allowing the full flexibility and capabilities of the Rake system.
Example: Build and test a solution
1: require 'albacore'
2:
3: task :default => [:build, :unittests]
4:
5: msbuild :build do |msb|
6: msb.solution = "src/example.sln"
7: msb.targets :clean, :build
8: msb.properties :configuration => :release
9: end
10:
11: nunit :unittests do |nunit|
12: nunit.path_to_command = "nunit/nunit-console.exe"
13: nunit.assemblies "src/tests/bin/release/tests.dll"
14: end
</div> </div>
Bake: The Sexy Little DSL; and Phantom: So Simple, It’s Scary
Runtime: .NET
Build Configuration Language: Boo DSL for builds
URL: http://code.google.com/p/boo-build-system/ and https://github.com/JeremySkinner/Phantom
… At this point, I’m not sure about the state of this project or it’s adoption in the real world. Does anyone know if it’s still alive and/or being used anywhere? You may be better off looking at the Phantom build system, which is similar to Bake, but appears to be an active project.
Bake is “A build system written in Boo, inspired by Rake.”. It’s based on the Boo language – an object oriented DSL creation language for the .NET runtime. Also known as the “Boo Build System”, this particular project was subject to quite a bit of potty humor for a while, before being renamed to Bake. 🙂 The Boo language allows you to write your own Domain Specific Language (DSL) to run on the .NET platform, and Bake provides a DSL specifically for builds.
Bake and Phantom are targeted at the .NET developer that wants a simple DSL for creating builds, want a Rake like syntax, but want to keep the runtime dependency limited to the .NET platform.
Example: Using Phantom to build and test a solution
1: target compile:
2: msbuild(file: "path/to/somefile.sln", configuration: "release")
3:
4: target test:
5: test_assemblies = ("path/to/testassembly.dll", "path/to/AnotherTestAssembly.dll")
6: nunit(assemblies: test_assemblies, toolpath: "path/to/nunit.console.exe" })
</div> </div>
Fake: The Functional Build System
Runtime: .NET
Build Configuration Language: F#
URL: http://bitbucket.org/forki/fake/wiki/Home
Fake is the F# build system – a functional language that run on the .NET platform with a DSL for builds on top of it. Fake provides “all benefits of the .NET Framework and functional programming can be used, including the extensive class library, powerful debuggers and integrated development environments like Visual Studio 2008 or SharpDevelop, which provide syntax highlighting and code completion.”
Fake is targeted as developers who like the simplicity and elegance of a functional language and still want the powerful and capabilities of the .NET runtime and tooling.
Example: Running NUnit tests
1: (* define test dlls *)
2: let testDlls = !+ (testDir + @"/Test.*.dll") |> Scan
3:
4: Target? NUnitTest <-
5: fun _ ->
6: testDlls
7: |> NUnit (fun p ->
8: {p with
9: ToolPath = nunitPath;
10: DisableShadowCopy = true;
11: OutputFile = testDir + "TestResults.xml"})
</div> </div>
Make: The One. The Original.
Runtime: everywhere (usually associated with C/C++ though)
Build Configuration Language: Make files
URL (the best one I know of): http://en.wikipedia.org/wiki/Make_%28software%29
Make isn’t old-school… that’s like saying cave drawings are old school email letters or instant messages. No, Make isn’t old school… it’s the original. Make is the grand daddy of all the build systems and deserves our respect. Although I doubt that the original make system could do much more for a .NET developer than shell out to a command line tool, there are dozens (if not hundreds or thousands) of Make ancestors that are likely to be very capable in building .NET code. The namesake alone is still alive and well, with Rake – the “Ruby Make” system, Bake – the “Boo Make” system, Fake – the “F# Make”, etc. All of us – every developer that works in any modern language – owe a lot to Make for getting us started way back when. Whether or not you realize it, you are using a tool that has it’s roots in Make.
How Do I Know Which To Choose?!
With all of these options available making choices can be a daunting task. What it ultimately comes down to, though, is what you and your team are comfortable with. I love to push albacore as a build too for .NET as anyone that knows me will attest. However, I have also been known to say that it’s the wrong choice for some teams. Getting a build script and an automated build in place, combined with a Continuous Integration server, is the goal. Picking the build tool to do that is an implementation detail that should not get in the way of the goal. If your team does not have ruby / rake experience, albacore might not be the right tool for you. If your team does not like xml, Psake might be the right tool for you. You need to understand what your team is capable of today and what they want to be capable of tomorrow, to understand which tool is right for you.