Tinderboxing problems: missing default USE flags

I’ve already written some time ago about blockers and the way they hinder tinderboxing; today I want to write a bit about the problems related to a similar workaround: ebuilds failing with not enough USE flags enabled.

For a long time we had various different ways to cope with packages that required at least one out of a set of USE flags to be enabled to work; we still haven’t been able to fix this by expressing dependencies between USE flags, which would also allow us to explain to the package manager that a given USE flag depends on another, or that two of them conflicts between each other, but at least nowadays we have some ways to handle the first and most common case.

It’s not an uncommon sight after all, a lot of packages have multiple backends, and require that at least one of them is enabled (sometimes exactly one of them). This usually can be handled either by considering one particular backend the default one, and thus not providing an USE flag for it or, with the modern Portage versions, by using EAPI=1 and default USEs.

When not using EAPI=1 and the default USE flag method, you usually end up with just checking for one of the possible USE flags to be enabled, like the following code:

IUSE="sqlite mysql postgres"

pkg_setup() {
    if !use sqlite && !use mysql && !use postgres"; then
        die "At least one between "sqlite, mysql or postgres USE flags should be enabled"
    fi
}

You’re just showing to the user a failure message, forcing almost all users to write an entry for the package in package.use to enable the correct backend. This gets even worse when the message does not specify the available options, it’s pretty annoying to read in your build logs “please enable at least one backend USE flag”, without telling which USE flags are available.

A common alternative is to use a more complex logic in the ebuild, removing the sqlite option:

src_compile() {
  myconf="$(use_enable mysql) $(use_enable postgres)"

  if !use mysql && !use postgres; then
    myconf="$myconf --enable-sqlite"
  else
    myconf="$myconf --disable-sqlite"
  fi
}

While this sort of works, it does not advertise to the user the presence of sqlite, which might be what the user prefers to use in the first place. A final alternative is to still allow for sqlite USE flags to be present, but force sqlite on when none of the USE flags is enabled:

src_compile() {
  myconf="$(use_enable mysql) $(use_enable postgres)"

  if !use mysql && !use postgres; then
    myconf="$myconf --enable-sqlite"
  else
    myconf="$myconf $(use_enable sqlite)"
  fi
}

Which still is not representing the best to the user since it seems to provide him with an option to use no backend, which produces a working package, but with an hidden dependency on sqlite. It also makes the DEPEND/RDEPEND syntax quite difficult to read.

With EAPI=1 you can just check during pkg_setup whether the conditions for a successful merge are present (at least one USE flag enabled), and die if they aren’t, but you can also make sure that the user always get a working package out of a blind emerge foobar. Basically what you got is something like this:

EAPI=1

IUSE="+sqlite mysql postgres"

pkg_setup() {
    if !use sqlite && !use mysql && !use postgres"; then
        die "At least one between "sqlite, mysql or postgres USE flags should be enabled"
    fi
}

This solves the problem quite well, for the most common and easy of the cases: it allows the user to have fine-grained control over which backends to enable, yet for most users it just enables sqlite by default without asking them to enable it explicitly. It’s pretty cool.

Please remember to make use of this feature for the sake of users, and of tinderboxes. Thank you.

Please note: this blog post is going to be used as reference URL for bugs requesting ebuilds not using the latter method to move to that.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s