debian/rake: Ruby DH Sequencing?

In my previous post I looked at the possibility of using rake, a Ruby build tool, instead of make to write debian/rules files. While that turned out to not be entirely impossible as far as the core dpkg-* utilities used to build Debian packages are concerned, wiring it up with the debhelper ‘dh’ command sequencer appears unfortunately impossible without changes to dh itself.

Clearly the solution here is to write our own sequencer in Ruby! To do that we will first have to understand what a sequencer does though.

In the post about using rake for debian/rules I already briefly outlined what the Debian package build process looks like and that it is, for the most part, driven by a tool called dpkg-buildpackage. The rules file itself is mostly just a harness receiving commands from dpkg-buildpackage and forwarding them to the dh sequencer.

We already looked at the most trivial of rules files previously and did not spend time on looking into how this works. But since we want to implement our own version of dh it probably is time to have a closer look.

#!/usr/bin/make -f

%:
    dh $@

If one does not know make-syntax very well that piece of code is probably not very descriptive.

Perhaps it would be best to look at what it does, and then infer how it does it. So, let us find out what exactly dpkg-buildpackage does with debian/rules by using a no-op rules to inspect what is happening here.

#!/usr/bin/make -f

%:
    @echo TARGET $@

Prints the following when we try to build a package with this debian/rules file:

 fakeroot debian/rules clean
TARGET clean
 debian/rules build
TARGET build
 fakeroot debian/rules binary
TARGET binary

At this point I will go ahead and mention that % is a pattern rule (target) that matches anything. Each make file is composed of targets, each target represents a build step, as it were. One uses make by calling one or more targets. Since writing generic targets over and over again would get annoying quickly, make has this pattern system where you can define a target that is kind of like a regular expression to apply to multiple different inputs. The most generic version of such a target is %, it will be used for everything and the kitchen sink (as long as there is no more conrecte target that would match anyway).

If the % target is run for every possible target dpkg-buildpackage might call then clearly dh, and to that extent our Ruby version of dh, will have to support at least clean, build and binary as target commands. Namely if I run ‘rake -f debian/rules clean’ it should clean up the source. Trivial enough to implement in rake:

#!/usr/bin/rake -f

task :clean do |t|
end

task :build do |t|
end

task :binary do |t|
end

Lovely. That clearly does not do anything though. What is missing is the command sequencing bit of the command sequencer. In the previous post, I mentioned that debhelper is a collection of tools that help with building a package. There are many of those, they all are called dh_somethingsomething and they need to be called in a somewhat set order for them to do their thing. dh does exactly that. It runs the numerous dh_ tools in sequence to build a package.

We will have to implement the sequence as well if we want a sequencer written in Ruby. So, after a bit of digging in the code here are the default sequences. At this point it ought to be noted that build and binary targets in fact are legacy targets dpkg-buildpackage will call for compatibility reasons and the dh sequences are layed out in the more concrete new targets.

Now that we know the sequences, it is only a game of implementing the sequences and perhaps thinking of a way to conveniently allow overrides. The version I came up with when I worked on this originally (which is really just a quick hack and not the smoothest way to implement the sequencer) leads to code like this:

#!/usr/bin/rake -f

require_relative 'sequencer'

override :dh_strip do
  puts 'CALLED DH STRIP'
  sh 'dh_strip'
end

In conclusion. It is possible to write debian/rules files using rake instead of make as the dpkg-* tools are largely independent of the actual implementation language. We can even use the debhelper utils so long as we reimplement the sequencer bit.

mission-accomplished

If you are interested in a more comprehensive re-implementation of dh, the Debian-KDE/Kubuntu team is actually using a pure make sequencer.