Skip to content
mhenry07 edited this page Aug 17, 2012 · 14 revisions

Getting Started

Albacore is a build system that is based on Ruby's Rake. Within it, you can use several different build 'tasks' that help you forge the build of your choice. To understand what kind of tasks and options you can use, you can take a look at the task pages, or follow this quick guide.

Rake Essentials

Rake's goal is to provide a task infrastructure and a ruby based DSL; it is smart enough to resolve dependencies, run several tasks and more.

Rake Files

By convention, the build tasks for your project will reside at your project root in a file called Rakefile. Rake will automatically find your file based on this naming convention, when run. (Note that you can vary the name to be rakefile, RakeFile, rakefile.rb, etc.) You can use any file name you wish and run rake with optional command line parameters to execute that file. However, the convention of rakefile and it's variants make it easy to spot the file that contains the build steps.

Rake Tasks

A rakefile is a collection of tasks - work to be performed. A rakefile is also a valid ruby script, meaning you can write any executable ruby code that you wish to use with your tasks, in this file. This allows you a lot of freedom and flexibility in creating your build scripts, compared to tools that use XML to define tasks, for example.

Here you can see a task default that depends on task test. Depends on, means test will be performed as a prerequisite to default. task :default => :test

A more typical task looks like below. In this form, a task can take a description with the desc annotation, and it can also take a body of code between the do..end keywords.

desc "Publish my blog."
task :publish do
  toto "publishing your article(s)..."
  `git push heroku master`
end

Running Rake Tasks

If you want to run a task, you command line to your project root and run rake mytaskname. In the example above (taken from toto blog engine) you would run rake publish.

Looking at your complete task list is accomplished via rake -T.

If you provide a task named default, as shown above, then you can run rake without any parameters and the default task will be executed. It is common practice to provide a default task that only depends on other tasks:

task :default => [:version, :build, :test]

Running rake against this rake file will generate version information, run the build process and execute the tests for the project (all of which will be detailed, below).

To close the loop with Albacore -- Albacore is a set of Rake tasks geared towards your build system. Every task is smart enough to make it a breeze for you to use it -- nothing much other than pasting the task into your own rakefile and tweaking the default parameters in its body.

Albacore Quick Start

You'd be amazed at how simple it is to create your build, to your own favorite customization levels. If you're used to things like tinkering with CC.Net / NAnt, you probably thought to put aside several hours -- if not a day for this.

The good (excellent) news are that setting your build will now take a few minutes, it will be maintainable and readable.

These examples are based on http://github.com/jondot/nchurn, a free and open source project run by Dotan Nahum. Feel free to look at that project - and many others on GitHub - for examples of albacore usage.

Lets start.

Installing Albacore And Dependencies

You'll need to have ruby installed on your system, first. Please check http://github.com/derickbailey/Albacore - main page of the project - for a list of supported versions of Ruby, and choose whichever is appropriate for you.

After you've installed Ruby, rake should already be present on your system as it is typically distributed with ruby. However, it may not be. If you are unable to run rake --version from a command prompt after installing ruby, you may need to install rake manually. To do this, run

gem install rake

or from a command prompt with IronRuby installed:

igem install rake

Albacore and it's dependencies can now be installed in the same way:

gem install albacore

or from an command prompt with IronRuby installed:

igem install albacore

In some cases, installing albacore via the gem system will not bring down the rubyzip dependency. If you get an error from your rakefile, or if you do not see that rubyzip was installed, run the following:

gem install rubyzip

or

igem install rubyzip

Now that we have albacore installed, we can create a simple rakefile and build script using that uses it.

Building Your Solution

