Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 6 additions & 7 deletions architecture/build.md
Original file line number Diff line number Diff line change
Expand Up @@ -120,13 +120,12 @@ and the supervisor image from `deploy/docker/Dockerfile.supervisor`. Neither
Dockerfile compiles Rust — both copy a staged binary out of
`deploy/docker/.build/prebuilt-binaries/<arch>/` into the final image.

Local binary staging is driven by `tasks/scripts/stage-prebuilt-binaries.sh`. Because
staging cross-compiles on the host, it sources `tasks/scripts/build-env.sh` and
raises the per-process open-file limit before invoking `cargo zigbuild` on
macOS — the static musl link opens hundreds of `.rlib` files at once and would
otherwise fail with `ProcessFdQuotaExceeded` under macOS's default soft limit of
256. The guard is a no-op on Linux and when `cargo-zigbuild` is absent. Gateway
binaries use `cargo zigbuild` with GNU targets pinned to glibc 2.28, including
Local binary staging is driven by `tasks/scripts/stage-prebuilt-binaries.sh`.
It and the local gateway tasks source `tasks/scripts/build-env.sh` before host
Rust builds on macOS. The helper raises the per-process open-file limit because
sccache and static musl linking can each open hundreds of files, exceeding the
default soft limit of 256. The guard is a no-op on Linux. Gateway binaries use
`cargo zigbuild` with GNU targets pinned to glibc 2.28, including
native-architecture builds, so the gateway image, standalone tarballs, and Linux
packages share the same host portability floor. The gateway build enables
`bundled-z3`. Linux VM driver release artifacts use the same glibc floor so
Expand Down
2 changes: 1 addition & 1 deletion tasks/gateway.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

["build:gateway"]
description = "Build the standalone openshell-gateway binary"
run = "cargo build -p openshell-gateway --bin openshell-gateway"
run = "bash -c 'source tasks/scripts/build-env.sh && ensure_build_nofile_limit && cargo build -p openshell-gateway --bin openshell-gateway'"
hide = true

["gateway"]
Expand Down
24 changes: 10 additions & 14 deletions tasks/scripts/build-env.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,19 @@
# SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
# SPDX-License-Identifier: Apache-2.0

# Shared build-environment helpers for host-side cross-compilation.
# Shared build-environment helpers for host-side Rust builds.
#
# Source this file (do not execute it) and call the helpers before invoking
# cargo-zigbuild on the host.
# Cargo on the host.

