Posted on Feb 7, 2009

Building Ruby: Creating Packages

As I commented in my previous post, building Ruby can be a daunting task. This time I want to explain the logic behind the new DSL created for RubyInstaller

Oh no, not another DSL!

Oh yeah, another DSL.

While it might sound reinventing the wheel, it was something needed, but instead of creating everything from scratch, I’ve tried to learn from my mistakes.

The following is the list of caveats that exist @master branch of the project and that I’ve tried to solve in the new @dsl branch.

Unique location for configuration of packages

RubyInstaller code is build on a base of recipes: a series of automated instructions that allow building different packages.

In current implementation, both configuration and resources are split between config/ruby_installer.rb and the recipe itself.

Take for example GCC 3.4.5:

(gist: 60033)

It required edition of file downloads in one place, and the complex instructions for downloading and extracting in another.

Now, see the new version:

(gist: 60037)

As you can see, more clear indications of what files are being downloaded and from which server.

Also you no longer need worry where the package get extracted, allowing you have multiple packages (hint: gcc3 and gcc4) ;)

Better chaining and package dependency

In current implementation, there was no way to make Ruby18 package depend on a previous package that requires to be build.

Now, defining depends_on is taking care of the dependency chain and ensure the page is complete for you.

Hooks for pre and post actions

Take as example extract_utils.rake and msys.rake, first one defined it self as requirement for other extract options while the second one tweak several files in prepare action.

Now, see the new 7-zip (extract utils) recipe:

(gist: 60049)

It uses bundled RubyZip to extract itself and the replace extract helper with it’s own version.

As you can see, there is no noise generated by Rake tasks, and also Package provide some hooks to better integrate before and after actions, like download or extract

Avoid double extraction

One criticism of current implementation was that every time it tried to checkout or extract all the files that comprises a package.

The new implementation avoids that using checkpoint files, something originally suggested by Lars Christensen and implemented.

These checkpoint files also help for actions that modifies and alter the file and folder structure, like patching or creating new files inside the package.

See this example:

(gist: 60053)

But what about compilation?

Right now I’m working on letting the compiler define it’s helper and let you configure, compile and install Ruby in the sandboxed environment.

I’ve been working on those and hope get these ironed over this weekend.

Keep an eye on this blog!