#!/usr/bin/env bash
#
# Host side of the Linux GPU dependency stack build. Drives
# script/package-linux-gpu-stack-build.sh inside a RHEL 8 generation container,
# because the stack has to match the glibc baseline Navop is built against and
# only that distribution generation ships a Mesa user space at it.
#
# Docker is used for its package manager, not for cross-architecture emulation:
# the container runs natively on the host runner while the RPMs it resolves
# target --target's architecture. Nothing in the pipeline executes a collected
# library, so no emulator is required.
set -euo pipefail
repository_root="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")/.." && pwd)"
default_image="rockylinux:8"
binary=""
target=""
output=""
image="$default_image"
source_distribution=""
usage() {
cat <<'USAGE'
Usage: package-linux-gpu-stack-docker.sh --binary PATH --target TRIPLE --output DIR [options]
Options:
--binary PATH release Navop binary for the target
--target TRIPLE x86_64-unknown-linux-gnu or aarch64-unknown-linux-gnu
--output DIR directory to receive navop-gpu-stack-linux-.tar.gz
--image NAME build container (default rockylinux:8)
--source-distribution TEXT overrides the distribution string in the manifest
--help
USAGE
}
fail() {
printf 'Error: %s\n' "$*" >&2
exit 1
}
parse_arguments() {
while [ "$#" -gt 0 ]; do
case "$1" in
--binary)
shift
[ "$#" -gt 0 ] || fail "--binary requires a path"
binary="$1"
;;
--target)
shift
[ "$#" -gt 0 ] || fail "--target requires a triple"
target="$1"
;;
--output)
shift
[ "$#" -gt 0 ] || fail "--output requires a directory"
output="$1"
;;
--image)
shift
[ "$#" -gt 0 ] || fail "--image requires a name"
image="$1"
;;
--source-distribution)
shift
[ "$#" -gt 0 ] || fail "--source-distribution requires text"
source_distribution="$1"
;;
-h | --help)
usage
exit 0
;;
*)
fail "unknown argument: $1 (try --help)"
;;
esac
shift
done
[ -n "$binary" ] || fail "--binary is required"
[ -n "$target" ] || fail "--target is required"
[ -n "$output" ] || fail "--output is required"
}
main() {
parse_arguments "$@"
command -v docker >/dev/null 2>&1 ||
fail "docker is required to resolve the RHEL 8 dependency tree"
[ -f "$binary" ] || fail "release binary does not exist: $binary"
binary="$(cd -- "$(dirname -- "$binary")" && pwd)/$(basename -- "$binary")"
mkdir -p "$output"
output="$(cd -- "$output" && pwd)"
# The container only ever sees three mounts: the repository (read only), the
# binary's directory, and the output directory.
local binary_directory
binary_directory="$(dirname -- "$binary")"
local container_arguments=(
--binary "/binary/$(basename -- "$binary")"
--target "$target"
--output /out
)
if [ -n "$source_distribution" ]; then
container_arguments+=(--source-distribution "$source_distribution")
fi
docker run --rm \
-v "$repository_root:/workspace:ro" \
-v "$binary_directory:/binary:ro" \
-v "$output:/out" \
--workdir /workspace \
"$image" \
bash /workspace/script/package-linux-gpu-stack-build.sh "${container_arguments[@]}"
# Resolve the newest archive with portable test operators only: the GNU-only
# `find` time predicates are unavailable on a BSD userland.
local archive="" candidate
for candidate in "$output"/navop-gpu-stack-linux-*.tar.gz; do
[ -f "$candidate" ] || continue
if [ -z "$archive" ] || [ "$candidate" -nt "$archive" ]; then
archive="$candidate"
fi
done
[ -n "$archive" ] || fail "the build container produced no dependency archive in $output"
printf 'Dependency stack written: %s\n' "$archive"
}
main "$@"