chore: import upstream snapshot with attribution
This commit is contained in:
Executable
+243
@@ -0,0 +1,243 @@
|
||||
#!/bin/bash
|
||||
# Copyright © 2026 Apple Inc. and the Containerization project authors.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# https://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
# Builds the x86_64 deployment tarball.
|
||||
#
|
||||
# Runs INSIDE the aarch64 Linux dev container (invoked by
|
||||
# `make dist-x86_64` via the linux_run macro). Cross-compiles all four
|
||||
# host-side binaries — cctl, vminitd, cloud-hypervisor, virtiofsd —
|
||||
# to x86_64-linux-musl, packs an initfs.ext4 with the x86_64 guest
|
||||
# binaries inside, and emits bin/containerization-x86_64-<sha>.tar.gz.
|
||||
#
|
||||
# See docs/x86_64-build.md for full documentation: prerequisites,
|
||||
# pipeline stages, toolchain rationale, and troubleshooting.
|
||||
#
|
||||
# Force-rebuild env vars (default = skip stages whose outputs are
|
||||
# up-to-date):
|
||||
# REBUILD_VMINITD=1 vminitd + vmexec
|
||||
# REBUILD_INITFS=1 initfs.ext4 (and the native aarch64 cctl packer)
|
||||
# REBUILD_CH=1 cloud-hypervisor
|
||||
# REBUILD_VIRTIOFSD=1 virtiofsd
|
||||
# cctl x86 cross always rebuilds (Swift incremental handles no-ops).
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
cd /workspace
|
||||
|
||||
GIT_SHA=$(git rev-parse --short HEAD 2>/dev/null || echo unknown)
|
||||
DIST_NAME="containerization-x86_64-${GIT_SHA}"
|
||||
DIST_DIR="bin/dist-x86_64"
|
||||
STAGE="${DIST_DIR}/${DIST_NAME}"
|
||||
TGZ="bin/${DIST_NAME}.tar.gz"
|
||||
|
||||
CROSS_PREFIX=/opt/cross-x86_64-musl
|
||||
GNU_PREFIX=/opt/cross-x86_64-gnu
|
||||
PATCH=/workspace/scripts/patches/virtiofsd-skip-cap-drop-with-sandbox-none.patch
|
||||
|
||||
# Cargo cross env for the musl stages (cctl, vminitd, cloud-hypervisor).
|
||||
# CC/CXX/AR are used by cc-rs (Rust build scripts that compile C, e.g.
|
||||
# zstd-sys, libseccomp-sys, capng) — points them at the Zig-backed
|
||||
# wrappers. Linker is intentionally NOT set here: cargo-zigbuild
|
||||
# installs its own linker wrapper that strips Rust's self-contained
|
||||
# musl crt files (which would otherwise collide with Zig's musl crt).
|
||||
# Setting CARGO_TARGET_*_LINKER ourselves would override that and
|
||||
# cause duplicate-symbol link errors.
|
||||
# pkg-config (used by libseccomp-sys and libcap-ng's capng-sys) points
|
||||
# at the static-musl prefix, not the aarch64 host.
|
||||
# PKG_CONFIG_ALL_STATIC=1 makes pkg-config-rs emit
|
||||
# `rustc-link-lib=static=...` for resolved libs — required because
|
||||
# the C libs at $CROSS_PREFIX are static-only (.a, no .so), so the
|
||||
# default dynamic link would fail to find the .so.
|
||||
#
|
||||
# virtiofsd has its own glibc-dynamic env block below; it overrides
|
||||
# PKG_CONFIG_LIBDIR / SYSROOT_DIR in a subshell so the musl values
|
||||
# stay correct for cloud-hypervisor.
|
||||
. /root/.cargo/env
|
||||
export CC_x86_64_unknown_linux_musl=x86_64-linux-musl-gcc
|
||||
export CXX_x86_64_unknown_linux_musl=x86_64-linux-musl-g++
|
||||
export AR_x86_64_unknown_linux_musl=x86_64-linux-musl-ar
|
||||
export PKG_CONFIG_LIBDIR="${CROSS_PREFIX}/lib/pkgconfig"
|
||||
export PKG_CONFIG_SYSROOT_DIR="${CROSS_PREFIX}"
|
||||
export PKG_CONFIG_ALLOW_CROSS=1
|
||||
# Add the static-musl cross prefix to rustc's native library search
|
||||
# path so the linker finds the libseccomp.so / libcap-ng.so linker
|
||||
# scripts that build-musl-x86_64-deps.sh installs alongside the .a
|
||||
# files. The scripts redirect resolution to the static archives.
|
||||
export CARGO_TARGET_X86_64_UNKNOWN_LINUX_MUSL_RUSTFLAGS="-L native=${CROSS_PREFIX}/lib"
|
||||
|
||||
# Pre-flight checks
|
||||
[ -f .local/cloud-hypervisor/Cargo.toml ] || {
|
||||
echo "ERROR: missing .local/cloud-hypervisor source checkout." >&2
|
||||
echo " git clone -b v52.0 https://github.com/cloud-hypervisor/cloud-hypervisor .local/cloud-hypervisor" >&2
|
||||
exit 1
|
||||
}
|
||||
[ -f .local/virtiofsd/Cargo.toml ] || {
|
||||
echo "ERROR: missing .local/virtiofsd source checkout." >&2
|
||||
echo " git clone https://gitlab.com/virtio-fs/virtiofsd .local/virtiofsd" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Kernel candidates (prefer the compressed bzImage produced by
|
||||
# `make -C kernel TARGET_ARCH=x86_64`, fall back to an uncompressed
|
||||
# vmlinux). The kernel is required — a tarball without one isn't
|
||||
# usable, so fail hard rather than silently producing one.
|
||||
KERNEL_SRC=
|
||||
for candidate in kernel/vmlinuz-x86_64 kernel/vmlinux-x86_64; do
|
||||
if [ -f "$candidate" ]; then
|
||||
if file "$candidate" | grep -qE 'x86 boot|x86-64'; then
|
||||
KERNEL_SRC=$candidate
|
||||
break
|
||||
else
|
||||
echo "ERROR: $candidate exists but is not x86_64." >&2
|
||||
file "$candidate" >&2
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
done
|
||||
if [ -z "${KERNEL_SRC}" ]; then
|
||||
echo "ERROR: no x86_64 kernel found at kernel/vmlinuz-x86_64 or kernel/vmlinux-x86_64." >&2
|
||||
echo " build one with 'make -C kernel TARGET_ARCH=x86_64'." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
mkdir -p "${DIST_DIR}"
|
||||
|
||||
# Decide which steps need to run before doing any work, so log messages
|
||||
# match what's actually happening.
|
||||
|
||||
NEED_VMINITD=1
|
||||
if [ "${REBUILD_VMINITD:-0}" != "1" ] \
|
||||
&& [ -x "${DIST_DIR}/vminitd" ] && [ -x "${DIST_DIR}/vmexec" ] \
|
||||
&& [ -z "$(find vminitd/Sources vminitd/Package.swift Sources/Containerization/SandboxContext \
|
||||
-newer "${DIST_DIR}/vminitd" -print -quit 2>/dev/null)" ] \
|
||||
&& [ -z "$(find vminitd/Sources vminitd/Package.swift Sources/Containerization/SandboxContext \
|
||||
-newer "${DIST_DIR}/vmexec" -print -quit 2>/dev/null)" ]; then
|
||||
NEED_VMINITD=0
|
||||
fi
|
||||
|
||||
NEED_INITFS=1
|
||||
if [ "${REBUILD_INITFS:-0}" != "1" ] \
|
||||
&& [ "${NEED_VMINITD}" = "0" ] \
|
||||
&& [ -f "${DIST_DIR}/initfs.ext4" ] \
|
||||
&& [ "${DIST_DIR}/initfs.ext4" -nt "${DIST_DIR}/vminitd" ] \
|
||||
&& [ "${DIST_DIR}/initfs.ext4" -nt "${DIST_DIR}/vmexec" ]; then
|
||||
NEED_INITFS=0
|
||||
fi
|
||||
|
||||
NEED_CH=1
|
||||
if [ "${REBUILD_CH:-0}" != "1" ] && [ -x "${DIST_DIR}/cloud-hypervisor" ]; then
|
||||
NEED_CH=0
|
||||
fi
|
||||
|
||||
NEED_VIRTIOFSD=1
|
||||
if [ "${REBUILD_VIRTIOFSD:-0}" != "1" ] && [ -x "${DIST_DIR}/virtiofsd" ]; then
|
||||
NEED_VIRTIOFSD=0
|
||||
fi
|
||||
|
||||
echo "==> Cross-compiling cctl to x86_64-linux-musl"
|
||||
swift build -c release \
|
||||
--swift-sdk x86_64-swift-linux-musl \
|
||||
--product cctl \
|
||||
-Xswiftc -warnings-as-errors \
|
||||
-Xlinker -L"${CROSS_PREFIX}/lib" \
|
||||
--disable-automatic-resolution
|
||||
CCTL_X86_64_BIN="$(swift build -c release --swift-sdk x86_64-swift-linux-musl --show-bin-path)/cctl"
|
||||
install -m 755 "${CCTL_X86_64_BIN}" "${DIST_DIR}/cctl"
|
||||
|
||||
if [ "${NEED_VMINITD}" = "1" ]; then
|
||||
echo "==> Cross-compiling vminitd + vmexec to x86_64-linux-musl"
|
||||
make -C vminitd \
|
||||
LIBC=musl \
|
||||
MUSL_ARCH=x86_64 \
|
||||
BUILD_CONFIGURATION=release \
|
||||
INSTALL_DIR="$(pwd)/${DIST_DIR}"
|
||||
else
|
||||
echo "==> Reusing staged vminitd + vmexec (sources unchanged; set REBUILD_VMINITD=1 to force)"
|
||||
fi
|
||||
|
||||
if [ "${NEED_CH}" = "1" ]; then
|
||||
echo "==> Cross-compiling cloud-hypervisor to x86_64-unknown-linux-musl"
|
||||
(
|
||||
cd .local/cloud-hypervisor
|
||||
cargo zigbuild --release --target x86_64-unknown-linux-musl --bin cloud-hypervisor
|
||||
)
|
||||
install -m 755 \
|
||||
".local/cloud-hypervisor/target/x86_64-unknown-linux-musl/release/cloud-hypervisor" \
|
||||
"${DIST_DIR}/cloud-hypervisor"
|
||||
else
|
||||
echo "==> Reusing staged cloud-hypervisor (set REBUILD_CH=1 to force)"
|
||||
fi
|
||||
|
||||
if [ "${NEED_VIRTIOFSD}" = "1" ]; then
|
||||
echo "==> Cross-compiling virtiofsd to x86_64-unknown-linux-gnu.2.35 (glibc-dynamic, with cap-drop patch)"
|
||||
# virtiofsd ships glibc-dynamic: the deployment host provides
|
||||
# libseccomp.so.2 and libcap-ng.so.0 at runtime. Subshell scopes
|
||||
# the gnu env so it doesn't bleed into other stages.
|
||||
(
|
||||
export CC_x86_64_unknown_linux_gnu=x86_64-linux-gnu-gcc
|
||||
export CXX_x86_64_unknown_linux_gnu=x86_64-linux-gnu-g++
|
||||
export AR_x86_64_unknown_linux_gnu=x86_64-linux-gnu-ar
|
||||
export PKG_CONFIG_LIBDIR="${GNU_PREFIX}/lib/pkgconfig"
|
||||
export PKG_CONFIG_SYSROOT_DIR="${GNU_PREFIX}"
|
||||
export CARGO_TARGET_X86_64_UNKNOWN_LINUX_GNU_RUSTFLAGS="-L native=${GNU_PREFIX}/lib"
|
||||
cd .local/virtiofsd
|
||||
if git apply --check "${PATCH}" 2>/dev/null; then
|
||||
git apply "${PATCH}"
|
||||
echo "applied virtiofsd cap-drop patch"
|
||||
elif git apply --reverse --check "${PATCH}" 2>/dev/null; then
|
||||
echo "virtiofsd cap-drop patch already applied"
|
||||
else
|
||||
echo "ERROR: virtiofsd cap-drop patch does not apply cleanly" >&2
|
||||
exit 1
|
||||
fi
|
||||
cargo zigbuild --release --target x86_64-unknown-linux-gnu.2.35
|
||||
)
|
||||
install -m 755 \
|
||||
".local/virtiofsd/target/x86_64-unknown-linux-gnu/release/virtiofsd" \
|
||||
"${DIST_DIR}/virtiofsd"
|
||||
else
|
||||
echo "==> Reusing staged virtiofsd (set REBUILD_VIRTIOFSD=1 to force)"
|
||||
fi
|
||||
|
||||
if [ "${NEED_INITFS}" = "1" ]; then
|
||||
echo "==> Building aarch64 cctl natively (used to pack initfs.ext4)"
|
||||
swift build -c release --product cctl -Xswiftc -warnings-as-errors --disable-automatic-resolution
|
||||
NATIVE_CCTL="$(swift build -c release --show-bin-path)/cctl"
|
||||
|
||||
echo "==> Building initfs.ext4 with x86_64 guest binaries"
|
||||
rm -f "${DIST_DIR}/init.rootfs.tar.gz" "${DIST_DIR}/initfs.ext4"
|
||||
"${NATIVE_CCTL}" rootfs create \
|
||||
--vminitd "${DIST_DIR}/vminitd" \
|
||||
--vmexec "${DIST_DIR}/vmexec" \
|
||||
--ext4 "${DIST_DIR}/initfs.ext4" \
|
||||
--label org.opencontainers.image.source=https://github.com/apple/containerization \
|
||||
--image vminit-x86_64:latest \
|
||||
"${DIST_DIR}/init.rootfs.tar.gz"
|
||||
else
|
||||
echo "==> Reusing staged initfs.ext4 (vminitd/vmexec unchanged; set REBUILD_INITFS=1 to force)"
|
||||
fi
|
||||
|
||||
echo "==> Staging tree at ${STAGE} and packaging"
|
||||
rm -rf "${STAGE}"
|
||||
mkdir -p "${STAGE}/bin"
|
||||
install -m 755 "${DIST_DIR}/cctl" "${STAGE}/bin/cctl"
|
||||
install -m 755 "${DIST_DIR}/cloud-hypervisor" "${STAGE}/bin/cloud-hypervisor"
|
||||
install -m 755 "${DIST_DIR}/virtiofsd" "${STAGE}/bin/virtiofsd"
|
||||
mkdir -p "${STAGE}/kernel"
|
||||
cp "${KERNEL_SRC}" "${STAGE}/kernel/$(basename "${KERNEL_SRC}")"
|
||||
cp "${DIST_DIR}/initfs.ext4" "${STAGE}/initfs.ext4"
|
||||
rm -f "${TGZ}"
|
||||
tar -czf "${TGZ}" -C "${DIST_DIR}" "${DIST_NAME}"
|
||||
echo "wrote ${TGZ}"
|
||||
Executable
+138
@@ -0,0 +1,138 @@
|
||||
#!/bin/bash
|
||||
# Copyright © 2026 Apple Inc. and the Containerization project authors.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# https://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
# Builds x86_64-linux-gnu shared-library versions of libseccomp and
|
||||
# libcap-ng (the two C libs virtiofsd links against) and installs them
|
||||
# at /opt/cross-x86_64-gnu. Sibling of build-musl-x86_64-deps.sh; the
|
||||
# Dockerfile invokes both at image build time.
|
||||
#
|
||||
# Why a separate prefix: virtiofsd ships glibc-dynamic in the x86_64
|
||||
# tarball (see docs/x86_64-build.md) so deployment hosts can use their
|
||||
# system libseccomp.so.2 + libcap-ng.so.0; everything else in the tarball
|
||||
# stays musl-static. Mixing static-musl .a archives and dynamic-gnu .so
|
||||
# files at one prefix confuses pkg-config and the linker, so they live
|
||||
# apart.
|
||||
#
|
||||
# The glibc baseline is pinned at 2.35 (Ubuntu 22.04 / Debian 12 / RHEL 9
|
||||
# era) via the Zig wrapper scripts at /usr/local/bin/x86_64-linux-gnu-*,
|
||||
# which dispatch to `zig cc -target x86_64-linux-gnu.2.35`. Bump the
|
||||
# wrapper triple if the baseline moves.
|
||||
#
|
||||
# Only two libraries here, both shared: virtiofsd's other build-script
|
||||
# deps (zstd, etc.) come from cargo crates that vendor C sources, and
|
||||
# cctl's libarchive lives on the musl side.
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
HOST=x86_64-linux-gnu
|
||||
PREFIX=/opt/cross-x86_64-gnu
|
||||
|
||||
mkdir -p "${PREFIX}/lib" "${PREFIX}/include"
|
||||
|
||||
export CC="${HOST}-gcc"
|
||||
export CXX="${HOST}-g++"
|
||||
export AR="${HOST}-ar"
|
||||
export RANLIB="${HOST}-ranlib"
|
||||
export STRIP="${HOST}-strip"
|
||||
export PKG_CONFIG_PATH="${PREFIX}/lib/pkgconfig"
|
||||
|
||||
WORK=$(mktemp -d)
|
||||
trap 'rm -rf "${WORK}"' EXIT
|
||||
cd "${WORK}"
|
||||
|
||||
JOBS="$(nproc)"
|
||||
|
||||
# fetch_extract URL ARCHIVE
|
||||
#
|
||||
# Downloads URL to ARCHIVE then extracts. Relies on HTTPS for transport
|
||||
# integrity; no SHA pinning. The other build-time deps (apt packages,
|
||||
# Zig, Rust toolchain) trust the same.
|
||||
fetch_extract() {
|
||||
local url=$1 archive=$2
|
||||
curl -fsSL -o "${archive}" "${url}"
|
||||
tar -xf "${archive}"
|
||||
}
|
||||
|
||||
# Sanity check: cross compiler produces clean output for a trivial
|
||||
# program. autotools / libtool turn unexpected compiler chatter into
|
||||
# baffling configure errors; surfacing it here gives a real message.
|
||||
echo "==> cross compiler sanity check"
|
||||
"${CC}" --version
|
||||
cat > "${WORK}/sanity.c" <<'EOF'
|
||||
void foo(void) {}
|
||||
EOF
|
||||
out=$("${CC}" -c "${WORK}/sanity.c" -o "${WORK}/sanity.o" 2>&1) || {
|
||||
echo "ERROR: cross compiler failed on trivial test.c:" >&2
|
||||
echo "${out}" >&2
|
||||
exit 1
|
||||
}
|
||||
if [ -n "${out}" ]; then
|
||||
echo "WARNING: cross compiler emitted output on a clean compile:" >&2
|
||||
echo "${out}" >&2
|
||||
fi
|
||||
|
||||
# libcap-ng — github auto-archive (release artifacts for older tags
|
||||
# aren't always uploaded).
|
||||
LIBCAP_NG_VERSION=0.8.5
|
||||
fetch_extract "https://github.com/stevegrubb/libcap-ng/archive/refs/tags/v${LIBCAP_NG_VERSION}.tar.gz" libcap-ng.tar.gz
|
||||
(
|
||||
cd "libcap-ng-${LIBCAP_NG_VERSION}"
|
||||
# GNU automake's strict mode requires these standard files to exist;
|
||||
# the auto-archive tarball doesn't ship NEWS. Cheaper than
|
||||
# configure.ac surgery.
|
||||
touch NEWS README AUTHORS ChangeLog
|
||||
autoreconf -i
|
||||
./configure --host="${HOST}" --prefix="${PREFIX}" \
|
||||
--disable-static --enable-shared \
|
||||
--without-python --without-python3
|
||||
make -j"${JOBS}"
|
||||
make install
|
||||
)
|
||||
|
||||
# libseccomp — needs gperf at build time (installed via the Dockerfile
|
||||
# alongside the musl deps). Built shared here.
|
||||
LIBSECCOMP_VERSION=2.5.5
|
||||
fetch_extract "https://github.com/seccomp/libseccomp/releases/download/v${LIBSECCOMP_VERSION}/libseccomp-${LIBSECCOMP_VERSION}.tar.gz" libseccomp.tar.gz
|
||||
(
|
||||
cd "libseccomp-${LIBSECCOMP_VERSION}"
|
||||
./configure --host="${HOST}" --prefix="${PREFIX}" \
|
||||
--disable-static --enable-shared \
|
||||
--disable-python
|
||||
make -j"${JOBS}"
|
||||
make install
|
||||
)
|
||||
|
||||
# Drop libtool .la files — they encode build-host paths and confuse
|
||||
# downstream consumers; the .so + pkg-config .pc files are sufficient.
|
||||
rm -f "${PREFIX}/lib"/*.la
|
||||
|
||||
# Force the unversioned dev symlinks (libseccomp.so, libcap-ng.so).
|
||||
# libtool conservatively omits these when cross-compiling, but rustc's
|
||||
# link step looks for them by unversioned name; without them the
|
||||
# link fails with "unable to find dynamic system library 'seccomp'".
|
||||
# Idempotent — `ln -sf` overwrites any existing symlink, and the loop
|
||||
# picks up whatever versioned files libtool actually installed.
|
||||
for stem in libseccomp libcap-ng; do
|
||||
versioned=$(ls "${PREFIX}/lib/${stem}.so."* 2>/dev/null | sort -V | head -n1)
|
||||
if [ -n "${versioned}" ]; then
|
||||
ln -sf "$(basename "${versioned}")" "${PREFIX}/lib/${stem}.so"
|
||||
else
|
||||
echo "ERROR: no ${stem}.so.* found in ${PREFIX}/lib after install" >&2
|
||||
ls -la "${PREFIX}/lib" >&2
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
|
||||
echo "glibc-dynamic x86_64 C deps installed under ${PREFIX}"
|
||||
Executable
+188
@@ -0,0 +1,188 @@
|
||||
#!/bin/bash
|
||||
# Copyright © 2026 Apple Inc. and the Containerization project authors.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# https://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
# Builds static-musl x86_64 versions of the C libraries that cctl and
|
||||
# virtiofsd link against, and installs them at /opt/cross-x86_64-musl
|
||||
# (a standalone prefix — the Zig-based cross compiler has no
|
||||
# traditional sysroot, so the build-dist-x86_64.sh script and the
|
||||
# cargo cross flow add explicit -L / -I flags pointing here).
|
||||
#
|
||||
# Invoked once at dev-image build time; the resulting layer is cached
|
||||
# until this script changes. Adding/removing a library here is the only
|
||||
# reason to invalidate it.
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
HOST=x86_64-linux-musl
|
||||
PREFIX=/opt/cross-x86_64-musl
|
||||
|
||||
mkdir -p "${PREFIX}/lib" "${PREFIX}/include"
|
||||
|
||||
export CC="${HOST}-gcc"
|
||||
export CXX="${HOST}-g++"
|
||||
export AR="${HOST}-ar"
|
||||
export RANLIB="${HOST}-ranlib"
|
||||
export STRIP="${HOST}-strip"
|
||||
export PKG_CONFIG_PATH="${PREFIX}/lib/pkgconfig"
|
||||
|
||||
WORK=$(mktemp -d)
|
||||
trap 'rm -rf "${WORK}"' EXIT
|
||||
cd "${WORK}"
|
||||
|
||||
JOBS="$(nproc)"
|
||||
|
||||
# fetch_extract URL ARCHIVE
|
||||
#
|
||||
# Downloads URL to ARCHIVE then extracts. Relies on HTTPS for transport
|
||||
# integrity; no SHA pinning. The other build-time deps (apt packages,
|
||||
# Zig, Rust toolchain) trust the same.
|
||||
fetch_extract() {
|
||||
local url=$1 archive=$2
|
||||
curl -fsSL -o "${archive}" "${url}"
|
||||
tar -xf "${archive}"
|
||||
}
|
||||
|
||||
# Sanity check: cross compiler is on PATH and produces clean output
|
||||
# for a trivial program. If it doesn't, zlib's configure script (which
|
||||
# treats any stderr/stdout from a test compile as evidence of -Werror)
|
||||
# will fail with a misleading "Compiler error reporting is too harsh"
|
||||
# error. Surfacing this here gives us a real error message instead.
|
||||
echo "==> cross compiler sanity check"
|
||||
"${CC}" --version
|
||||
cat > "${WORK}/sanity.c" <<'EOF'
|
||||
void foo(void) {}
|
||||
EOF
|
||||
out=$("${CC}" -c "${WORK}/sanity.c" -o "${WORK}/sanity.o" 2>&1) || {
|
||||
echo "ERROR: cross compiler failed on trivial test.c:" >&2
|
||||
echo "${out}" >&2
|
||||
exit 1
|
||||
}
|
||||
if [ -n "${out}" ]; then
|
||||
echo "WARNING: cross compiler emitted output on a clean compile:" >&2
|
||||
echo "${out}" >&2
|
||||
echo "(this will trip up zlib's configure script — see fix below)" >&2
|
||||
fi
|
||||
|
||||
# zlib — provides libz.a. Its configure does not take --host, so the
|
||||
# CC env var is what selects the cross compiler.
|
||||
ZLIB_VERSION=1.3.1
|
||||
fetch_extract "https://zlib.net/fossils/zlib-${ZLIB_VERSION}.tar.gz" zlib.tar.gz
|
||||
(
|
||||
cd "zlib-${ZLIB_VERSION}"
|
||||
if ! ./configure --static --prefix="${PREFIX}"; then
|
||||
echo "==================== zlib configure.log ====================" >&2
|
||||
[ -f configure.log ] && cat configure.log >&2
|
||||
echo "============================================================" >&2
|
||||
exit 1
|
||||
fi
|
||||
make -j"${JOBS}"
|
||||
make install
|
||||
)
|
||||
|
||||
# xz — provides liblzma.a.
|
||||
XZ_VERSION=5.6.4
|
||||
fetch_extract "https://github.com/tukaani-project/xz/releases/download/v${XZ_VERSION}/xz-${XZ_VERSION}.tar.gz" xz.tar.gz
|
||||
(
|
||||
cd "xz-${XZ_VERSION}"
|
||||
./configure --host="${HOST}" --prefix="${PREFIX}" \
|
||||
--enable-static --disable-shared \
|
||||
--disable-doc --disable-scripts \
|
||||
--disable-xz --disable-xzdec --disable-lzmadec --disable-lzmainfo \
|
||||
--disable-lzma-links
|
||||
make -j"${JOBS}"
|
||||
make install
|
||||
)
|
||||
|
||||
# bzip2 — no autotools, drives a plain Makefile. Build only the static
|
||||
# library; the bzip2 CLI tools are not needed.
|
||||
BZIP2_VERSION=1.0.8
|
||||
fetch_extract "https://sourceware.org/pub/bzip2/bzip2-${BZIP2_VERSION}.tar.gz" bzip2.tar.gz
|
||||
(
|
||||
cd "bzip2-${BZIP2_VERSION}"
|
||||
make CC="${CC}" AR="${AR}" RANLIB="${RANLIB}" libbz2.a -j"${JOBS}"
|
||||
install -m 644 libbz2.a "${PREFIX}/lib/"
|
||||
install -m 644 bzlib.h "${PREFIX}/include/"
|
||||
)
|
||||
|
||||
# libarchive — needs zlib + lzma + bz2 (built above). Disable optional
|
||||
# deps that pull in extra toolchain weight (xml2, iconv, zstd, lz4,
|
||||
# openssl, libb2). cctl uses libarchive for tar/ext layouts; the
|
||||
# disabled formats are not used at runtime.
|
||||
LIBARCHIVE_VERSION=3.7.7
|
||||
fetch_extract "https://github.com/libarchive/libarchive/releases/download/v${LIBARCHIVE_VERSION}/libarchive-${LIBARCHIVE_VERSION}.tar.gz" libarchive.tar.gz
|
||||
(
|
||||
cd "libarchive-${LIBARCHIVE_VERSION}"
|
||||
./configure --host="${HOST}" --prefix="${PREFIX}" \
|
||||
--enable-static --disable-shared \
|
||||
--disable-bsdtar --disable-bsdcat --disable-bsdcpio --disable-bsdunzip \
|
||||
--without-xml2 --without-iconv --without-zstd --without-lz4 \
|
||||
--without-openssl --without-libb2 \
|
||||
CPPFLAGS="-I${PREFIX}/include" \
|
||||
LDFLAGS="-L${PREFIX}/lib"
|
||||
make -j"${JOBS}"
|
||||
make install
|
||||
)
|
||||
|
||||
# libcap-ng — github auto-archive (release artifacts for older tags
|
||||
# aren't always uploaded; the auto-archive URL is always available
|
||||
# for any tag, but doesn't ship a pre-generated configure script, so
|
||||
# we autoreconf it ourselves).
|
||||
LIBCAP_NG_VERSION=0.8.5
|
||||
fetch_extract "https://github.com/stevegrubb/libcap-ng/archive/refs/tags/v${LIBCAP_NG_VERSION}.tar.gz" libcap-ng.tar.gz
|
||||
(
|
||||
cd "libcap-ng-${LIBCAP_NG_VERSION}"
|
||||
# GNU automake's default (strict) mode requires these standard
|
||||
# files to exist; the auto-archive tarball doesn't ship NEWS.
|
||||
# Cheaper than configure.ac surgery.
|
||||
touch NEWS README AUTHORS ChangeLog
|
||||
autoreconf -i
|
||||
./configure --host="${HOST}" --prefix="${PREFIX}" \
|
||||
--enable-static --disable-shared \
|
||||
--without-python --without-python3
|
||||
make -j"${JOBS}"
|
||||
make install
|
||||
)
|
||||
|
||||
# libseccomp — needs gperf at build time (installed via apt above).
|
||||
LIBSECCOMP_VERSION=2.5.5
|
||||
fetch_extract "https://github.com/seccomp/libseccomp/releases/download/v${LIBSECCOMP_VERSION}/libseccomp-${LIBSECCOMP_VERSION}.tar.gz" libseccomp.tar.gz
|
||||
(
|
||||
cd "libseccomp-${LIBSECCOMP_VERSION}"
|
||||
./configure --host="${HOST}" --prefix="${PREFIX}" \
|
||||
--enable-static --disable-shared \
|
||||
--disable-python
|
||||
make -j"${JOBS}"
|
||||
make install
|
||||
)
|
||||
|
||||
# Linker-script `.so` shims for libseccomp + libcap-ng. The Rust
|
||||
# `-sys` crates emit plain `cargo:rustc-link-lib=seccomp` (no
|
||||
# static= prefix), and they don't declare `links = "..."` in their
|
||||
# Cargo.toml, so cargo's build-script override can't match them.
|
||||
# Instead we hand the linker fake `.so` files that are actually GNU
|
||||
# ld linker scripts pointing at the static archive — when ld resolves
|
||||
# `-lseccomp` to libseccomp.so it reads the script and pulls in
|
||||
# libseccomp.a as if statically linked. Works regardless of -Bstatic
|
||||
# vs -Bdynamic state and avoids needing to patch the -sys crates.
|
||||
cat > "${PREFIX}/lib/libseccomp.so" <<EOF
|
||||
/* Linker script: pull in the static archive when -lseccomp resolves here. */
|
||||
GROUP ( ${PREFIX}/lib/libseccomp.a )
|
||||
EOF
|
||||
cat > "${PREFIX}/lib/libcap-ng.so" <<EOF
|
||||
/* Linker script: pull in the static archive when -lcap-ng resolves here. */
|
||||
GROUP ( ${PREFIX}/lib/libcap-ng.a )
|
||||
EOF
|
||||
|
||||
echo "static-musl x86_64 C deps installed under ${PREFIX}"
|
||||
Executable
+58
@@ -0,0 +1,58 @@
|
||||
#!/bin/bash
|
||||
# Copyright © 2025-2026 Apple Inc. and the Containerization project authors.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# https://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
# Script to scan the VM boot logs from the integration tests for kernel panics.
|
||||
# Looks for common kernel panic messages like "attempted to kill init" or "Kernel panic".
|
||||
|
||||
GIT_ROOT=$(git rev-parse --show-toplevel 2>/dev/null)
|
||||
if [ -z "$GIT_ROOT" ]; then
|
||||
echo "Error: Not in a git repository"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
BOOT_LOGS_DIR="$GIT_ROOT/bin/integration-bootlogs"
|
||||
|
||||
if [ ! -d "$BOOT_LOGS_DIR" ]; then
|
||||
echo "Error: Boot logs directory not found: $BOOT_LOGS_DIR"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Scanning boot logs in: $BOOT_LOGS_DIR"
|
||||
echo "========================================"
|
||||
echo ""
|
||||
|
||||
PANIC_FOUND=0
|
||||
|
||||
for logfile in "$BOOT_LOGS_DIR"/*; do
|
||||
if [ -f "$logfile" ]; then
|
||||
if grep -qi "attempted to kill init\|Kernel panic\|end Kernel panic\|Attempted to kill the idle task\|Oops:" "$logfile"; then
|
||||
echo "🚨 PANIC DETECTED in: $(basename "$logfile")"
|
||||
echo "---"
|
||||
grep -i -B 5 -A 10 "attempted to kill init\|Kernel panic\|end Kernel panic\|Attempted to kill the idle task\|Oops:" "$logfile" | head -30
|
||||
echo ""
|
||||
echo "========================================"
|
||||
echo ""
|
||||
PANIC_FOUND=1
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
if [ $PANIC_FOUND -eq 0 ]; then
|
||||
echo "✅ No kernel panics detected in boot logs"
|
||||
else
|
||||
echo "❌ Found kernel panics - Virtual machine(s) crashed during integration tests"
|
||||
fi
|
||||
|
||||
exit $PANIC_FOUND
|
||||
@@ -0,0 +1,11 @@
|
||||
[SWIFT_STYLE]
|
||||
firstLine = '//===----------------------------------------------------------------------===//'
|
||||
endLine = "//===----------------------------------------------------------------------===//\n"
|
||||
beforeEachLine = '// '
|
||||
afterEachLine = ''
|
||||
allowBlankLines = false
|
||||
multipleLines = true
|
||||
padLines = false
|
||||
firstLineDetectionPattern = '//\s?==='
|
||||
lastLineDetectionPattern = '//\s?==='
|
||||
skipLinePattern = '// swift-tools-version'
|
||||
Executable
+24
@@ -0,0 +1,24 @@
|
||||
#!/usr/bin/env bash
|
||||
# Copyright © 2025-2026 Apple Inc. and the Containerization project authors.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# https://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
echo "Checking existence of hawkeye..."
|
||||
|
||||
if command -v .local/bin/hawkeye >/dev/null 2>&1; then
|
||||
echo "hawkeye found!"
|
||||
else
|
||||
echo "hawkeye not found in PATH"
|
||||
echo "please install hawkeye. For convenience, you can run scripts/install-hawkeye.sh"
|
||||
exit 1
|
||||
fi
|
||||
Executable
+50
@@ -0,0 +1,50 @@
|
||||
#!/usr/bin/env bash
|
||||
# Copyright © 2025-2026 Apple Inc. and the Containerization project authors.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# https://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
if command -v .local/bin/hawkeye >/dev/null 2>&1; then
|
||||
echo "hawkeye already installed"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# This installer supports Apple silicon (arm64 macOS) only.
|
||||
if [ "$(uname -s)" != "Darwin" ] || [ "$(uname -m)" != "arm64" ]; then
|
||||
echo "error: install-hawkeye.sh supports Apple silicon (arm64 macOS) only" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
VERSION=v6.5.1
|
||||
ARTIFACT="hawkeye-aarch64-apple-darwin.tar.xz"
|
||||
ARTIFACT_URL="https://github.com/korandoru/hawkeye/releases/download/${VERSION}/${ARTIFACT}"
|
||||
# Pinned SHA-256 of ${ARTIFACT} for ${VERSION}; update when bumping VERSION.
|
||||
EXPECTED_SHA256="99777f21e4e56c9946ed93621885532c6a0476377f497565c583f5911f2cbb1f"
|
||||
|
||||
echo "Installing hawkeye ${VERSION}"
|
||||
workdir="$(mktemp -d)"
|
||||
trap 'rm -rf "${workdir}"' EXIT
|
||||
tarball="${workdir}/${ARTIFACT}"
|
||||
|
||||
# Download the tarball, verify it against the pinned checksum (aborts on
|
||||
# mismatch), then extract just the hawkeye binary into .local/bin.
|
||||
curl --proto '=https' --tlsv1.2 -LsSf "${ARTIFACT_URL}" -o "${tarball}"
|
||||
echo "${EXPECTED_SHA256} ${tarball}" | shasum -a 256 -c -
|
||||
|
||||
tar -xf "${tarball}" --strip-components 1 -C "${workdir}"
|
||||
mkdir -p .local/bin
|
||||
mv "${workdir}/hawkeye" .local/bin/hawkeye
|
||||
chmod +x .local/bin/hawkeye
|
||||
|
||||
echo "hawkeye ${VERSION} installed to .local/bin/hawkeye"
|
||||
@@ -0,0 +1,13 @@
|
||||
Copyright ©{{ " " }}{%- set created = attrs.git_file_created_year or attrs.disk_file_created_year -%}{%- set modified = attrs.git_file_modified_year or created -%}{%- if created != modified -%} {{created}}-{{modified}}{%- else -%}{{created}}{%- endif -%}{{ " " }}{{ props["copyrightOwner"] }}.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
https://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
Executable
+52
@@ -0,0 +1,52 @@
|
||||
#! /bin/bash -e
|
||||
# Copyright © 2025-2026 Apple Inc. and the Containerization project authors.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# https://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
opts=()
|
||||
opts+=("--allow-writing-to-directory" "$1")
|
||||
opts+=("generate-documentation")
|
||||
opts+=("--target" "Containerization")
|
||||
opts+=("--target" "ContainerizationArchive")
|
||||
opts+=("--target" "ContainerizationError")
|
||||
opts+=("--target" "ContainerizationEXT4")
|
||||
opts+=("--target" "ContainerizationExtras")
|
||||
opts+=("--target" "ContainerizationIO")
|
||||
opts+=("--target" "ContainerizationNetlink")
|
||||
opts+=("--target" "ContainerizationOCI")
|
||||
opts+=("--target" "ContainerizationOS")
|
||||
opts+=("--output-path" "$1")
|
||||
opts+=("--disable-indexing")
|
||||
opts+=("--transform-for-static-hosting")
|
||||
opts+=("--enable-experimental-combined-documentation")
|
||||
opts+=("--experimental-documentation-coverage")
|
||||
|
||||
if [ ! -z "$2" ] ; then
|
||||
opts+=("--hosting-base-path" "$2")
|
||||
fi
|
||||
|
||||
/usr/bin/swift package ${opts[@]}
|
||||
|
||||
echo '{}' > "$1/theme-settings.json"
|
||||
|
||||
cat > "$1/index.html" <<'EOF'
|
||||
<html lang="en-US">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="refresh" content="0; url=./documentation/">
|
||||
</head>
|
||||
<body>
|
||||
<p>If you are not redirected automatically, <a href="./documentation/">click here</a>.</p>
|
||||
</body>
|
||||
</html>
|
||||
EOF
|
||||
@@ -0,0 +1,41 @@
|
||||
# virtiofsd patch — skip capability drop when --sandbox=none.
|
||||
#
|
||||
# virtiofsd 1.13.3 unconditionally calls capng::apply (capset(2)) at
|
||||
# startup when running as root. Inside apple/container's --virtualization
|
||||
# dev container the default seccomp profile blocks capset(2), so virtiofsd
|
||||
# fails with "failed to sync capabilities with the kernel" and
|
||||
# process::exit(1)s before binding its socket.
|
||||
#
|
||||
# We already pass --sandbox=none to virtiofsd from VirtiofsdProcess (same
|
||||
# rationale as why cloud-hypervisor runs with --seccomp false in the same
|
||||
# environment). This patch extends the existing upstream gate ("We don't
|
||||
# modify the capabilities if the user call us without any sandbox") so
|
||||
# that --sandbox=none also skips cap drop at uid==0, matching the user's
|
||||
# explicit opt-out from the sandbox.
|
||||
#
|
||||
# Applied automatically by `make build-virtiofsd` before `cargo build`.
|
||||
# Targets virtiofsd 1.13.3 (.local/virtiofsd).
|
||||
|
||||
diff --git a/src/main.rs b/src/main.rs
|
||||
index 176e178..27dce55 100644
|
||||
--- a/src/main.rs
|
||||
+++ b/src/main.rs
|
||||
@@ -858,8 +858,17 @@ fn main() {
|
||||
|
||||
// We don't modify the capabilities if the user call us without
|
||||
// any sandbox (i.e. --sandbox=none) as unprivileged user
|
||||
+ //
|
||||
+ // CONTAINERIZATION-PATCH: also skip cap drop with --sandbox=none even
|
||||
+ // when running as root. Inside apple/container's --virtualization dev
|
||||
+ // container the seccomp profile blocks capset(2), so capng::apply
|
||||
+ // fails with "failed to sync capabilities with the kernel" and
|
||||
+ // virtiofsd process::exit(1)s before binding its socket. The
|
||||
+ // user explicitly opted out of the sandbox; respect that and don't
|
||||
+ // touch caps either. Same class of issue as why CH runs with
|
||||
+ // --seccomp false in the same env.
|
||||
let uid = unsafe { libc::geteuid() };
|
||||
- if uid == 0 {
|
||||
+ if uid == 0 && !matches!(opt.sandbox, SandboxMode::None) {
|
||||
drop_capabilities(fs_cfg.inode_file_handles, opt.modcaps);
|
||||
}
|
||||
|
||||
Executable
+16
@@ -0,0 +1,16 @@
|
||||
#! /bin/bash -e
|
||||
|
||||
setup_error() {
|
||||
echo failed to run: $1 1>&2
|
||||
echo run '"make pre-commit"' and try again 1>&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
if [ ! -z "${PRECOMMIT_NOFMT}" ] ; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
echo checking formatting and licenses 1>&2
|
||||
project_pathname=$(git rev-parse --show-toplevel)
|
||||
cd "${project_pathname}"
|
||||
make check
|
||||
Reference in New Issue
Block a user