Skip to content

Instantly share code, notes, and snippets.

@CJKay
Created October 11, 2021 09:59
Show Gist options
  • Save CJKay/f4789cb8c2030b85b467e0ca0be39a6e to your computer and use it in GitHub Desktop.
Save CJKay/f4789cb8c2030b85b467e0ca0be39a6e to your computer and use it in GitHub Desktop.
Update LLVM Alternatives
#!/bin/bash
packages=("clang" "lldb" "lld" "clangd")
for package in ${packages[@]}; do
versions=$(apt-cache search --names-only "^${package}-[0-9]+$" | cut -d' ' -f1 | rev | cut -d'-' -f1 | rev)
for version in ${versions}; do
if ! dpkg -l "${package}-${version}" > /dev/null 2>&1; then
continue
fi
master=
slaves=()
files=$(dpkg -L "${package}-${version}")
for file in ${files}; do
if ! [ -f "${file}" ]; then
continue
fi
dirname=$(dirname ${file})
basename=$(basename ${file})
realname=${basename//-${version}/}
if [[ ":$PATH:" != *":${dirname}:"* ]] && [[ "${dirname}" != "/usr/share/man/"* ]]; then
continue
fi
if [ "${realname}" = "${package}" ]; then
master=${file}
else
slaves=(${slaves[@]} "${file}")
fi
done
if [ -z "${master}" ]; then
>&2 echo "No master identified for package: ${package}-${version}"
>&2 echo "Please update these alternatives manually: ${slaves}"
continue
fi
priority=$((100 * ${version}))
master_link=${master//-${version}/}
master_alternative=${master}
master_name=$(basename "${master_link}")
command=("sudo" "update-alternatives" "--install" "${master_link}" "${master_name}" "${master_alternative}" "${priority}")
for slave in ${slaves[@]}; do
slave_link=${slave//-${version}/}
slave_alternative=${slave}
slave_name=$(basename "${slave_link}")
command=(${command[@]} "--slave" "${slave_link}" "${slave_name}" "${slave_alternative}")
done
${command[@]}
done
done
@CJKay
Copy link
Author

CJKay commented Oct 11, 2021

This script is intended for consumers of LLVM's Debian/Ubuntu automatic installer script, which can be found here. It identifies the list of installed versioned LLVM packages (i.e. clang-<version>, lldb-<version>, lld-<version> and clangd-<version>) and uses update-alternatives to create switchable symbolic links to the packages' binaries and manpages.

The master/slave relationship between the main package binary and its dependants is maintained when creating alternatives. For example, where clang is the package, /usr/bin/clang is the master binary, and /usr/bin/clang++ is a slave binary. Doing this ensures that the binaries from each package are switched together rather than independently:

$ file /etc/alternatives/clang /etc/alternatives/clang++
/etc/alternatives/clang:   symbolic link to /usr/bin/clang-12
/etc/alternatives/clang++: symbolic link to /usr/bin/clang++-12
$ sudo update-alternatives --config clang
There are 2 choices for the alternative clang (providing /usr/bin/clang).

  Selection    Path               Priority   Status
------------------------------------------------------------
  0            /usr/bin/clang-13   1300      auto mode
* 1            /usr/bin/clang-12   1200      manual mode
  2            /usr/bin/clang-13   1300      manual mode

Press <enter> to keep the current choice[*], or type selection number: 0
update-alternatives: using /usr/bin/clang-13 to provide /usr/bin/clang (clang) in auto mode
$ file /etc/alternatives/clang /etc/alternatives/clang++
/etc/alternatives/clang:   symbolic link to /usr/bin/clang-13
/etc/alternatives/clang++: symbolic link to /usr/bin/clang++-13

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment