Today lurking on #gentoo-hardened I came to look at an ebuild written particularly badly, that exasperated one very bad construct for what concerns parallel builds (which are a very good thing with modern multi-core multi-thread CPUs):
src_compile() {
if use foo; then
emake foo || die
fi
if use bar; then
emake bar || die
fi
if use doc; then
emake doc || die
fi
}
This situation wastes a lot of processing power: the three targets with all their dependencies will be taken into consideration serially, not in parallel; if you requested 12 jobs, but each of foo and bar only have three object files as dependencies, they should have been built at the same time, not in two different invocations.
I admit I made this mistake before, and even so recently, mostly related to documentation building, so how does one solve this problem? Well there are many options, my favourite being something along these lines:
src_compile() {
emake
$(use foo && echo foo)
$(use bar && echo bar)
$(use doc && echo doc)
|| die "emake failed"
}
Of course this has one problem in the fact that I don’t have a general target so it should rather be something more like this:
src_compile() {
local maketargets=""
if use bar ; then
maketargets="${maketargets} bar"
else
maketargets="${maketargets} foo"
fi
emake ${maketargets}
$(use doc && echo doc)
|| die "emake failed"
}
This will make sure that all the targets will be considered at once, and will leave make
to take care of dependency resolution.
I tried this approach out in the latest revision of the Drizzle ebuild that I proxy-maintain for Pavel; the result is quite impressive because doxygen, instead of taking its dear time after the build completed, runs for about half of the build process (using up only one slot of the twelve jobs I allocate for builds on Yamato).
Obviously, this won’t make any difference if the package is broken with respect to parallel build (using emake -j1
) and won’t make a difference when you’re not building in parallel, but why not doing it right, while we’re at it?