build: relink only static initfs binaries on boot-ABI change, not the desktop
The ABI-staleness step recompiled the ENTIRE dynamically-linked userspace (Qt, KF6, mesa, sddm) whenever relibc/base/a-protocol-fork changed -- so editing a driver, acpi, or base recipe rebuilt the whole desktop. That is wrong: relibc is a shared libc.so.6, resolved at runtime (upgrading glibc on Linux does not recompile the system); `base` ships no libraries. Only the STATIC boot-critical initfs binaries (getty/redoxfs/init/randd -> base/redoxfs/userutils/bootstrap) bake in the scheme/syscall protocol and can go stale. Invalidate only those. Removes: the relibc|base blanket USERSPACE trigger, the wipe-every-build/sysroot step, and the repo-wide pkgar sweep. Genuine relibc C-ABI break -> --no-cache.
This commit is contained in:
@@ -628,7 +628,9 @@ if [ "$NO_CACHE" != "1" ]; then
|
||||
find "$PROJECT_ROOT/recipes" -path "*/$src/target" -type d -exec rm -rf {} + 2>/dev/null || true
|
||||
STALE_DETECTED=1
|
||||
[ "$src" = "relibc" ] && RELIBC_INVALIDATED=1
|
||||
case "$src" in relibc|base) USERSPACE_RUNTIME_STALE=1 ;; esac
|
||||
# NB: base ships NO libraries (daemons/drivers/init) and relibc is
|
||||
# a shared libc.so.6 — neither forces a userspace-wide relink. Only
|
||||
# the static initfs-critical binaries are handled, selectively, below.
|
||||
fi
|
||||
fi
|
||||
done
|
||||
@@ -661,13 +663,11 @@ if [ "$NO_CACHE" != "1" ]; then
|
||||
done
|
||||
|
||||
|
||||
if [ "$USERSPACE_RUNTIME_STALE" = "1" ] && [ "${REDBEAR_SKIP_ABI_STALENESS:-0}" != "1" ]; then
|
||||
echo ">>> Cleaning stale build/sysroot dirs (userspace-linked runtime changed)..."
|
||||
find "$PROJECT_ROOT/recipes" "$PROJECT_ROOT/local/recipes" \
|
||||
\( -path "*/target/x86_64-unknown-redox/build" \
|
||||
-o -path "*/target/x86_64-unknown-redox/sysroot" \) \
|
||||
-type d -exec rm -rf {} + 2>/dev/null || true
|
||||
fi
|
||||
# (The blanket "wipe every recipe's build/sysroot when a runtime fork changed"
|
||||
# step used to live here. It was the bug: it recompiled the entire dynamically
|
||||
# -linked desktop — Qt, KF6, mesa, sddm — on any relibc/base/syscall change,
|
||||
# which is exactly what a shared-libc system never needs. Replaced by the
|
||||
# selective, static-consumer-only invalidation below.)
|
||||
|
||||
# Downstream ABI-staleness prevention (relibc consumers).
|
||||
#
|
||||
@@ -739,78 +739,36 @@ if [ "$NO_CACHE" != "1" ]; then
|
||||
*) return 1 ;;
|
||||
esac
|
||||
}
|
||||
# ── Config-scoped ABI invalidation ──────────────────────────────────
|
||||
# repo/ is shared across configs, so a `redbear-mini` build must NOT nuke
|
||||
# packages that only `redbear-full` builds (Qt, mesa, sddm, ...) just because
|
||||
# their pkgars sit in the repo older than relibc.pkgar. Resolve the closure
|
||||
# of the config being built and only ever invalidate packages inside it.
|
||||
# No env flag needed — you named the config, so we know it's mini not full.
|
||||
declare -A _config_pkg_set
|
||||
_config_scoped=0
|
||||
_cfg_file="$PROJECT_ROOT/config/$CONFIG.toml"
|
||||
if [ -f "$_cfg_file" ]; then
|
||||
while read -r _p; do
|
||||
[ -n "$_p" ] && _config_pkg_set["$_p"]=1
|
||||
done < <(timeout 120 "$PROJECT_ROOT/target/release/repo" push-tree \
|
||||
--filesystem="$_cfg_file" 2>/dev/null \
|
||||
| sed -E 's/^[^A-Za-z0-9_]+//' | awk '{print $1}' | grep -E '^[A-Za-z0-9]')
|
||||
[ "${#_config_pkg_set[@]}" -gt 0 ] && _config_scoped=1
|
||||
fi
|
||||
if [ "$_config_scoped" = "1" ]; then
|
||||
echo ">>> ABI-staleness scoped to $CONFIG (${#_config_pkg_set[@]} pkgs); other configs' repo packages untouched."
|
||||
else
|
||||
echo ">>> NOTE: could not resolve $CONFIG package closure; ABI sweep is repo-wide (fallback)."
|
||||
fi
|
||||
_pkg_in_config() {
|
||||
# true unless we have a config closure and pkg is outside it
|
||||
[ "$_config_scoped" != "1" ] && return 0
|
||||
[ -n "${_config_pkg_set[$1]:-}" ]
|
||||
}
|
||||
invalidate_consumer() {
|
||||
local pkg="$1"
|
||||
_pkg_in_config "$pkg" || return 0
|
||||
rm -f "$REPO_DIR/$pkg".*
|
||||
find "$PROJECT_ROOT/recipes" "$PROJECT_ROOT/local/recipes" \
|
||||
-path "*/$pkg/target" -type d -exec rm -rf {} + 2>/dev/null || true
|
||||
}
|
||||
if [ "${REDBEAR_SKIP_ABI_STALENESS:-0}" = "1" ]; then
|
||||
# Fast-iteration escape hatch: skip the entire relibc-consumer
|
||||
# invalidation. Safe ONLY when relibc's ABI is unchanged (e.g. iterating
|
||||
# on a single driver/app recipe). The cookbook's own BLAKE3 dep-hash
|
||||
# cache still rebuilds recipes whose sources changed, so your edited
|
||||
# package re-cooks while everything else stays cached — no 30-min churn
|
||||
# to re-reach it. Unset to restore the stale-binary safety net (which is
|
||||
# required whenever relibc/base actually changed).
|
||||
echo ">>> REDBEAR_SKIP_ABI_STALENESS=1 — skipping relibc-consumer invalidation"
|
||||
echo ">>> (fast iteration; assumes relibc ABI unchanged). Unset to restore it."
|
||||
elif [ "$relibc_rebuilding" = "1" ]; then
|
||||
echo ">>> relibc is rebuilding — it is statically linked into every"
|
||||
echo ">>> userspace binary, so ALL packages are invalidated to force a"
|
||||
echo ">>> clean relink (correctness over speed; prevents stale-binary skew)."
|
||||
for _pkgar in "$REPO_DIR"/*.pkgar; do
|
||||
[ -f "$_pkgar" ] || continue
|
||||
_pkg="$(basename "$_pkgar" .pkgar)"
|
||||
_pkg_in_config "$_pkg" || continue
|
||||
if _rb_preserve_toolchain "$_pkg"; then
|
||||
echo ">>> preserving ABI-inert toolchain pkg '$_pkg' (consumer relinks;" \
|
||||
"set REDBEAR_FORCE_TOOLCHAIN_RECOOK=1 to force a full re-cook)."
|
||||
continue
|
||||
fi
|
||||
invalidate_consumer "$_pkg"
|
||||
done
|
||||
elif [ -f "$RELIBC_PKGAR" ]; then
|
||||
relibc_ts=$(stat -c %Y "$RELIBC_PKGAR" 2>/dev/null || echo "0")
|
||||
for _pkgar in "$REPO_DIR"/*.pkgar; do
|
||||
[ -f "$_pkgar" ] || continue
|
||||
_pkg="$(basename "$_pkgar" .pkgar)"
|
||||
[ "$_pkg" = "relibc" ] && continue
|
||||
_pkg_in_config "$_pkg" || continue
|
||||
_rb_preserve_toolchain "$_pkg" && continue
|
||||
_pkg_ts=$(stat -c %Y "$_pkgar" 2>/dev/null || echo "0")
|
||||
if [ "$relibc_ts" != "0" ] && [ "$relibc_ts" -gt "$_pkg_ts" ]; then
|
||||
echo ">>> ABI-stale $_pkg (older than relibc.pkgar — interrupted prior build); invalidating..."
|
||||
invalidate_consumer "$_pkg"
|
||||
fi
|
||||
# ── Selective, static-consumer-only ABI invalidation ───────────────
|
||||
# relibc is a SHARED library (libc.so.6): dynamically-linked userspace — Qt,
|
||||
# KF6, mesa, sddm, the whole desktop — resolves it at RUNTIME, so a relibc
|
||||
# rebuild needs NO recompile there. That is exactly why upgrading glibc on
|
||||
# Linux does not recompile the system. `base` ships no libraries at all
|
||||
# (daemons/drivers/init). The ONLY binaries that can genuinely go stale are
|
||||
# the STATIC, boot-critical initfs binaries that bake in the Redox
|
||||
# scheme/syscall protocol before libc.so is available — the getty / redoxfs /
|
||||
# init / randd class. Those come from a small fixed set of forks; when the
|
||||
# boot ABI changes (relibc rebuilds, or a syscall/libredox/redox-scheme
|
||||
# protocol crate changed -> USERSPACE_RUNTIME_STALE), relink ONLY them.
|
||||
#
|
||||
# This restores the selective rule the old "nuke every pkgar + wipe every
|
||||
# build/sysroot" version had replaced (which recompiled the entire desktop on
|
||||
# any driver/acpi/base edit). For a genuine relibc *C-ABI* break — a libc
|
||||
# struct/inline baked into a compiled consumer, which is rare — force a full
|
||||
# clean rebuild with `--no-cache`.
|
||||
ABI_CRITICAL_PKGS="base redoxfs userutils bootstrap"
|
||||
_boot_abi_changed=0
|
||||
[ "$relibc_rebuilding" = "1" ] && _boot_abi_changed=1
|
||||
[ "$USERSPACE_RUNTIME_STALE" = "1" ] && _boot_abi_changed=1
|
||||
if [ "$_boot_abi_changed" = "1" ]; then
|
||||
echo ">>> Boot ABI touched (relibc / syscall protocol fork) — relinking ONLY the"
|
||||
echo ">>> static initfs-critical binaries: $ABI_CRITICAL_PKGS."
|
||||
echo ">>> Dynamically-linked userspace (Qt/KF6/mesa/sddm/desktop) is untouched —"
|
||||
echo ">>> shared libc.so resolved at runtime (the Linux glibc model)."
|
||||
for _pkg in $ABI_CRITICAL_PKGS; do
|
||||
rm -f "$REPO_DIR/$_pkg".*
|
||||
find "$PROJECT_ROOT/recipes" "$PROJECT_ROOT/local/recipes" \
|
||||
-path "*/$_pkg/target" -type d -exec rm -rf {} + 2>/dev/null || true
|
||||
done
|
||||
fi
|
||||
fi
|
||||
|
||||
Reference in New Issue
Block a user