Created
November 3, 2020 07:26
-
-
Save salewski/d85517f5e2eca6988872d5e60fa1759a to your computer and use it in GitHub Desktop.
Print all rustup 'rustc' versions mapped to the corresponding "toolchain" name
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash - | |
# SPDX-FileCopyrightText: <text> © 2020 Alan D. Salewski <[email protected]> </text> | |
# SPDX-License-Identifier: GPL-2.0-or-later | |
# | |
# This program is free software; you can redistribute it and/or modify | |
# it under the terms of the GNU General Public License as published by | |
# the Free Software Foundation; either version 2 of the License, or | |
# (at your option) any later version. | |
# | |
# This program is distributed in the hope that it will be useful, | |
# but WITHOUT ANY WARRANTY; without even the implied warranty of | |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
# GNU General Public License for more details. | |
# | |
# You should have received a copy of the GNU General Public License | |
# along with this program; if not, write to the Free Software Foundation, | |
# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301,, USA. | |
# rustup-rustc-versions: Print all rustup 'rustc' versions mapped to | |
# the corresponding "toolchain". | |
# | |
# Uses 'rustup' and related commands to obtain the list of rustup | |
# "toolchain" names and their corresponding rustc(1) versions, for | |
# each toolchain the user has configured. | |
# | |
# This program is a more ergonomic version of the following command | |
# (from which it evolved): | |
# | |
# $ ( target=$(eval "$(rustc --print cfg | grep -E '^target_(arch|vendor|os|env)=')" && printf '%s-%s-%s-%s\n' "${target_arch}" "${target_vendor}" "${target_os}" "${target_env}" ) && rustup toolchain list | sed -e 's/[[:space:]]\{1,\}[(]default[)][[:space:]]*$//' -e 's/'"-${target}"'$//' | while read -r tc; do printf '%10s: %s\n' "$tc" "$(rustup run $tc rustc --version)"; done ) | |
# stable: rustc 1.47.0 (18bf6b4f0 2020-10-07) | |
# beta: rustc 1.48.0-beta.5 (4c78178b1 2020-10-21) | |
# nightly: rustc 1.49.0-nightly (ffa2e7ae8 2020-10-24) | |
# system: rustc 1.46.0 | |
# | |
# Usage: | |
# rustup-rustc-versions | |
# | |
# | |
# Example: | |
# $ rustup-rustc-versions | |
# stable: rustc 1.47.0 (18bf6b4f0 2020-10-07) | |
# beta: rustc 1.48.0-beta.5 (4c78178b1 2020-10-21) | |
# nightly: rustc 1.49.0-nightly (ffa2e7ae8 2020-10-24) | |
# system: rustc 1.46.0 | |
# | |
# | |
# See also: | |
# | |
# * rustup | |
# | |
# * rustc(1) | |
# | |
declare -r PROG='rustup-rustc-versions' | |
DEBUGGING=false | |
# By default we'll use the external programs found on $PATH. But we | |
# allow the user to override any particular tool by setting an | |
# environment variable named after the tool (with hyphen chars | |
# changed to underscores). | |
# | |
SED_PROG="${SED:-sed}" | |
GREP_PROG="${GREP:-grep}" | |
RUSTC_PROG="${RUSTC:-rustc}" | |
RUSTUP_PROG="${RUSTUP:-rustup}" | |
declare -a NEEDED_EXTERNAL_PROGS=( | |
"${SED_PROG}" | |
"${GREP_PROG}" | |
"${RUSTC_PROG}" | |
"${RUSTUP_PROG}" | |
) | |
for ext_tool in "${NEEDED_EXTERNAL_PROGS[@]}"; do | |
t_path=$(builtin type -p "${ext_tool}") | |
if test $? -ne 0; then | |
printf "${PROG} (error): was unable to locate \"%s\" on PATH; bailing out\n" "${ext_tool}" 1>&2 | |
exit 1 | |
fi | |
if $DEBUGGING; then | |
printf "${PROG} (debug): path to external tool \"%s\": %s\n" "${ext_tool}" "${t_path}" 1>&2 | |
fi | |
done | |
# We use the 'rustup toolchain list' command to enumerate all of the | |
# rustup "toolchains" that the user has configured. | |
# | |
# $ rustup toolchain list | |
# stable-x86_64-unknown-linux-gnu | |
# beta-x86_64-unknown-linux-gnu | |
# nightly-x86_64-unknown-linux-gnu | |
# system (default) | |
# | |
# There's currently no knob to prevent that " (default)" token from | |
# being emitted, so we'll slice it off manually: | |
# | |
# $ rustup toolchain list | sed -e 's/[[:space:]]\{1,\}[(]default[)][[:space:]]*$//' | |
# stable-x86_64-unknown-linux-gnu | |
# beta-x86_64-unknown-linux-gnu | |
# nightly-x86_64-unknown-linux-gnu | |
# system | |
# | |
# The list of "toolchain" names in the above output is specific, but | |
# that comprehensive spelling is not typically how users specify | |
# them on the rustup command line. Rather than, | |
# "nightly-x86_64-unknown-linux-gnu", the user would just type | |
# "nightly", at least in the common case of targetting the current | |
# host and a non-date-specific nightly. | |
# | |
# The 'x86_64-unknown-linux-gnu' value is in the form: | |
# | |
# <arch>-<vendor>-<os>-<env> | |
# | |
# and we can query for the correct values to use for those fields on | |
# the current host from the 'rustc --print cfg' command: | |
# | |
# $ rustc --print cfg | |
# debug_assertions | |
# target_arch="x86_64" | |
# target_endian="little" | |
# target_env="gnu" | |
# target_family="unix" | |
# target_feature="fxsr" | |
# target_feature="sse" | |
# target_feature="sse2" | |
# target_os="linux" | |
# target_pointer_width="64" | |
# target_vendor="unknown" | |
# unix | |
# | |
# We can pull out just the relevant settings like this: | |
# | |
# $ rustc --print cfg | grep -E '^target_(arch|vendor|os|env)=' | |
# target_arch="x86_64" | |
# target_env="gnu" | |
# target_os="linux" | |
# target_vendor="unknown" | |
# | |
# Notice that those are legit shell statements, so if we do that in | |
# a subshell we can just use the 'target_*' variables directly: | |
# | |
# $ ( eval "$(rustc --print cfg | grep -E '^target_(arch|vendor|os|env)=')" && printf '%s-%s-%s-%s\n' "${target_arch}" "${target_vendor}" "${target_os}" "${target_env}" ) | |
# x86_64-unknown-linux-gnu | |
# | |
target=$( eval "$("${RUSTC_PROG}" --print cfg \ | |
| "${GREP_PROG}" -E '^target_(arch|vendor|os|env)=')" \ | |
&& printf '%s-%s-%s-%s\n' \ | |
"${target_arch}" \ | |
"${target_vendor}" \ | |
"${target_os}" \ | |
"${target_env}" ) | |
if test $? -ne 0 \ | |
|| test -z "${target}"; then | |
printf "${PROG} (error): was unable to extract <arch>-<vendor>-<os>-<env> target spec; bailing out\n" 1>&2 | |
exit 1 | |
fi | |
# Gather "toolchain" names, slicing off the " (default)" label, and | |
# shortening the explicit toolchain names that match our default | |
# target host arch/vendor/os/env. | |
# | |
# We will note the length of the longest name as we go. | |
# | |
declare -a toolchain_names=() | |
largest=0 | |
while read -r tc_name; do | |
toolchain_names+=( "${tc_name}" ) | |
if test "${#tc_name}" -gt "${largest}"; then | |
largest=${#tc_name} | |
fi | |
done < <("${RUSTUP_PROG}" toolchain list \ | |
| "${SED_PROG}" -e 's/[[:space:]]\{1,\}[(]default[)][[:space:]]*$//' \ | |
-e 's/'"-${target}"'$//') | |
if test $? -ne 0; then | |
printf "${PROG} (error): was unable to obtain list of rustup \"toolchain\" names; bailing out\n" 1>&2 | |
exit 1 | |
fi | |
# We will use the $largest value to display the toolchain names in a | |
# fixed width field. | |
# | |
for one_tc_name in "${toolchain_names[@]}"; do | |
printf '%*s: %s\n' \ | |
"${largest}" "${one_tc_name}" \ | |
"$("${RUSTUP_PROG}" run "${one_tc_name}" rustc --version)" | |
if test $? -ne 0; then | |
printf "${PROG} (error): was unable to print rustc version for toolchain \"%s\"; bailing out\n" \ | |
"${one_tc_name}" 1>&2 | |
exit 1 | |
fi | |
done |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment