1#!/bin/bash 2# 3# Copyright 2023 The Fuchsia Authors 4# 5# Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0 6# <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT 7# license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option. 8# This file may not be copied, modified, or distributed except according to 9# those terms. 10 11# This script is a thin wrapper around Cargo that provides human-friendly 12# toolchain names which are automatically translated to the toolchain versions 13# we have pinned in CI. 14# 15# cargo.sh --version <toolchain-name> # looks up the version for the named toolchain 16# cargo.sh +<toolchain-name> [...] # runs cargo commands with the named toolchain 17# cargo.sh +all [...] # runs cargo commands with each toolchain 18# 19# The meta-toolchain "all" instructs this script to run the provided command 20# once for each toolchain (msrv, stable, nightly). 21# 22# A common task that is especially annoying to perform by hand is to update 23# trybuild's stderr files. Using this script: 24# 25# TRYBUILD=overwrite ./cargo.sh +all test --workspace 26 27set -eo pipefail 28 29function print-usage-and-exit { 30 echo "Usage:" >&2 31 echo " $0 --version <toolchain-name>" >&2 32 echo " $0 +<toolchain-name> [...]" >&2 33 echo " $0 +all [...]" >&2 34 exit 1 35} 36 37[[ $# -gt 0 ]] || print-usage-and-exit 38 39function pkg-meta { 40 # NOTE(#547): We set `CARGO_TARGET_DIR` here because `cargo metadata` 41 # sometimes causes the `cargo-metadata` crate to be rebuilt from source using 42 # the default toolchain. This has the effect of clobbering any existing build 43 # artifacts from whatever toolchain the user has specified (e.g., `+nightly`), 44 # causing the subsequent `cargo` invocation to rebuild unnecessarily. By 45 # specifying a separate build directory here, we ensure that this never 46 # clobbers the build artifacts used by the later `cargo` invocation. 47 CARGO_TARGET_DIR=target/cargo-sh cargo metadata --format-version 1 | jq -r ".packages[] | select(.name == \"zerocopy\").$1" 48} 49 50function lookup-version { 51 VERSION="$1" 52 case "$VERSION" in 53 msrv) 54 pkg-meta rust_version 55 ;; 56 stable) 57 pkg-meta 'metadata.ci."pinned-stable"' 58 ;; 59 nightly) 60 pkg-meta 'metadata.ci."pinned-nightly"' 61 ;; 62 *) 63 echo "Unrecognized toolchain name: '$VERSION' (options are 'msrv', 'stable', 'nightly')" >&2 64 return 1 65 ;; 66 esac 67} 68 69function get-rustflags { 70 [ "$1" == nightly ] && echo "--cfg __INTERNAL_USE_ONLY_NIGHLTY_FEATURES_IN_TESTS" 71} 72 73function prompt { 74 PROMPT="$1" 75 YES="$2" 76 while true; do 77 read -p "$PROMPT " yn 78 case "$yn" in 79 [Yy]) $YES; return $?; ;; 80 [Nn]) return 1; ;; 81 *) break; ;; 82 esac 83 done 84} 85 86case "$1" in 87 # cargo.sh --version <toolchain-name> 88 --version) 89 [[ $# -eq 2 ]] || print-usage-and-exit 90 lookup-version "$2" 91 ;; 92 # cargo.sh +all [...] 93 +all) 94 echo "[cargo.sh] warning: running the same command for each toolchain (msrv, stable, nightly)" >&2 95 for toolchain in msrv stable nightly; do 96 echo "[cargo.sh] running with toolchain: $toolchain" >&2 97 $0 "+$toolchain" ${@:2} 98 done 99 exit 0 100 ;; 101 # cargo.sh +<toolchain-name> [...] 102 +*) 103 TOOLCHAIN="$(lookup-version ${1:1})" 104 105 cargo "+$TOOLCHAIN" version &>/dev/null && \ 106 rustup "+$TOOLCHAIN" component list | grep '^rust-src (installed)$' >/dev/null || { 107 echo "[cargo.sh] missing either toolchain '$TOOLCHAIN' or component 'rust-src'" >&2 108 # If we're running in a GitHub action, then it's better to bail than to 109 # hang waiting for input we're never going to get. 110 [ -z ${GITHUB_RUN_ID+x} ] || exit 1 111 prompt "[cargo.sh] would you like to install toolchain '$TOOLCHAIN' and component 'rust-src' via 'rustup'?" \ 112 "rustup toolchain install $TOOLCHAIN -c rust-src" 113 } || exit 1 114 115 RUSTFLAGS="$(get-rustflags ${1:1}) $RUSTFLAGS" cargo "+$TOOLCHAIN" ${@:2} 116 ;; 117 *) 118 print-usage-and-exit 119 ;; 120esac 121