blob: befaf053643cc35572ecc5934263dcf3a309c053 [file] [log] [blame]
#!/bin/bash
# Copyright lowRISC contributors.
# Licensed under the Apache License, Version 2.0, see LICENSE for details.
# SPDX-License-Identifier: Apache-2.0
# This is a wrapper script for `bazelisk` that downloads and executes bazelisk.
# Bazelisk is a wrapper for `bazel` that can download and execute the project's
# required bazel version.
#
# CI jobs should use ci/bazelisk.sh instead, which performs CI-friendly additional
# setup.
set -euo pipefail
# Change to this script's directory, as it is the location of the bazel workspace.
cd "$(dirname "$0")"
: "${CURL_FLAGS:=--silent}"
: "${REPO_TOP:=$(git rev-parse --show-toplevel)}"
: "${BINDIR:=.bin}"
: "${BAZEL_BIN:=$(which bazel)}"
readonly release="v1.11.0"
declare -A hashes=(
# sha256sums for v1.11.0. Update this if you update the release.
[linux-amd64]="231ec5ca8115e94c75a1f4fbada1a062b48822ca04f21f26e4cb1cd8973cd458"
)
declare -A architectures=(
# Map `uname -m -o` to bazelisk's precompiled binary target names.
[x86_64 GNU/Linux]="linux-amd64"
)
function os_arch() {
local arch
arch="$(uname -m -o)"
echo "${architectures[$arch]:-${arch}}"
}
function check_hash() {
local file target
file="$1"
target="$(os_arch)"
echo "${hashes[$target]} $file" | sha256sum --check --quiet
}
function prepare() {
local target
target="$(os_arch)"
local bindir="${REPO_TOP}/${BINDIR}"
local file="${bindir}/bazelisk"
local url="https://github.com/bazelbuild/bazelisk/releases/download/${release}/bazelisk-${target}"
mkdir -p "$bindir"
echo "Downloading bazelisk ${release} (${url})." >> $bindir/bazelisk.log
curl ${CURL_FLAGS} --location "$url" --output "$file"
chmod +x "$file"
}
function up_to_date() {
local file="$1"
# We need an update if the file doesn't exist or it has the wrong hash
test -f "$file" || return 1
check_hash "$file" || return 1
return 0
}
function outquery_starlark_expr() {
local query="$1"
shift
if [[ ${query} == "outquery" ]]; then
q="-one"
else
q=${query#outquery}
fi
case "$q" in
-one)
echo "target.files.to_list()[0].path"
;;
-all)
echo "\"\\n\".join([f.path for f in target.files.to_list()])"
;;
-*)
echo "\"\\n\".join([f.path for f in target.files.to_list() if \"$q\"[1:] in f.path])"
;;
.*)
echo "\"\\n\".join([f.path for f in target.files.to_list() if f.path.endswith(\"$q\")])"
;;
esac
}
function do_outquery() {
local qexpr="$1"
shift
"$file" cquery "$@" \
--output=starlark --starlark:expr="$qexpr" \
--ui_event_filters=-info --noshow_progress
}
function main() {
local bindir="${REPO_TOP}/${BINDIR}"
local file="${BAZEL_BIN:-${bindir}/bazelisk}"
local lockfile="${bindir}/bazelisk.lock"
# Are we using bazel from the user's PATH or using bazelisk?
if expr match "${file}" ".*bazelisk$" >/dev/null; then
if ! up_to_date "$file"; then
# Grab the lock, blocking until success. Upon success, check again
# whether we're up to date (because some other process might have
# downloaded bazelisk in the meantime). If not, download it ourselves.
mkdir -p "$bindir"
(flock -x 9; up_to_date "$file" || prepare) 9>>"$lockfile"
fi
if ! check_hash "$file"; then
echo "sha256sum doesn't match expected value"
exit 1
fi
fi
case "$1" in
outquery*)
# The custom 'outquery' command can be used to query bazel for the
# outputs associated with labels.
# The outquery command can take several forms:
# outquery: return one output file associated with the label.
# outquery-all: return all output files associated with the label.
# outquery-x: return output files containing the substring "x".
# outquery.x: return output files ending with the substring ".x".
local qexpr
qexpr="$(outquery_starlark_expr "$1")"
shift
do_outquery "$qexpr" "$@"
;;
build-then)
# The 'build-then' command builds the requested targets and then
# evaluates the given command template, replacing "%s" with the path
# to an output file.
#
# For example, the command below would build "//:foo" and run "less"
# on one of the output files.
#
# ./bazelisk.sh build-then "less %s" //:foo
shift
local command_template="$1"
shift
local qexpr outfile
qexpr="$(outquery_starlark_expr outquery)"
outfile=$(do_outquery "$qexpr" "$@")
"$file" build "$@"
# shellcheck disable=SC2059
# We are intentionally using $command_template as a format string.
eval "$(printf "$command_template" "$outfile")"
;;
*)
exec "$file" "$@"
;;
esac
}
main "$@"