# ensure_build_nofile_limit raises the per-process open-file limit before a
# host cargo-zigbuild cross-compile. The static *-unknown-linux-musl link opens
# hundreds of .rlib files simultaneously, which exceeds macOS's default soft
# limit of 256 and fails with ProcessFdQuotaExceeded. The raised limit
# propagates to the cargo/zig children the caller spawns.
# host Rust build. Sccache and static *-unknown-linux-musl links can each open
# hundreds of files simultaneously, exceeding macOS's default soft limit of
# 256. The raised limit propagates to the Cargo children the caller spawns.
#
# The limit is read from OPENSHELL_BUILD_NOFILE_LIMIT (default 8192), honoring
# the legacy OPENSHELL_VM_BUILD_NOFILE_LIMIT for back-compat. This is a no-op on
# Linux and when cargo-zigbuild is not installed (native builds, CI Linux
# runners), so it must be safe to call unconditionally.
# the legacy OPENSHELL_VM_BUILD_NOFILE_LIMIT for back-compat. This is a no-op
# on Linux, so it must be safe to call unconditionally.
ensure_build_nofile_limit() {
local desired="${OPENSHELL_BUILD_NOFILE_LIMIT:-${OPENSHELL_VM_BUILD_NOFILE_LIMIT:-8192}}"
local minimum=1024
Expand All @@ -26,8 +24,6 @@ ensure_build_nofile_limit() {
local target=""

[ "$(uname -s)" = "Darwin" ] || return 0
command -v cargo-zigbuild >/dev/null 2>&1 || return 0

current="$(ulimit -n 2>/dev/null || echo "")"
case "${current}" in
''|*[!0-9]*)
Expand All @@ -54,7 +50,7 @@ ensure_build_nofile_limit() {
esac

if [ "${target}" -gt "${current}" ] && ulimit -n "${target}" 2>/dev/null; then
echo "==> Raised open file limit for cargo-zigbuild: ${current} -> $(ulimit -n)"
echo "==> Raised open file limit for host Cargo build: ${current} -> $(ulimit -n)"
fi

current="$(ulimit -n 2>/dev/null || echo "${current}")"
Expand All @@ -65,11 +61,11 @@ ensure_build_nofile_limit() {
esac

if [ "${current}" -lt "${desired}" ]; then
echo "WARNING: Open file limit is ${current}; cargo-zigbuild is more reliable at ${desired}+ on macOS."
echo "WARNING: Open file limit is ${current}; host Cargo builds are more reliable at ${desired}+ on macOS."
fi

if [ "${current}" -lt "${minimum}" ]; then
echo "ERROR: Open file limit (${current}) is too low for cargo-zigbuild on macOS." >&2
echo "ERROR: Open file limit (${current}) is too low for host Cargo builds on macOS." >&2
echo " Run: ulimit -n ${desired}" >&2
echo " Then re-run this script." >&2
exit 1
Expand Down
4 changes: 4 additions & 0 deletions tasks/scripts/gateway-docker.sh
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@
set -euo pipefail

ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
# shellcheck source=tasks/scripts/build-env.sh
source "${ROOT}/tasks/scripts/build-env.sh"
ensure_build_nofile_limit

PORT="${OPENSHELL_SERVER_PORT:-18080}"
GATEWAY_NAME="${OPENSHELL_DOCKER_GATEWAY_NAME:-docker-dev}"
STATE_DIR="${OPENSHELL_DOCKER_GATEWAY_STATE_DIR:-${ROOT}/.cache/gateway-docker}"
Expand Down
4 changes: 4 additions & 0 deletions tasks/scripts/gateway-podman.sh
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@
set -euo pipefail

ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
# shellcheck source=tasks/scripts/build-env.sh
source "${ROOT}/tasks/scripts/build-env.sh"
ensure_build_nofile_limit

PORT="${OPENSHELL_SERVER_PORT:-18080}"
GATEWAY_NAME="${OPENSHELL_PODMAN_GATEWAY_NAME:-podman-dev}"
STATE_DIR="${OPENSHELL_PODMAN_GATEWAY_STATE_DIR:-${OPENSHELL_GATEWAY_STATE_DIR:-${ROOT}/.cache/gateway-podman}}"
Expand Down
4 changes: 4 additions & 0 deletions tasks/scripts/gateway-vm.sh
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,10 @@
set -euo pipefail

ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
# shellcheck source=tasks/scripts/build-env.sh
source "${ROOT}/tasks/scripts/build-env.sh"
ensure_build_nofile_limit

PORT="${OPENSHELL_SERVER_PORT:-18081}"
GATEWAY_NAME="${OPENSHELL_VM_GATEWAY_NAME:-vm-dev}"
STATE_DIR="${OPENSHELL_VM_GATEWAY_STATE_DIR:-${ROOT}/.cache/gateway-vm}"
Expand Down
4 changes: 4 additions & 0 deletions tasks/scripts/gateway.sh
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ set -euo pipefail
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
GATEWAY_BIN="${ROOT}/target/debug/openshell-gateway"

# shellcheck source=tasks/scripts/build-env.sh
source "${ROOT}/tasks/scripts/build-env.sh"
ensure_build_nofile_limit

usage() {
cat <<'EOF'
Usage: mise run gateway [-- --driver DRIVER]
Expand Down
22 changes: 4 additions & 18 deletions tasks/scripts/test-build-env.sh
Original file line number Diff line number Diff line change
Expand Up @@ -38,28 +38,14 @@ if [ "${os}" != "Darwin" ]; then
exit 0
fi

# Darwin below.
if ! command -v cargo-zigbuild >/dev/null 2>&1; then
# Without cargo-zigbuild the helper must be a no-op even on macOS.
(
ulimit -Sn 256 2>/dev/null || true
before="$(ulimit -n)"
ensure_build_nofile_limit >/dev/null
after="$(ulimit -n)"
[ "${before}" = "${after}" ] || fail "limit changed on macOS without cargo-zigbuild (${before} -> ${after})"
)
pass "no-op on macOS without cargo-zigbuild"
echo "All build-env tests passed."
exit 0
fi

# Darwin + cargo-zigbuild: the helper should raise a low soft limit.
# Darwin native Cargo builds need the same protection even when
# cargo-zigbuild is unavailable.
(
if ! ulimit -Sn 256 2>/dev/null; then
echo "SKIP: unable to lower soft limit to 256 for test"
exit 0
fi
ensure_build_nofile_limit >/dev/null
PATH="/usr/bin:/bin" ensure_build_nofile_limit >/dev/null
after="$(ulimit -n)"
hard="$(ulimit -Hn 2>/dev/null || echo unlimited)"
case "${hard}" in
Expand All @@ -76,7 +62,7 @@ fi
;;
esac
)
pass "raises low soft limit on macOS with cargo-zigbuild"
pass "raises low soft limit for native Cargo builds on macOS"

# Idempotent: when the current limit already meets the desired value, the helper
# leaves it unchanged (drive this via the env override so it holds regardless of
Expand Down
Loading