blob: 9ef8165de975c788381ffeac68c84d5ff9315b5d [file] [log] [blame]
#!/bin/bash
#
# Copyright 2020 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
PLATFORM=${PLATFORM:-shodan}
## Shamelessly borrowed from android's envsetup.sh.
function getrootdir
{
local TOPFILE="build/Makefile"
# if env variable `SHODAN_ROOTDIR` is set, the setting is sticky.
if [[ -n "$SHODAN_ROOTDIR" && -f "$SHODAN_ROOTDIR/$TOPFILE" ]]; then
# The following circumlocution ensures we remove symlinks
# from SHODAN_ROOTDIR.
(cd "${SHODAN_ROOTDIR}"; PWD= /bin/pwd)
else
if [[ -f "${TOPFILE}" ]]; then
# The following circumlocution (repeated below as well) ensures
# that we record the true directory name and not one that is
# faked up with symlink names.
PWD= /bin/pwd
else
local HERE="${PWD}"
local R=
while [ \( ! \( -f "${TOPFILE}" \) \) -a \( "${PWD}" != "/" \) ]; do
\cd ..
R=`PWD= /bin/pwd -P`
done
\cd "${HERE}"
if [ -f "${R}/${TOPFILE}" ]; then
echo "${R}"
fi
fi
fi
}
export ROOTDIR="$(getrootdir)"
export OUT="${ROOTDIR}/out"
export CACHE="${ROOTDIR}/cache"
# NB: platform setup.sh (included below) sets up the rust toolchain
export PATH="${HOME}/.local/bin:${PATH}"
export PATH="${CACHE}/toolchain/bin:${PATH}"
export PATH="${ROOTDIR}/scripts:${PATH}"
export PATH="${CACHE}/renode:${PATH}"
export PATH="${OUT}/host/qemu/riscv32-softmmu:${PATH}"
export PATH="${OUT}/host/flatbuffers/bin:${PATH}"
export PATH="${OUT}/host/verilator/bin:${PATH}"
export PATH="${OUT}/host/verible/bin:${PATH}"
export CANTRIP_RUST_VERSION=${CANTRIP_RUST_VERSION:-"nightly-2023-04-20"}
export RENODE_PORT=1234
export PYTHONPATH="${PYTHONPATH}:${ROOTDIR}/cicd/"
export PYTHON_SHODAN_ENV="${CACHE}/python-venv"
function renode
{
"${CACHE}/renode/renode" "$@"
}
function iss
{
(cd "${ROOTDIR}" && python3 "${ROOTDIR}/scripts/quick_sim.py" "$@")
}
function get-groups
{
git --git-dir="${ROOTDIR}/.repo/manifests.git" config \
--get manifest.groups
}
function m
{
(cd "${ROOTDIR}" && make -f "${ROOTDIR}/build/Makefile" "$@")
return $?
}
function _hmm
{
local targetname="$1"; shift
targetname="${targetname}" gawk -f "${ROOTDIR}/build/helpmemake.awk" \
"${ROOTDIR}/build/Makefile" \
"${ROOTDIR}/build/platforms/${PLATFORM}"/*.mk \
"${ROOTDIR}"/build/*.mk
}
function hmm
{
local usage="Usage: hmm [-h] [-l] <targetname>"
local long=""
local args=$(getopt hl $*)
set -- $args
for i; do
case "$1" in
-l)
long=1
shift 1
;;
--)
shift
break
;;
-h|*)
echo $usage >/dev/stderr
return 1
;;
esac
done
local targetname="${1}"; shift
if [[ -n "${targetname}" ]]; then
_hmm "${targetname}"
return 0
fi
if [[ -z "${long}" ]]; then
_hmm | fmt --width=80
else
_hmm
fi
}
function safe-abandon
{
local branch="${1}"; shift
if [[ -z "${branch}" ]]; then
echo "Usage: safe-abandon <branchname>"
echo
echo "Abandons a repo branch in the current project only."
echo "This is much safer than using the actual 'repo abandon'"
echo "command, since it won't globally revert branches across"
echo "the entire project space."
echo
return 1
fi
repo abandon "${branch}" .
}
function list-platforms
{
for i in $(echo "${ROOTDIR}/build/platforms"/*); do
basename $i |sed 's/\.sh$//'
done
}
function set-platform
{
local platform="${1}"; shift
if [[ -z "${platform}" ]]; then
(
echo "Usage: set-platform <platform>"
echo
echo "Sets the target platform for the build. Platforms available are:"
echo
list-platforms
echo
) | fmt
return 1
fi
export PLATFORM="${platform}"
export CANTRIP_OUT_DIR="${OUT}/cantrip/${PLATFORM}"
export CHERIOT_OUT_DIR="${OUT}/cheriot/${PLATFORM}"
source "${ROOTDIR}/build/platforms/${platform}/setup.sh"
}
function kcargo
{
# NB: sel4-config needs a path to the kernel build which could be
# in debug or release (for our needs either works)
local SEL4_OUT_DIR="${CANTRIP_OUT_DIR}/debug/kernel/"
if [[ ! -d "${SEL4_OUT_DIR}/gen_config" ]]; then
SEL4_OUT_DIR="${CANTRIP_OUT_DIR}/release/kernel/"
if [[ ! -d "${SEL4_OUT_DIR}/gen_config" ]]; then
echo "No kernel build found at ${SEL4_OUT_DIR}; build a kernel first"
set +x
return 1
fi
fi
local SEL4_PLATFORM=$(awk '$1 == "CONFIG_PLATFORM" {print $3}' "$ROOTDIR/build/platforms/$PLATFORM/cantrip.mk")
local RUST_TARGET=$(awk '/RUST_TARGET/{print $3}' "$ROOTDIR/build/platforms/$PLATFORM/cantrip_apps.mk")
local CARGO_CMD="cargo +${CANTRIP_RUST_VERSION}"
local CARGO_TARGET="--target ${RUST_TARGET} --features ${SEL4_PLATFORM}"
local CARGO_OPTS='-Z unstable-options -Z avoid-dev-deps'
# TODO(sleffler): maybe set --target-dir to avoid polluting the src tree
# NB: we don't want to export anything to the user's shell (in particular
# RUSTFLAGS), hence the subshell parenthesis.
(
export RUSTFLAGS='-Z tls-model=local-exec'
export SEL4_OUT_DIR="$SEL4_OUT_DIR"
cmd=${1:-build}
case "$1" in
fmt)
${CARGO_CMD} $*;;
""|-*)
${CARGO_CMD} build ${CARGO_OPTS} ${CARGO_TARGET};;
clippy)
# NB: track preupload-clippy.sh
${CARGO_CMD} clippy ${CARGO_OPTS} ${CARGO_TARGET} \
--target-dir ${CANTRIP_OUT_DIR}/clippy -- \
-D warnings \
-A clippy::uninlined_format_args
;;
*)
${CARGO_CMD} $* ${CARGO_OPTS} ${CARGO_TARGET};;
esac
)
}
set-platform ${PLATFORM}
if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then
unset JUMP_TARGETS
declare -Ax JUMP_TARGETS
JUMP_TARGETS[.]="."
JUMP_TARGETS[top]="${ROOTDIR}"
JUMP_TARGETS[rootdir]="${ROOTDIR}"
JUMP_TARGETS[out]="${OUT}"
JUMP_TARGETS[build]="${ROOTDIR}/build"
JUMP_TARGETS[doc]="${ROOTDIR}/doc"
JUMP_TARGETS[sel4]="${ROOTDIR}/cantrip/kernel"
JUMP_TARGETS[kernel]="${ROOTDIR}/cantrip/kernel"
JUMP_TARGETS[cantrip]="${ROOTDIR}/cantrip/projects/cantrip"
JUMP_TARGETS[system]="${ROOTDIR}/cantrip/projects/cantrip/apps/system"
JUMP_TARGETS[c-apps]="${ROOTDIR}/cantrip/projects/cantrip/apps/c"
JUMP_TARGETS[rust-apps]="${ROOTDIR}/cantrip/projects/cantrip/apps/rust"
JUMP_TARGETS[debug]="${CANTRIP_OUT_DIR}/debug"
JUMP_TARGETS[release]="${CANTRIP_OUT_DIR}/release"
JUMP_TARGETS[tock]="${ROOTDIR}/sw/tock"
JUMP_TARGETS[sim]="${ROOTDIR}/sim"
function j
{
local target="$1"; shift
local splitpath=(${target//\// })
local subpath=""
if [[ -z "${target}" ]]; then
cd "${ROOTDIR}"
return 0
fi
if [[ -z "${JUMP_TARGETS[$target]}" ]]; then
target="${splitpath[0]}"
subpath="${splitpath[@]:1}"
fi
if [[ -z "${JUMP_TARGETS[$target]}" ]]; then
echo "Jump targets are:"
echo "${!JUMP_TARGETS[@]}"
return 1
fi
cd "${JUMP_TARGETS[$target]}"
if [[ ! -z "${subpath}" ]]; then
cd "${subpath}"
fi
}
if builtin complete >/dev/null 2>/dev/null; then
function _j_targets
{
echo "${!JUMP_TARGETS[@]}"
}
function _j
{
local cur="${COMP_WORDS[COMP_CWORD]}"
COMPREPLY=()
if [[ "${COMP_CWORD}" -eq 1 ]]; then
COMPREPLY=( $(compgen -W "$(_j_targets)" $cur) )
fi
}
complete -F _j j
function _complete_build_targets
{
local cur="${COMP_WORDS[COMP_CWORD]}"
COMPREPLY=()
if [[ "${COMP_CWORD}" -eq 1 ]]; then
COMPREPLY=( $(compgen -W "$(hmm -l)" $cur) )
fi
}
complete -F _complete_build_targets m
complete -F _complete_build_targets hmm
function _complete_platform_targets
{
local cur="${COMP_WORDS[COMP_CWORD]}"
COMPREPLY=()
if [[ "${COMP_CWORD}" -eq 1 ]]; then
COMPREPLY=( $(compgen -W "$(list-platforms)" $cur) )
fi
}
complete -F _complete_platform_targets set-platform
fi
fi
## Watch a file for a pattern and exit when matched or timed out
function expect_match
{
local match_string="$1"
local log_path="$2"
local timeout="$3"
if [[ -z "${match_string}" ]] || [[ -z "${log_path}" ]]; then
echo "Usage: expect_match <pattern> <file path> [timeout]"
echo " pattern: grep regexp pattern"
echo " file path: Path to file to search"
echo " timeout: optional timeout, defaults to 30s"
return 1
fi
log_path="$(realpath ${log_path})"
if [[ -z "${timeout}" ]]; then
timeout="30s"
fi
echo "Watching for ${match_string} in ${log_path}"
timeout "${timeout}" bash -c "until grep -q -e \"${match_string}\" \"${log_path}\"; do sleep 1; done"
}
# Explicitly set the variables to run the venv python interpreter.
export PATH="${PYTHON_SHODAN_ENV}/bin:${PATH}"
export VIRTUAL_ENV="${PYTHON_SHODAN_ENV}"
echo "========================================"
echo ROOTDIR="${ROOTDIR}"
echo OUT="${OUT}"
echo PLATFORM="${PLATFORM}"
echo PYTHON_SHODAN_ENV="${PYTHON_SHODAN_ENV}"
echo "========================================"
echo
echo Type \'m \[target\]\' to build.
echo
echo "Targets available are:"
echo
hmm
echo
echo "To get more information on a target, use 'hmm [target]'"
echo
declare -F parting_messages >/dev/null && parting_messages