Ayende @ Rahien

My name is Oren Eini
Founder of Hibernating Rhinos LTD and RavenDB.
You can reach me by phone or email:


+972 52-548-6969

, @ Q c

Posts: 18 | Comments: 66

filter by tags archive

Introducing Boobs: Boo Build System

time to read 2 min | 332 words

I hate XML, a long time ago, I also hated XML, but I also had some free time, and I played with building a build system in Boo. To match NAnt, I called it NUncle.

It never really gotten anywhere, but Georges Benatti has taken the code and created the Boo Build System. I am just taking a look, and it is fairly impressive. It has the concept of tasks and dependencies between them, as well as action that it can perform.

Here is a part of Boobs' own build script:

Task "build boobs", ["build engine", "build extensions"]:
	bc = Booc(
		SourcesSet   : FileSet("tools/boobs/**/*.boo"),
		OutputFile   : "build/boobs.exe"

Task "build engine":
		SourcesSet  : FileSet("src/boobs.engine/**/*.boo"),
		OutputFile  : "build/boobs.engine.dll",
		OutputTarget: TargetType.Library 

Task "build extensions", ["build io.extensions", "build compiler.extensions"]

Task "build io.extensions":
		SourcesSet  : FileSet("src/extensions/boobs.io.extensions/**/*.boo"),
		OutputFile  : "build/boobs.io.extensions.dll",
		OutputTarget: TargetType.Library 

Task "build compiler.extensions":
	bc = Booc(
		SourcesSet   : FileSet("src/extensions/boobs.compiler.extensions/**/*.boo"),
		OutputFile   : "build/boobs.compiler.extensions.dll",
		OutputTarget : TargetType.Library 

I don't know about you, but this makes me feel very nice.

The concept is pretty obvious, I feel, and the really nice thing is that extending it is a piece of cake. Here is how you validate dates of two files:

def IsUpToDate(target as string, source as string):
	return true unless File.Exists(source)
	return false unless File.Exists(target)

	targetInfo = FileInfo(target)
	sourceInfo = FileInfo(source)
	return targetInfo.LastAccessTimeUtc >= sourceInfo.LastAccessTimeUtc

And its usage:

Cp("source.big", "dest.big") if not IsUpToDate("source.big", "dest.big")

Or, you know what, this is fairly routine, and it comes as part of the standard library for Boobs. Let us create something new, ConditionalCopy:

def ConditionalCp(src as string, dest as string):
	Cp(src, dest) if not IsUpToDate(src, dest)

Usage should be clear by now, I hope.


Aaron Erickson

nice... only issue... how do you google for help on boobs without... ahem... throwing all the red flags up on the corp firewall?

Pierre Henri Kuaté

Damn, somebody has beaten me at the first joke about ... boobs :)

What are the odds of a software being (unintentionally) called like that? Scott Adams would like that.

On a little bit more serious tone: Is it really necessary to add the word "Set" at the end of "SourcesSet" and "ReferencesSet"?

Georges Benatti


As a Brazilian, I had no problem choosen that name to the project, but i can't really say that it was unintentional.

In a serious note, if it gets used, may be we should change the name.

Chris Carter

don't change the name! it's hilarious, I need to be able to put that on my resume and use it in interviews.

Interviewer: "What experience do you have?"


Interviewer: "Did you say boobs?"

Me:"Yep. I have extensive experience in Boobs, some would even say that I'm an expert"


Try this, it's a __very simple Google CSE to start with. Iit's just a beginng, but everyone can contribute ;) !

Georges Benatti



As a note, there are Tasks, and FileTasks, just like Rake,

so a conditional copy can be done as:

FileTask "targetfilename", ["sourcefilename"] do

Cp("targetfilename", "targetfilename"

Bas Jansen

I wondered if the code is right

The definition of the methode is:

def IsUpToDate(target as string, source as string):

and then the it is used like this:

Cp("source.big", "dest.big") if not IsUpToDate("source.big", "dest.big")

Now the first parameter is source so it is a bit confusing, for me.

But it looks nice and it again remembers me that I want to dive in Boo and even in Boops...

Comment preview

Comments have been closed on this topic.


  1. RavenDB 3.0 New Stable Release - 3 hours from now
  2. Production postmortem: The case of the lying configuration file - about one day from now
  3. Production postmortem: The industry at large - 2 days from now
  4. The insidious cost of allocations - 3 days from now
  5. Buffer allocation strategies: A possible solution - 6 days from now

And 4 more posts are pending...

There are posts all the way to Sep 11, 2015


  1. Find the bug (5):
    20 Apr 2011 - Why do I get a Null Reference Exception?
  2. Production postmortem (10):
    31 Aug 2015 - The case of the memory eater and high load
  3. What is new in RavenDB 3.5 (7):
    12 Aug 2015 - Monitoring support
  4. Career planning (6):
    24 Jul 2015 - The immortal choices aren't
View all series


Main feed Feed Stats
Comments feed   Comments Feed Stats