blob: 261b4c1902c1c61f7c6884387dc3022684168c4e [file] [log] [blame]
#!/bin/bash -eu
# Copyright 2022 The ChromiumOS Authors.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
#
# Script intended to be hacked on by you and run by `git bisect run`, like so:
# `git bisect run ./run_bisection_step.sh`.
#
# Note that `set -e` doesn't play well at all with `git bisect`, but letting
# errors potentially pass silently seems really bad. We don't want to signal to
# `git bisect` that a revision is new because we failed to `mktemp`.
#
# Hence, this script is structured so that you _must_ call one of
# {bisect_new,bisect_old,bisect_skip} before this script exits. These functions
# will all terminate the script immediately. If you do that, this script will
# exit with the appropriate exit code. If not, it'll exit with a code that will
# abort `git bisect`ion.
# Internal details. Feel free to skip to the bottom of this script, which has
# examples/commentary.
BISECT_RESULT=abort
# Make a temporary file for convenience, since it's likely the user will
# need/want it for `grep`ing failing command output/etc.
temp_file=
cleanup() {
local exit_code=$?
if [[ -n "${temp_file:-}" ]]; then
rm -f "${temp_file}" || :
fi
local exit_code
case "${BISECT_RESULT}" in
abort )
echo "Internal error: script exited with code ${exit_code}." >&2
echo "Note: Users should call one of bisect_{old,new,skip} before exiting." >&2
exit 128
;;
old )
exit_code=0
;;
new )
exit_code=1
;;
skip )
exit_code=125
;;
* )
echo "Internal error: unknown BISECT_RESULT: ${BISECT_RESULT}" >&2
exit 128
;;
esac
# If we apply patches to Rust sources, we need to clean them up before
# returning control to `git bisect`. Otherwise, `git bisect`'s next
# `checkout` may fail due to modified files.
if ! "${my_dir}/clean_and_sync_rust_root.sh" >& /dev/null; then
echo "Failed cleaning/syncing Rust root; bisection might fail..." >&2
# Keep going anyway, knowing that at worst, `git bisect` will simply give up.
fi
exit "${exit_code}"
}
trap "cleanup" EXIT
my_dir="$(dirname "$(readlink -m "$0")")"
# Verify that cros-rust is set to build from "${FILESDIR}/rust" enabled. If
# not, `git bisect` is unlikely to do anything of value.
if ! grep -q '^CROS_RUSTC_BUILD_RAW_SOURCES=.' "${my_dir}/../../../../eclass/cros-rustc.eclass"; then
echo "It seems CROS_RUSTC_BUILD_RAW_SOURCES is unset. This is likely a mistake." >&2
exit 1
fi
# Running this from outside of the chroot is not supported.
if [[ ! -e /etc/cros_chroot_version ]]; then
echo "It seems this script was invoked from outside of the chroot. This is unsupported." >&2
exit 1
fi
temp_file="$(mktemp)"
bisect_old() { BISECT_RESULT=old; exit; }
bisect_new() { BISECT_RESULT=new; exit; }
bisect_skip() { BISECT_RESULT=skip; exit; }
# Instruct dev-lang/rust to use ccache for LLVM builds. This saves considerable
# time on incremental rebuilds.
export FEATURES=ccache
# Start by preparing our source directory. If any of these steps fail, we
# want to abort bisection as a whole; something's gone very wrong.
"${my_dir}/clean_and_sync_rust_root.sh"
"${my_dir}/prepare_rust_for_offline_build.sh"
# Now build Rust, skipping if this revision isn't buildable. Output is tee'd to
# a temp file in case it's useful to you.
#
# If you want to check whether a build failed because patches failed to apply,
# you can do something like:
# ```
# if sudo ebuild $(equery w dev-lang/rust-host) clean configure >& >(tee "${temp_file}"); then
# bisect_old
# fi
#
# if grep -qF 'Applying Rust patches...' "${temp_file}" && ! grep -qF 'Rust patch application completed successfully' "${temp_file}"; then
# bisect_new
# fi
# bisect_skip
# ```
#
# In general, it's recommended to `bisect_skip` on failed builds of Rust,
# unless you're trying to troubleshoot something about the actual build of
# dev-lang/rust{,-host}. ToT can always be red.
sudo emerge dev-lang/rust{,-host} >& >(tee "${temp_file}") || bisect_skip
# Put your test-case here. An example might be:
# ```
# setup_board --board=atlas || bisect_skip
# emerge-atlas memd |& tee "${temp_file}"
# if grep -q some-error "${temp_file}"; then
# bisect_new
# else
# bisect_old
# fi
# ```