#!/bin/sh
set -eu

SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd -P)"
FREEBSD_SRC="${FREEBSD_SRC:-/usr/src}"
FS_SRC="${SCRIPT_DIR}/src"
BUILD_DIR="${SCRIPT_DIR}/build"
WORK_DIR="${BUILD_DIR}/obj"
MAKE="${MAKE:-make}"
WITH_ZSTDIO="${WITH_ZSTDIO:-0}"
NM_UNDEF=""

cleanup() {
	[ -z "${NM_UNDEF}" ] || rm -f "${NM_UNDEF}"
}

trap cleanup EXIT
trap 'cleanup; exit 1' HUP INT TERM

fail() {
	echo "ERROR: $*" >&2
	exit 1
}

make_kmod() {
	MAKEOBJDIR="${WORK_DIR}" "${MAKE}" -C "${FS_SRC}" \
		SRCTOP="${FREEBSD_SRC}" SYSDIR="${FREEBSD_SRC}/sys" \
		WITH_ZSTDIO="${WITH_ZSTDIO}" "$@"
}

[ "$(uname -s)" = "FreeBSD" ] ||
	fail "build.sh requires a native FreeBSD build host"
[ -d "${FREEBSD_SRC}/sys" ] ||
	fail "FreeBSD source tree not found: ${FREEBSD_SRC}"
[ -d "${FS_SRC}" ] || fail "Source directory not found: ${FS_SRC}"
command -v "${MAKE}" >/dev/null 2>&1 || fail "make is required"
command -v awk >/dev/null 2>&1 || fail "awk is required"
command -v nm >/dev/null 2>&1 || fail "nm is required"
[ -f "${FREEBSD_SRC}/sys/tools/vnode_if.awk" ] ||
	fail "vnode_if.awk not found in ${FREEBSD_SRC}"
[ -f "${FREEBSD_SRC}/sys/kern/vnode_if.src" ] ||
	fail "vnode_if.src not found in ${FREEBSD_SRC}"
case "${WITH_ZSTDIO}" in
0|1) ;;
*) fail "WITH_ZSTDIO must be 0 or 1" ;;
esac

rm -rf "${WORK_DIR}"
mkdir -p "${WORK_DIR}"
KMOD="$(make_kmod -V PROG)"
[ -n "${KMOD}" ] || fail "src/Makefile did not define a module output"

echo "==> Building repo22 ${KMOD}"
make_kmod all

[ -f "${WORK_DIR}/${KMOD}" ] || fail "module was not produced"

NM_UNDEF="$(mktemp "${WORK_DIR}/nm-undef.XXXXXX")" ||
	fail "could not create nm output file"
if ! nm -u "${WORK_DIR}/${KMOD}" >"${NM_UNDEF}"; then
	fail "nm failed while checking ${KMOD}"
fi
if ! awk '$NF == "bcmp" { found = 1 } END { exit found }' "${NM_UNDEF}"; then
	fail "${KMOD} contains an unresolved bcmp reference"
fi

cp -f "${WORK_DIR}/${KMOD}" "${BUILD_DIR}/"
echo "==> SUCCESS: ${BUILD_DIR}/${KMOD}"
