From ArchWiki
Jump to navigation Jump to search

The Idea

Provide an alternatives system to allow users to select which package provides a file.

Current Situation

'/usr/bin/sh' is a symlink to 'bash'. People may want to use a different shell interpreter for 'sh', e.g. 'dash', but this is currently not possible without rebuilding the bash package to remove the symlink first.



An alternative would be specified in a PKGBUILD as:


Note that this is an array - a package could potentially provide more than one set of alternatives

Makepkg would add this information to the .PKGINFO file:

 alternative = python

The list of symlinks for an alternative is stored in a file called python.alternative and have format like:

 usr/bin/python -> python2
 usr/bin/idle -> idle2

This syntax assumes the symlinks will point to a file in the same directory. However full or relative paths can be specified if needed:

 usr/bin/java -> /usr/lib/jvm/java-7-openjdk/jre/bin/java
 usr/bin/java -> ../lib/jvm/java-7-openjdk/jre/bin/java

Directories can be symlinked just like files.

 usr/include/lua -> lua-5.2

Note the top entry is the primary alternative and will be used in some pacman output (the master alternative in Debian/Fedora speak). The rest are what is dragged in with it (slaves in Debian/Fedora speak...).

These files are stored in the package root with name



Should we have a way of globbing and what syntax? e.g.

 usr/include/* -> lua5.1/*

That would take all files in the package directory usr/include/lua5.1/ and symlink them into usr/include.


Should we have a way of piggybacking alternatives? E.g. python2-pip may way to piggyback on the python2 package's python alternative. No other implementation has this. Does this force packagers decisions onto the user, or should there be a way to avoid it?



On installation of a package with an alternative, the .ALTERNATIVE file is extracted to:


If the primary alternative symlink is not present, this package becomes the active owner of that alternative on this system. This is recorded with symlink is placed in:

 /var/lib/pacman/alternative/python/python2 -> /var/lib/pacman/local/python2-2.7.17-1/alternative.python

All symlinks specified in this file are created.

If the primary alternative symlink is present on the system, then nothing happens on package install.

TODO: Update handling. The symlink recording active alternatives will need adjusted with each update. Makes sense if we need to rescan the alternatives file and adjust.

TODO: Should we only check the primary alternative symlink? What is the behaviour when secondary symlinks are present in the system? Skip with a warning?

TODO: output - both when activating an alternative, and when not activating (like optdepends?)

New pacman option examples

List all alternatives from installed packages

 $ pacman -A
 python ->
    python3 3.7.2-3 [active]
    python2 2.7.17-1
 sh ->
    bash 5.0.002-1
    dash [active]

List installed alternatives for a given command

 $ pacman -A sh
 bash 5.0.002-1
 dash [active]

Update alternative (print error if mismatch between alternative name and package):

 $ pacman -Au sh bash
 usr/bin/sh -> bash

(only print the primary alternative?)

NEEDS WORK List all symlinks provided by an alternative:

 $ pacman -Ai python2
   usr/bin/python -> python2
   usr/bin/idle -> idle2

Other options requiring behaviour changes

pacman -Si <pkg> - prints alternatives like dependencies
pacman -Qi <pkg> - prints alternatives and also note whether alternative is active
pacman -Qo <alternative symlink> - assigned ownership to the package providing the alternative


pacman -F...
pacman -Ql <pkg>