Alternatives

Overview

Alternatives are a concept we use for two purposes: providing choice, and making slotting more manageable. They allow for switching out the package which provides files such as libraries, binaries, and manpages by replacing the “normal location” of the file (ex. /usr/i686-pc-linux-gnu/bin/python) with a symlink to the “actual file”, (/etc/env.d/alternatives/python2/_current/usr/i686-pc-linux-gnu/bin/python2) which alternatives.exlib stores in /etc/env.d/alternatives.

Alternatives are also a part of eclectic, the tool we use for some aspects of system configuration. There’s an alternatives module which is used by alternatives.exlib for allowing for programmatic creation of new modules which can then be invoked as normal modules in eclectic.

Related to and often used with Providers and virtuals.

Examples

Usage on the command line

Examples are edited for brevity, don’t expect it to look exactly like this.

somasis/cicero:~/ % eclectic

Usage: eclectic <global options> <module name> <module options>

Alternatives modules:
  awk                       Alternatives for awk
  gcc                       Alternatives for gcc
  gzip                      Alternatives for gzip
  hostname                  Alternatives for hostname
  init                      Alternatives for init
  kmod-tools                Alternatives for kmod-tools
  ld                        Alternatives for ld
  locate                    Alternatives for locate
  lua                       Alternatives for lua
  perl                      Alternatives for perl
  pkg-config                Alternatives for pkg-config
  python                    Alternatives for python
  python2                   Alternatives for python2
  python3                   Alternatives for python3
  ruby                      Alternatives for ruby
  vala                      Alternatives for vala
  wxwidgets                 Alternatives for wxwidgets

Extra modules:
  alternatives              Maintain Alternatives symlinks

Each package which uses alternatives has a name of what it provides, and that is what is used as the name of the module eclectic shows you. Usually, the package’s main binary, or the name of whichever package came first is used as the module name; gcc, awk, wxwidgets, etc.

somasis/cicero:~/ % eclectic awk list
Available providers for awk:
  [1]   mawk *
  [2]   gawk

As shown here, you can list the packages you have installed that can provide for the module you’re listing. sys-apps/mawk and sys-apps/gawk both provide an implementation of the AWK programming language, and both can function fine as /usr/host/bin/awk. The asterisk indicates the provider currently set.

somasis/cicero:~/ % eclectic awk set gawk
somasis/cicero:~/ % awk
Usage: awk [POSIX or GNU style options] -f progfile [--] file ...
Usage: awk [POSIX or GNU style options] [--] 'program' file ...

gawk is a pattern scanning and processing language.
By default it reads standard input and writes standard output.

Examples:
    gawk '{ sum += $1 }; END { print sum }' file
    gawk -F: '{ print $1 }' /etc/passwd
somasis/cicero:~/ % eclectic awk set mawk
somasis/cicero:~/ % awk
Usage: mawk [Options] [Program] [file ...]

Program:
    The -f option value is the name of a file containing program text.
    If no -f option is given, a "--" ends option processing; the following
    parameters are the program text.

Magic.

Usage in exheres

alternatives_for

alternatives_for <module name> <provider name> <[provider importance]> <source> <target> [<source> <target>...]

alternatives_for is the main function, which is what actually sets the module name, provider, provider importance value, and files which are provided by the package in question. It must only be used in src_install.

If the source and target are a bit confusing, here’s an example:

In addition, if the the source’s basename exists, and the target doesn’t, alternatives_for will move the source to the target.

alternatives_pkg_postinst

alternatives_pkg_postinst is what creates the alternatives module for the package being installed, if it doesn’t already exist. If it does exist, it updates the alternatives modules to have a valid provider. On package upgrades, it also updates the currently selected provider, to maintain the integrity of the file list. alternatives_pkg_postrm does the opposite, and cleans up alternatives modules that no longer have any providers.

Alternatives module metadata

DESCRIPTION

DESCRIPTION is what is displayed in the output of eclectic list-modules, shown next to the name of the alternative.

The correct way to set it is like so:

