mirror of
https://github.com/NVIDIA/OpenShell.git
synced 2026-10-16 05:20:22 +08:00
304 lines
9.3 KiB
Bash
Executable File
304 lines
9.3 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
|
|
|
|
# Bootstrap an OpenShell development checkout inside a sandbox image.
|
|
|
|
set -euo pipefail
|
|
|
|
REPO_SLUG="${OPENSHELL_DEVSHELL_REPO_SLUG:-NVIDIA/OpenShell}"
|
|
|
|
export HOME=/sandbox
|
|
export USER=sandbox
|
|
export MISE_CACHE_DIR=/sandbox/.cache/mise
|
|
export CARGO_HOME=/sandbox/.cargo
|
|
|
|
path_prepend() {
|
|
case ":${PATH}:" in
|
|
*":$1:"*) ;;
|
|
*) PATH="$1:${PATH}" ;;
|
|
esac
|
|
}
|
|
|
|
ld_prepend() {
|
|
case ":${LD_LIBRARY_PATH:-}:" in
|
|
*":$1:"*) ;;
|
|
*) LD_LIBRARY_PATH="$1:${LD_LIBRARY_PATH:-}" ;;
|
|
esac
|
|
}
|
|
|
|
preload_prepend() {
|
|
case ":${LD_PRELOAD:-}:" in
|
|
*":$1:"*) ;;
|
|
*) LD_PRELOAD="$1${LD_PRELOAD:+:${LD_PRELOAD}}" ;;
|
|
esac
|
|
}
|
|
|
|
find_libclang_dir() {
|
|
local dir
|
|
for dir in \
|
|
/sandbox/.deps/usr/lib/llvm-*/lib \
|
|
/usr/lib/llvm-*/lib \
|
|
/sandbox/.deps/usr/lib/*-linux-gnu \
|
|
/usr/lib/*-linux-gnu \
|
|
/usr/local/lib \
|
|
/usr/lib64; do
|
|
[ -d "$dir" ] || continue
|
|
if [ -e "$dir/libclang.so" ] \
|
|
|| compgen -G "$dir/libclang-*.so" >/dev/null \
|
|
|| compgen -G "$dir/libclang.so.*" >/dev/null; then
|
|
printf '%s\n' "$dir"
|
|
return 0
|
|
fi
|
|
done
|
|
return 1
|
|
}
|
|
|
|
find_clang_resource_include() {
|
|
local dir
|
|
for dir in \
|
|
/sandbox/.deps/usr/lib/llvm-*/lib/clang/*/include \
|
|
/usr/lib/llvm-*/lib/clang/*/include; do
|
|
if [ -f "$dir/stddef.h" ]; then
|
|
printf '%s\n' "$dir"
|
|
return 0
|
|
fi
|
|
done
|
|
return 1
|
|
}
|
|
|
|
find_z3_header() {
|
|
local header
|
|
for header in /sandbox/.deps/usr/include/z3.h /usr/local/include/z3.h /usr/include/z3.h; do
|
|
if [ -f "$header" ]; then
|
|
printf '%s\n' "$header"
|
|
return 0
|
|
fi
|
|
done
|
|
return 1
|
|
}
|
|
|
|
find_z3_libdir() {
|
|
local dir
|
|
for dir in /sandbox/.deps/usr/lib/*-linux-gnu /usr/local/lib /usr/lib/*-linux-gnu /usr/lib64; do
|
|
[ -d "$dir" ] || continue
|
|
if [ -e "$dir/libz3.so" ] || [ -e "$dir/libz3.a" ]; then
|
|
printf '%s\n' "$dir"
|
|
return 0
|
|
fi
|
|
done
|
|
return 1
|
|
}
|
|
|
|
find_nss_wrapper() {
|
|
local lib
|
|
for lib in \
|
|
/sandbox/.deps/usr/lib/*-linux-gnu/libnss_wrapper.so \
|
|
/usr/lib/*-linux-gnu/libnss_wrapper.so \
|
|
/usr/lib64/libnss_wrapper.so; do
|
|
if [ -f "$lib" ]; then
|
|
printf '%s\n' "$lib"
|
|
return 0
|
|
fi
|
|
done
|
|
return 1
|
|
}
|
|
|
|
etc_hosts_has_localhost() {
|
|
grep -E '^(127\.0\.0\.1|::1)[[:space:]].*localhost' /etc/hosts >/dev/null 2>&1
|
|
}
|
|
|
|
native_deps_ready() {
|
|
find_libclang_dir >/dev/null \
|
|
&& find_clang_resource_include >/dev/null \
|
|
&& find_z3_header >/dev/null \
|
|
&& find_z3_libdir >/dev/null \
|
|
&& { etc_hosts_has_localhost || find_nss_wrapper >/dev/null; }
|
|
}
|
|
|
|
ensure_native_deps() {
|
|
native_deps_ready && return 0
|
|
command -v apt-get >/dev/null 2>&1 || return 0
|
|
command -v dpkg-deb >/dev/null 2>&1 || return 0
|
|
[ -f /etc/apt/sources.list.d/ubuntu.sources ] || return 0
|
|
|
|
local apt_root=/sandbox/.apt
|
|
mkdir -p \
|
|
"$apt_root/apt.conf.d" \
|
|
"$apt_root/sources" \
|
|
"$apt_root/lists/partial" \
|
|
"$apt_root/cache/archives/partial" \
|
|
/sandbox/.deps
|
|
cp /etc/apt/sources.list.d/ubuntu.sources "$apt_root/sources/ubuntu.sources"
|
|
|
|
local apt_opts=(
|
|
-o Dir::Etc::main=/dev/null
|
|
-o "Dir::Etc::parts=$apt_root/apt.conf.d"
|
|
-o Dir::Etc::sourcelist=/dev/null
|
|
-o "Dir::Etc::sourceparts=$apt_root/sources"
|
|
-o "Dir::State::Lists=$apt_root/lists"
|
|
-o Dir::State::status=/var/lib/dpkg/status
|
|
-o "Dir::Cache=$apt_root/cache"
|
|
-o "Dir::Cache::archives=$apt_root/cache/archives"
|
|
-o Debug::NoLocking=1
|
|
-o Acquire::Languages=none
|
|
)
|
|
|
|
if ! compgen -G "$apt_root/lists/*_Packages*" >/dev/null; then
|
|
apt-get "${apt_opts[@]}" update
|
|
fi
|
|
if ! compgen -G "$apt_root/cache/archives/libclang-*.deb" >/dev/null \
|
|
|| ! compgen -G "$apt_root/cache/archives/libz3-dev_*.deb" >/dev/null; then
|
|
apt-get "${apt_opts[@]}" --download-only --reinstall -y install \
|
|
libclang-dev \
|
|
libz3-dev \
|
|
libnss-wrapper \
|
|
pkg-config
|
|
fi
|
|
|
|
local deb
|
|
for deb in "$apt_root"/cache/archives/*.deb; do
|
|
[ -f "$deb" ] || continue
|
|
dpkg-deb -x "$deb" /sandbox/.deps
|
|
done
|
|
}
|
|
|
|
configure_native_deps_env() {
|
|
local libclang_dir clang_include z3_header z3_libdir nss_wrapper
|
|
|
|
if [ -d /sandbox/.deps/usr/bin ]; then
|
|
path_prepend /sandbox/.deps/usr/bin
|
|
fi
|
|
|
|
if libclang_dir="$(find_libclang_dir)"; then
|
|
export LIBCLANG_PATH="$libclang_dir"
|
|
ld_prepend "$libclang_dir"
|
|
fi
|
|
if clang_include="$(find_clang_resource_include)"; then
|
|
export BINDGEN_EXTRA_CLANG_ARGS="-I${clang_include}${BINDGEN_EXTRA_CLANG_ARGS:+ ${BINDGEN_EXTRA_CLANG_ARGS}}"
|
|
fi
|
|
if z3_header="$(find_z3_header)"; then
|
|
export Z3_SYS_Z3_HEADER="$z3_header"
|
|
fi
|
|
if z3_libdir="$(find_z3_libdir)"; then
|
|
export Z3_LIBRARY_PATH_OVERRIDE="$z3_libdir"
|
|
ld_prepend "$z3_libdir"
|
|
fi
|
|
if [ -d /sandbox/.deps/usr/lib/aarch64-linux-gnu/pkgconfig ]; then
|
|
export PKG_CONFIG_PATH="/sandbox/.deps/usr/lib/aarch64-linux-gnu/pkgconfig${PKG_CONFIG_PATH:+:${PKG_CONFIG_PATH}}"
|
|
export PKG_CONFIG_SYSROOT_DIR=/sandbox/.deps
|
|
fi
|
|
|
|
if ! etc_hosts_has_localhost && nss_wrapper="$(find_nss_wrapper)"; then
|
|
{
|
|
printf '127.0.0.1 localhost localhost.localdomain\n'
|
|
printf '::1 localhost ip6-localhost ip6-loopback\n'
|
|
printf '8.8.8.8 dns.google\n'
|
|
grep -v -E '^(127\.0\.0\.1|::1)[[:space:]]' /etc/hosts || true
|
|
} > /sandbox/.nss-hosts
|
|
cat /etc/passwd > /sandbox/.nss-passwd
|
|
if ! grep -q -E "^$(id -un):" /sandbox/.nss-passwd; then
|
|
printf '%s:x:%s:%s::%s:%s\n' \
|
|
"$(id -un)" "$(id -u)" "$(id -g)" "$HOME" "${SHELL:-/bin/bash}" \
|
|
>> /sandbox/.nss-passwd
|
|
fi
|
|
cat /etc/group > /sandbox/.nss-group
|
|
if ! grep -q -E "^$(id -gn):" /sandbox/.nss-group; then
|
|
printf '%s:x:%s:%s\n' "$(id -gn)" "$(id -g)" "$(id -un)" \
|
|
>> /sandbox/.nss-group
|
|
fi
|
|
export NSS_WRAPPER_HOSTS=/sandbox/.nss-hosts
|
|
export NSS_WRAPPER_PASSWD=/sandbox/.nss-passwd
|
|
export NSS_WRAPPER_GROUP=/sandbox/.nss-group
|
|
export RUST_TEST_THREADS="${RUST_TEST_THREADS:-1}"
|
|
preload_prepend "$nss_wrapper"
|
|
fi
|
|
|
|
export PATH LD_LIBRARY_PATH LD_PRELOAD
|
|
}
|
|
|
|
write_shell_profile() {
|
|
{
|
|
printf 'export HOME=%q\n' "$HOME"
|
|
printf 'export USER=%q\n' "$USER"
|
|
printf 'export MISE_CACHE_DIR=%q\n' "$MISE_CACHE_DIR"
|
|
printf 'export CARGO_HOME=%q\n' "$CARGO_HOME"
|
|
printf 'export MISE_DATA_DIR=%q\n' "$MISE_DATA_DIR"
|
|
printf 'export RUSTUP_HOME=%q\n' "$RUSTUP_HOME"
|
|
printf 'export PATH=%q\n' "$PATH"
|
|
[ -z "${LD_LIBRARY_PATH:-}" ] || printf 'export LD_LIBRARY_PATH=%q\n' "$LD_LIBRARY_PATH"
|
|
[ -z "${LD_PRELOAD:-}" ] || printf 'export LD_PRELOAD=%q\n' "$LD_PRELOAD"
|
|
[ -z "${LIBCLANG_PATH:-}" ] || printf 'export LIBCLANG_PATH=%q\n' "$LIBCLANG_PATH"
|
|
[ -z "${BINDGEN_EXTRA_CLANG_ARGS:-}" ] || printf 'export BINDGEN_EXTRA_CLANG_ARGS=%q\n' "$BINDGEN_EXTRA_CLANG_ARGS"
|
|
[ -z "${PKG_CONFIG_PATH:-}" ] || printf 'export PKG_CONFIG_PATH=%q\n' "$PKG_CONFIG_PATH"
|
|
[ -z "${PKG_CONFIG_SYSROOT_DIR:-}" ] || printf 'export PKG_CONFIG_SYSROOT_DIR=%q\n' "$PKG_CONFIG_SYSROOT_DIR"
|
|
[ -z "${Z3_SYS_Z3_HEADER:-}" ] || printf 'export Z3_SYS_Z3_HEADER=%q\n' "$Z3_SYS_Z3_HEADER"
|
|
[ -z "${Z3_LIBRARY_PATH_OVERRIDE:-}" ] || printf 'export Z3_LIBRARY_PATH_OVERRIDE=%q\n' "$Z3_LIBRARY_PATH_OVERRIDE"
|
|
[ -z "${NSS_WRAPPER_HOSTS:-}" ] || printf 'export NSS_WRAPPER_HOSTS=%q\n' "$NSS_WRAPPER_HOSTS"
|
|
[ -z "${NSS_WRAPPER_PASSWD:-}" ] || printf 'export NSS_WRAPPER_PASSWD=%q\n' "$NSS_WRAPPER_PASSWD"
|
|
[ -z "${NSS_WRAPPER_GROUP:-}" ] || printf 'export NSS_WRAPPER_GROUP=%q\n' "$NSS_WRAPPER_GROUP"
|
|
[ -z "${RUST_TEST_THREADS:-}" ] || printf 'export RUST_TEST_THREADS=%q\n' "$RUST_TEST_THREADS"
|
|
} > /sandbox/.profile
|
|
cp /sandbox/.profile /sandbox/.bash_profile
|
|
printf 'source /sandbox/.profile\n' > /sandbox/.bashrc
|
|
}
|
|
|
|
configure_mise() {
|
|
if command -v mise >/dev/null 2>&1 && [ -d /usr/local/share/openshell/mise ]; then
|
|
export MISE_DATA_DIR=/usr/local/share/openshell/mise
|
|
export RUSTUP_HOME=/usr/local/share/openshell/mise/rustup
|
|
path_prepend /usr/local/share/openshell/mise/cargo/bin
|
|
path_prepend /usr/local/bin
|
|
path_prepend /usr/local/share/openshell/mise/shims
|
|
return
|
|
fi
|
|
|
|
if command -v mise >/dev/null 2>&1 && [ -d /opt/mise ]; then
|
|
export MISE_DATA_DIR=/opt/mise
|
|
export RUSTUP_HOME=/opt/mise/rustup
|
|
path_prepend /opt/mise/cargo/bin
|
|
path_prepend /usr/local/bin
|
|
path_prepend /opt/mise/shims
|
|
return
|
|
fi
|
|
|
|
export MISE_DATA_DIR=/sandbox/.local/share/mise
|
|
export RUSTUP_HOME=/sandbox/.rustup
|
|
path_prepend /sandbox/.cargo/bin
|
|
path_prepend /sandbox/.local/bin
|
|
path_prepend /sandbox/.local/share/mise/shims
|
|
if ! command -v mise >/dev/null 2>&1; then
|
|
mkdir -p /sandbox/.local/bin
|
|
curl -fsSL https://mise.run | sh
|
|
fi
|
|
}
|
|
|
|
clone_repo() {
|
|
if [ -d /sandbox/openshell/.git ]; then
|
|
return
|
|
fi
|
|
|
|
if command -v gh >/dev/null 2>&1; then
|
|
gh repo clone "$REPO_SLUG" /sandbox/openshell \
|
|
|| git clone "https://github.com/${REPO_SLUG}.git" /sandbox/openshell
|
|
else
|
|
git clone "https://github.com/${REPO_SLUG}.git" /sandbox/openshell
|
|
fi
|
|
}
|
|
|
|
mkdir -p /sandbox /sandbox/.cargo /sandbox/.cache/mise
|
|
configure_mise
|
|
ensure_native_deps
|
|
configure_native_deps_env
|
|
write_shell_profile
|
|
clone_repo
|
|
|
|
cd /sandbox/openshell
|
|
mise trust >/dev/null
|
|
MISE_YES=1 mise install
|
|
if [ -f pyproject.toml ] && ! .venv/bin/python -c 'import grpc_tools.protoc' >/dev/null 2>&1; then
|
|
uv sync --locked
|
|
fi
|
|
exec "$@"
|