Files
OpenShell/tasks/scripts/vm/build-supervisor-bundle.sh
Jim Meyer 745512e325 fix(build): raise open-file limit for host musl cross-compile on macOS (#2307)
Closes #2112

The host `cargo zigbuild` for `*-unknown-linux-musl` opens ~333 `.rlib`
files at once during the static link, exceeding macOS's default soft
limit of 256 and failing with `ProcessFdQuotaExceeded`. This blocked the
docker/podman `mise run gateway` paths for macOS contributors; only the
VM driver path guarded against it.

Extract the VM path's `ensure_build_nofile_limit` guard into a shared
`tasks/scripts/build-env.sh` and call it from the host-staging chokepoint
(`stage-prebuilt-binaries.sh`), fixing docker, podman, and all
docker:*/multiarch host cross-compiles at once. De-duplicate the VM
script to source the shared helper. The guard is a no-op on Linux and
when cargo-zigbuild is absent, so CI and Linux dev are unaffected. The
limit is read from `OPENSHELL_BUILD_NOFILE_LIMIT` (default 8192),
honoring the legacy `OPENSHELL_VM_BUILD_NOFILE_LIMIT` for back-compat.

Also correct the stale comment in gateway-docker.sh (the cross-compile
runs on the host, not inside Linux containers) and document the guard in
architecture/build.md. Adds tasks/scripts/test-build-env.sh, wired into
`mise run test` via `test:build-env`.

Signed-off-by: Jim Meyer <jim@meyer4hire.com>
2026-07-20 21:11:20 +00:00

129 lines
4.0 KiB
Bash
Executable File

#!/usr/bin/env bash
# SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
# SPDX-License-Identifier: Apache-2.0
set -euo pipefail
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../../.." && pwd)"
OUTPUT_DIR="${OPENSHELL_VM_RUNTIME_COMPRESSED_DIR:-${ROOT}/target/vm-runtime-compressed}"
# shellcheck source=tasks/scripts/build-env.sh
source "${ROOT}/tasks/scripts/build-env.sh"
GUEST_ARCH=""
while [[ $# -gt 0 ]]; do
case "$1" in
--arch)
GUEST_ARCH="$2"
shift 2
;;
--arch=*)
GUEST_ARCH="${1#--arch=}"
shift
;;
--help|-h)
echo "Usage: $0 [--arch aarch64|x86_64]"
exit 0
;;
*)
echo "Unknown argument: $1" >&2
exit 1
;;
esac
done
if [ -z "${GUEST_ARCH}" ]; then
case "$(uname -m)" in
aarch64|arm64) GUEST_ARCH="aarch64" ;;
x86_64|amd64) GUEST_ARCH="x86_64" ;;
*)
echo "ERROR: Unsupported host architecture: $(uname -m)" >&2
echo " Use --arch aarch64 or --arch x86_64 to override." >&2
exit 1
;;
esac
fi
case "${GUEST_ARCH}" in
aarch64|arm64)
RUST_TARGET="aarch64-unknown-linux-gnu"
;;
x86_64|amd64)
RUST_TARGET="x86_64-unknown-linux-gnu"
;;
*)
echo "ERROR: Unsupported guest architecture: ${GUEST_ARCH}" >&2
echo " Supported: aarch64, x86_64" >&2
exit 1
;;
esac
SUPERVISOR_BIN="${ROOT}/target/${RUST_TARGET}/release/openshell-sandbox"
SUPERVISOR_OUTPUT="${OUTPUT_DIR}/openshell-sandbox.zst"
echo "==> Building openshell-sandbox supervisor bundle"
echo " Guest arch: ${GUEST_ARCH}"
echo " Rust target: ${RUST_TARGET}"
echo " Output: ${SUPERVISOR_OUTPUT}"
mkdir -p "${OUTPUT_DIR}"
ensure_build_nofile_limit
SUPERVISOR_BUILD_LOG="$(mktemp -t openshell-supervisor-build.XXXXXX.log)"
run_supervisor_build() {
local rustc_wrapper_mode="${1:-default}"
local cargo_prefix=()
if [ "${rustc_wrapper_mode}" = "without-rustc-wrapper" ]; then
cargo_prefix=(env -u RUSTC_WRAPPER)
fi
if command -v cargo-zigbuild >/dev/null 2>&1; then
${cargo_prefix[@]+"${cargo_prefix[@]}"} cargo zigbuild --release -p openshell-sandbox --target "${RUST_TARGET}" \
--manifest-path "${ROOT}/Cargo.toml"
else
echo " cargo-zigbuild not found, falling back to cargo build..."
${cargo_prefix[@]+"${cargo_prefix[@]}"} cargo build --release -p openshell-sandbox --target "${RUST_TARGET}" \
--manifest-path "${ROOT}/Cargo.toml"
fi
}
print_build_failure() {
echo "ERROR: supervisor build failed. Full output:" >&2
cat "${SUPERVISOR_BUILD_LOG}" >&2
echo " (log saved at ${SUPERVISOR_BUILD_LOG})" >&2
}
if run_supervisor_build >"${SUPERVISOR_BUILD_LOG}" 2>&1; then
tail -5 "${SUPERVISOR_BUILD_LOG}"
rm -f "${SUPERVISOR_BUILD_LOG}"
else
status=$?
if [ -n "${RUSTC_WRAPPER:-}" ] && grep -Eq 'sccache: encountered fatal error|Too many open files|os error 24' "${SUPERVISOR_BUILD_LOG}"; then
echo "WARNING: supervisor build failed through RUSTC_WRAPPER=${RUSTC_WRAPPER}; retrying without RUSTC_WRAPPER." >&2
: >"${SUPERVISOR_BUILD_LOG}"
if run_supervisor_build without-rustc-wrapper >"${SUPERVISOR_BUILD_LOG}" 2>&1; then
tail -5 "${SUPERVISOR_BUILD_LOG}"
rm -f "${SUPERVISOR_BUILD_LOG}"
else
status=$?
print_build_failure
exit "${status}"
fi
else
print_build_failure
exit "${status}"
fi
fi
if [ ! -f "${SUPERVISOR_BIN}" ]; then
echo "ERROR: supervisor binary not found at ${SUPERVISOR_BIN}" >&2
exit 1
fi
zstd -19 -T0 -f "${SUPERVISOR_BIN}" -o "${SUPERVISOR_OUTPUT}"
echo "==> Bundled supervisor ready"
echo " Binary: $(du -sh "${SUPERVISOR_BIN}" | cut -f1)"
echo " Compressed: $(du -sh "${SUPERVISOR_OUTPUT}" | cut -f1)"