Since we discussed rake and its Rakefile, lets make sure your configuration answers to that form. You should have a Rakefile in your project root (from where you'd want to run rake). Its content should include require 'albacore'.

desc "Build"
msbuild :build do |msb|
  msb.properties :configuration => :Release
  msb.targets :Clean, :Build
  msb.solution = "NChurn.sln"
end

Take a moment to realize, that here you'd only need to replace the msb.solution parameter with your own solution. That's it, try rake build (since task is called :build) and your solution will compile.

Versioning

So next thing you're thinking, how do I add a version to each build? Usually, projects link to an AssemblyInfo.cs file, which is located centrally somewhere at the root of your solution.
Knowing this, lets use the assemblyinfo task.

assemblyinfo :assemblyinfo do |asm|
  asm.version = bumper_version.to_s
  asm.file_version = bumper_version.to_s
  
  asm.company_name = "Paracode"
  asm.product_name = "NChurn"
  asm.copyright = "Dotan Nahum (c) 2010-2011"
  asm.output_file = "AssemblyInfo.cs"
end

Here I'm using bumper_version. This is a variable that comes from a ruby gem that would maintain your version in a typical VERSION file and make it available to your Rake script. Use what ever logic you see fit, just make sure asm.version and asm.file_version get a string indicating a version, such as 1.0.0.0. The rest of the detail are trivial to fill in.

Now lets use some Rake magic and modify the original build task to run only after generating the version because thats the logical thing to do.

desc "Build"
msbuild :build => :assemblyinfo do |msb|
  msb.properties :configuration => :Release
  msb.targets :Clean, :Build
  msb.solution = "NChurn.sln"
end

Notice the => :assemblyinfo I've added. Thats it, run rake :build and see it working.

Testing

Next thing to do would be to run your tests. I guess this may sum up the core things people look for in a build (but I'll go even further in a bit!).

desc "Test"
nunit :test => :build do |nunit|
  nunit.command = "Tools/NUnit/nunit-console.exe"
  #  nunit.options '/framework v4.0.30319'
  nunit.assemblies "NChurn.Core.Tests/bin/release/NChurn.Core.Tests.dll"
end

Two things you need to do here, is update the path to your nunit-console.exe, and your test assembly (where actual unit tests reside).

Notice that I'm already including a dependency :test => :build, because again, I want to test something I've just built.

Coverage

You're probably thinking this one is tricky. It's not, behold:

desc "Run a sample NCover Console code coverage"
ncoverconsole :coverage do |ncc|
  ncc.command = "Tools/NCover/NCover.Console.exe"
  ncc.output :xml => "test-coverage.xml"
  ncc.cover_assemblies 'NChurn.Core'

		
  nunit = NUnitTestRunner.new("Tools/NUnit/nunit-console.exe")
  #  nunit.options '/framework=4.0.30319', '/noshadow'
  nunit.options '/noshadow'
  nunit.assemblies "NChurn.Core.Tests/bin/debug/NChurn.Core.Tests.dll"
		
  ncc.testrunner = nunit
end

Again, modify ncc.command to your NCover.Console.exe instance, your coverage assemblies in ncc.cover_assemblies like above. The nunit part should be configured in the same fashion as your unit tests.

In here I'm using the free version of NCover (1.58b if not mistaken). Flawless.

Lets push further

We've probably covered your build almost entirely. At least to get up and running and making useful builds, all in a matter of minutes.

If you want to continue, we can push even more.

IL Merge

A common thing to do is to merge up your assemblies towards a single deliverable. Here is an example of running a task that doesn't come with Albacore but is dead simple to implement:

exec :merge do |cmd|
	cmd.command = 'tools\ilmerge\ilmerge.exe'
	cmd.parameters ='/out:NChurn\bin\release\NChurn.exe NChurn\bin\release\NChurn.CLI.exe NChurn\bin\release\NChurn.Core.dll NChurn\bin\release\CommandLine.dll'
	puts 'merged.'
end

Here I'm using the exec task, which can take commands and parameters and wraps them in Albacore love. The result of this task is a merged assembly; same pattern of specifying the tool location, in cmd.command and its parameters in cmd.parameters as you would when you'd physically use the tool on the command line.

Zip

A natural step would be to zip your deliverables. Here goes:

zip :zip => :output do | zip |
	zip.directories_to_zip "out"
	zip.output_file = "nchurn.v#{bumper_version.to_s}.zip"
	zip.output_path = File.dirname(__FILE__)
end

I think this one is so well constructed that by now, it reads naturally. A note about File.dirname(__FILE__) would be that it takes the current file and path from the special variable __FILE__ and extracts a directory name with File.dirname. You may use this pattern a lot so it's good to know.

Summing Up

I could go on, but i think for now I'll stop and encourage you to look at the tasks. There are tasks in the dozens developed from real requirements, so you're in good hands.

Thanks for following!.

Note: you can edit this page for corrections and post questions to the mailing list. If you feel the urge you can tweet me directly @jondot, and I'll try to help.