xo-umbrella2/xo-cmake/bin/xo-docker-build.in
Roland Conybeare fa0c57d2c6
Some checks failed
cmake-docker / cmake-build (push) Failing after 18m46s
CI / smoke-test (push) Failing after 25m8s
xo-cmake: drop broken --gh-action-log feature
2026-07-25 21:18:27 -04:00

150 lines
5.4 KiB
Bash

#!/usr/bin/env bash
# Build xo subsystems inside the docker-xo-builder container.
#
# Two modes, selected by how you point it at source:
#
# installed (default) bootstrap xo-cmake from the snapshot installed
# alongside this script (@CMAKE_INSTALL_FULL_DATADIR@/xo-cmake/src), and
# take subsystem source by cloning committed HEAD of the target repo.
# The container's build tooling therefore always matches the installed
# xo-docker-build you ran. (Not a byte-exact CI reproduction: CI
# bootstraps xo-cmake from the cloned HEAD, not from an install.)
#
# worktree --xo-root-dir[=DIR]: use the xo umbrella worktree DIR
# directly -- copy it into the container, bootstrap xo-cmake from
# DIR/xo-cmake, and build DIR's subsystems. Picks up uncommitted edits to
# both tooling and subsystem source.
#
# In both modes the in-container build is
#
# xo-build <selection> --with-deps --configure --build --utest --install \
# --with-utests --with-examples --gh-action-log
#
# The container starts empty, so --with-deps is always used: naming a subsystem
# also builds its whole dependency closure. With no subsystem named it builds
# --all (the entire umbrella).
set -euo pipefail
# location of the installed xo-cmake bootstrap snapshot (baked at configure time)
xo_cmake_src="@CMAKE_INSTALL_FULL_DATADIR@/xo-cmake/src"
self="$(basename "$0")"
usage() {
cat <<EOF
usage: ${self} [-n|--dry-run] [--image=IMAGE]
${self} [--repo=DIR | --xo-root-dir[=DIR]] [NAME ...]
-n | --dry-run print the docker command instead of running it
--image=IMAGE builder image to run in
[default: \${XO_BUILDER_IMAGE:-docker-xo-builder:v2}]
-h | --help this message
--repo=DIR (installed mode) umbrella repo to clone committed HEAD from
[default: git toplevel of the current directory]
--xo-root-dir[=DIR]
(worktree mode) build directly from the xo umbrella worktree
DIR (default: git toplevel of the current directory),
including uncommitted edits. xo-cmake is bootstrapped from
DIR/xo-cmake instead of the install snapshot.
NAME ... subsystems to build (e.g. xo-arena). Each named subsystem's
dependency closure is built automatically. With none given,
builds every subsystem via 'xo-build --all'.
EOF
}
image="${XO_BUILDER_IMAGE:-docker-xo-builder:v2}"
repo=
xo_root_dir=
xo_root_set=0
dry_run=0
selection=()
while [[ $# -gt 0 ]]; do
case "$1" in
-h|--help) usage; exit 0 ;;
-n|--dry-run) dry_run=1 ;;
--image=*) image="${1#*=}" ;;
--repo=*) repo="${1#*=}" ;;
--xo-root-dir) xo_root_set=1 ;;
--xo-root-dir=*) xo_root_set=1; xo_root_dir="${1#*=}" ;;
xo-*|--all) selection+=("$1") ;;
*) echo "${self}: unexpected argument [$1]" >&2; usage >&2; exit 1 ;;
esac
shift
done
if [[ $xo_root_set -eq 1 && -n "$repo" ]]; then
echo "${self}: --repo and --xo-root-dir are mutually exclusive" >&2
exit 1
fi
# default a whole-umbrella build
if [[ ${#selection[@]} -eq 0 ]]; then
selection=(--all)
fi
if [[ $xo_root_set -eq 1 ]]; then
# ---- worktree mode: source (tooling + subsystems) is the worktree ----
mode="worktree"
if [[ -z "$xo_root_dir" ]]; then
xo_root_dir="$(git rev-parse --show-toplevel)"
fi
src_mount="$xo_root_dir"
# copy the worktree in (uncommitted edits included), minus git + build dirs
stage_cmd='tar -C /src --exclude="./.git" --exclude="./.build*" --exclude="*/.build" -cf - . | tar -C /work -xf -'
boot_src='/work/xo-cmake'
extra_mounts=()
else
# ---- installed mode: tooling from install snapshot, subsystems from HEAD ----
mode="installed"
if [[ ! -d "$xo_cmake_src" ]]; then
echo "${self}: xo-cmake source snapshot not found at:" >&2
echo " ${xo_cmake_src}" >&2
echo " install xo-cmake first, or use --xo-root-dir[=DIR] to build from a worktree." >&2
exit 1
fi
if [[ -z "$repo" ]]; then
repo="$(git rev-parse --show-toplevel)"
fi
src_mount="$repo"
stage_cmd='git clone --quiet --depth=1 file:///src /work'
boot_src='/xo-cmake-src'
extra_mounts=(-v "${xo_cmake_src}:/xo-cmake-src:ro")
fi
# in-container driver. host-expanded: ${mode} ${stage_cmd} ${boot_src};
# container-runtime vars are escaped (\$) so they survive to the container.
inner=$(cat <<INNER
set -euo pipefail
PREFIX=/work/local
export PATH="\$PREFIX/bin:\$PATH"
rm -rf /work && mkdir -p /work
${stage_cmd}
mkdir -p "\$PREFIX"
cd /work
cmake -S "${boot_src}" -B /work/.build/xo-cmake -DCMAKE_INSTALL_PREFIX="\$PREFIX"
cmake --build /work/.build/xo-cmake
cmake --install /work/.build/xo-cmake
xo-build "\$@" --with-deps --configure --build --utest --install \\
--with-utests --with-examples
INNER
)
docker_cmd=(docker run --rm -i -v "${src_mount}:/src:ro" "${extra_mounts[@]}" "${image}"
bash -s -- "${selection[@]}")
if [[ $dry_run -eq 1 ]]; then
printf '%q ' "${docker_cmd[@]}"; echo
echo "--- mode=${mode}; bootstrap -S ${boot_src}"
echo "--- inner: xo-build ${selection[*]} --with-deps --configure --build --utest --install --with-utests --with-examples"
exit 0
fi
exec "${docker_cmd[@]}" <<<"$inner"