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: 6,026 | Comments: 44,842

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.


No future posts left, oh my!


  1. Technical observations from my wife (3):
    13 Nov 2015 - Production issues
  2. Production postmortem (13):
    13 Nov 2015 - The case of the “it is slow on that machine (only)”
  3. Speaking (5):
    09 Nov 2015 - Community talk in Kiev, Ukraine–What does it take to be a good developer
  4. Find the bug (5):
    11 Sep 2015 - The concurrent memory buster
  5. Buffer allocation strategies (3):
    09 Sep 2015 - Bad usage patterns
View all series


Main feed Feed Stats
Comments feed   Comments Feed Stats