#!/usr/bin/env bash # SPDX-License-Identifier: Apache-2.0 # Copyright (C) 2021 Arm Limited or its affiliates and Contributors. All rights reserved. [[ "$TRACE" ]] && set -x set -euo pipefail print_help() { echo 'Usage: manyclangs-run [ELFSHAKER] [COMITTISH] [COMMAND]...' echo '' echo 'Extracts the snapshot matching COMITTISH to the specified ELFSHAKER directory and runs COMMAND.' echo 'If the first token of COMMAND is a path to a file in the ELFSHAKER directory, that path will be resolved as an absolute path to that file.' echo '' echo 'The commit is matched to a snapshot by searching for a snapshot with a tag containing a part of the truncated commit SHA.' echo 'ELFSHAKER/build/bin is removed, and ELFSHAKER/build/link.sh is run after extraction and before COMMAND.' echo '' echo 'If any step of finding a matching snapshot, extraction, or ./link.sh fails, the script exists with code 125 (git bisect skip).' echo 'Otherwise, the exit code is the code returned by COMMAND.' } get_file_arch() { readelf -h "$1" | grep Machine | awk '{$1=""; print $0}' | tr -d ' ' } has_docker_image() { docker image inspect "$1" &>/dev/null } run_docker_image() { docker run --rm --mount type=bind,source="$(realpath "$ELFSHAKER_DIR")",target=/elfshaker "$@" } link_and_run() { rm -r ./bin || true mkdir -p ./bin COMMAND_BASENAME="$(basename "$1")" LINK_AND_RUN_COMMAND="bash ./link.sh $COMMAND_BASENAME || exit 125; ./bin/$@" if [ "${USE_DOCKER_QEMU-,,}" = "aarch64" ]; then TEST_OBJECT=lib/Object/CMakeFiles/LLVMObject.dir/Object.cpp.o HOST_ARCH="$(get_file_arch /bin/cat)" TARGET_ARCH="$(get_file_arch "$TEST_OBJECT")" if [ "$HOST_ARCH" != "$TARGET_ARCH" ] && [ "$TARGET_ARCH" = "AArch64" ]; then if ! command -v docker &> /dev/null; then echo "The architecture of the executables you are attempting to run is '$TARGET_ARCH'." echo "We support running these on '$HOST_ARCH' through emulation, but require docker to do so." echo "Please install docker. https://www.docker.com/" exit 125 elif ! has_docker_image manyclangs-qemu-aarch64 &>/dev/null; then echo 'You need the manyclangs-qemu-aarch64 docker image to run manyclangs with AArch64 emulation.' echo 'See https://github.com/elfshaker/manyclangs/blob/main/docker-qemu-aarch64/README.md for instructions.' exit 1 else run_docker_image manyclangs-qemu-aarch64 bash -c "$LINK_AND_RUN_COMMAND" fi else echo "Running $TARGET_ARCH binaries on $HOST_ARCH via the manyclangs-qemu-aarch64 docker image is not supported!" exit 1 fi else $LINK_AND_RUN_COMMAND fi } main() { ELFSHAKER_DIR="$1" COMITTISH="$2" COMMAND=(${@:3}) SHA="$(git rev-parse --short=10 "$COMITTISH")" (cd "$ELFSHAKER_DIR" && elfshaker find "$SHA") | { read -r SNAPSHOT PACK || exit 125 TIMEFORMAT="elfshaker extracted $SHA in %R seconds" COMMAND_BASENAME="$(basename "${COMMAND[0]}")" time ( (cd "$ELFSHAKER_DIR" && elfshaker extract "$PACK:$SNAPSHOT" || exit 125) ) link_and_run "${COMMAND[@]}" } } case "${1:--h}" in -h | --help) print_help [ $# -ne 0 ] exit $? ;; *) main "$@" ;; esac