ALTERNATIVES_cc_DESCRIPTION="System-wide C compiler"
ALTERNATIVES_cxx_DESCRIPTION="System-wide C++ compiler"

alternatives_for cc gcc 1000 /usr/bin/gcc /usr/share/man/man1/gcc.1
alternatives_for c++ g++ 1000 /usr/bin/g++ /usr/share/man/man1/g++.1

Resulting in:

somasis/cicero:~/ % eclectic print-modules
[...]

Alternatives modules:
  cc                        Alternatives for cc
  c++                       Alternatives for c++
[...]

The alternative name is sanitized to work around some variable name restrictions in bash, by replacing [+=-] with x. Therefore, to set c++‘s description you would set ALTERNATIVES_cxx_DESCRIPTION to the description that is desired.

It is important that all providers share the same description. If they don’t, it will result in the description changing every time a different provider is installed.

Caveats

You should keep in mind that alternatives can affect package building. This means that you shouldn’t assume that the user has a certain provider selected for any of the alternative modules; you should instead find a way to make the package’s build system work, regardless of what the provider that the user has selected is.

Exheres are never allowed to change alternatives. You may not run eclectic <module> set in an exheres. It is only for users.

Example: some packages may assume that the user’s default /usr/host/bin/python is python2; alternatives give the ability to choose, so you should fix the package’s build system to specifically use python2 if it needs python2, rather than assume python is python2.

Importance

Importance should be a signed integer, and can contain decimals, but may not start with or end with a dot. The provider which has the highest importance value is the most important. No two providers are allowed to have the same importance; you must make a decision on how important one provider should be over another.

Importance controls the order of the providers used for the list that eclectic <module> list outputs, and what provider eclectic <module> update selects if the preferred one is uninstalled. Importance doesn’t matter in any other case though, since we make a best effort to abide by what the user’s choice on what they want as their provider when possible. A list of full rules that eclectic <module> update uses can be found here.

For light alternatives, importance controls what is selected, since light alternatives are designed to not be changed by the user.

Example exheres

# Copyright 2012 Elias Pipping <pipping@exherbo.org>
# Copyright 2015 Kylie McClain <somasis@exherbo.org>
# Distributed under the terms of the GNU General Public License v2

require alternatives

SUMMARY="Parallel implementation of gzip"
HOMEPAGE="http://www.zlib.net/${PN}"
DOWNLOADS="${HOMEPAGE}/${PNV}.tar.gz"

LICENCES="ZLIB"
SLOT="0"
PLATFORMS="~amd64"

MYOPTIONS=""

src_prepare() {
    edo sed \
            -e "s/^CC=.*/CC=$(exhost --tool-prefix)cc/"    \
            -e "s/^CFLAGS=.*//"                             \
            -i Makefile
}

src_install() {
    edo mkdir -p "${IMAGE}/usr/$(exhost --target)/bin"
    edo mv ${PN} "${IMAGE}/usr/$(exhost --target)/bin"
    dosym "/usr/$(exhost --target)/bin/${PN}" "/usr/$(exhost --target)/bin/unpigz"

    doman ${PN}.1
    dodoc README ${PN}.pdf

    alternatives_for "gzip" "${PN}" "50"                               \
                     "/usr/$(exhost --target)/bin/gzip"     "${PN}"    \
                     "/usr/$(exhost --target)/bin/gunzip"   "unpigz"   \
                     "/usr/share/man/man1/gzip.1"           "${PN}.1"
}

Light alternatives

Light alternatives are alternatives that aren’t intended to be messed with by the user. Their name is prefixed with an underscore, and they don’t show up in eclectic‘s list of modules, and are usually only changed by packages being installed, during the pkg_postinst phase. These are often used for slotted libraries so that the upgrade process is easier. An example of it’s usage is dev-libs/icu, which has its libraries slotted so that during the upgrade, you don’t hit linking errors and can safely upgrade and remove the previous version once all packages depending on it are linked correctly with cave fix-linkage.


Copyright 2015 Kylie McClain