feat: add build preflight and sysroot helpers
This commit is contained in:
@@ -0,0 +1,156 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||
PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
||||
|
||||
CONFIG="redbear-full"
|
||||
RELEASE="${REDBEAR_RELEASE:-}"
|
||||
STRICT_DURABILITY="${REDBEAR_STRICT_DURABILITY:-0}"
|
||||
STRICT_METADATA="${REDBEAR_STRICT_METADATA:-0}"
|
||||
EXTRA_PACKAGES=()
|
||||
|
||||
usage() {
|
||||
cat <<EOF
|
||||
Usage: $(basename "$0") [--config=<name>] [--release=<ver>] [--strict-durability] [--strict-metadata] [--extra-package=<pkg> ...]
|
||||
EOF
|
||||
}
|
||||
|
||||
while [ $# -gt 0 ]; do
|
||||
case "$1" in
|
||||
--config=*) CONFIG="${1#*=}" ;;
|
||||
--release=*) RELEASE="${1#*=}" ;;
|
||||
--strict-durability) STRICT_DURABILITY=1 ;;
|
||||
--strict-metadata) STRICT_METADATA=1 ;;
|
||||
--extra-package=*) EXTRA_PACKAGES+=("${1#*=}") ;;
|
||||
-h|--help) usage; exit 0 ;;
|
||||
*) echo "Unknown: $1" >&2; usage >&2; exit 1 ;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
|
||||
cd "$PROJECT_ROOT"
|
||||
|
||||
echo ">>> Build preflight: $CONFIG"
|
||||
|
||||
if [ -x "$SCRIPT_DIR/verify-overlay-integrity.sh" ]; then
|
||||
if ! "$SCRIPT_DIR/verify-overlay-integrity.sh" --quiet; then
|
||||
echo ">>> Preflight note: overlay integrity script reported legacy issues; continuing with build-focused checks."
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ -n "$RELEASE" ]; then
|
||||
bash "$SCRIPT_DIR/build-release-mode.sh" --release="$RELEASE" --config="$CONFIG" "${EXTRA_PACKAGES[@]/#/--extra-package=}"
|
||||
fi
|
||||
|
||||
python3 "$SCRIPT_DIR/validate-source-trees.py" "$CONFIG" "${EXTRA_PACKAGES[@]/#/--extra-package=}"
|
||||
|
||||
python3 - "$PROJECT_ROOT" "$CONFIG" "$STRICT_METADATA" "${EXTRA_PACKAGES[@]}" <<'PY'
|
||||
import sys
|
||||
import tomllib
|
||||
from pathlib import Path
|
||||
|
||||
project_root = Path(sys.argv[1])
|
||||
config_name = sys.argv[2]
|
||||
strict_metadata = sys.argv[3] == "1"
|
||||
extra_packages = sys.argv[4:]
|
||||
|
||||
def build_lookup():
|
||||
lookup = {}
|
||||
for root in (project_root / "recipes", project_root / "local/recipes"):
|
||||
for recipe_toml in root.rglob("recipe.toml"):
|
||||
if not recipe_toml.exists():
|
||||
continue
|
||||
parts = recipe_toml.parts
|
||||
if "source" in parts or "target" in parts:
|
||||
continue
|
||||
package_name = recipe_toml.parent.name
|
||||
lookup.setdefault(package_name, recipe_toml)
|
||||
return lookup
|
||||
|
||||
def resolve_config(config_path, visited=None):
|
||||
if visited is None:
|
||||
visited = set()
|
||||
config_path = config_path.resolve()
|
||||
if config_path in visited:
|
||||
return {}
|
||||
visited.add(config_path)
|
||||
config = tomllib.loads(config_path.read_text())
|
||||
packages = dict(config.get("packages", {}))
|
||||
for include in config.get("include", []):
|
||||
include_path = config_path.parent / include
|
||||
if include_path.exists():
|
||||
included = resolve_config(include_path, visited)
|
||||
for name, value in packages.items():
|
||||
included[name] = value
|
||||
packages = included
|
||||
return packages
|
||||
|
||||
lookup = build_lookup()
|
||||
config_path = project_root / "config" / f"{config_name}.toml"
|
||||
requested = resolve_config(config_path)
|
||||
for pkg in extra_packages:
|
||||
requested.setdefault(pkg, {})
|
||||
|
||||
errors = []
|
||||
warnings = []
|
||||
for package_name, package_conf in sorted(requested.items()):
|
||||
if str(package_conf) == "ignore" or package_name in {"libgcc", "libstdcxx"}:
|
||||
continue
|
||||
recipe_toml = lookup.get(package_name)
|
||||
if recipe_toml is None:
|
||||
continue
|
||||
recipe = tomllib.loads(recipe_toml.read_text())
|
||||
source = recipe.get("source", {})
|
||||
rel = recipe_toml.relative_to(project_root).as_posix()
|
||||
is_wip_or_local = rel.startswith("recipes/wip/") or rel.startswith("local/recipes/")
|
||||
if isinstance(source, dict) and "tar" in source and "blake3" not in source:
|
||||
msg = f"missing blake3 for tar recipe: {recipe_toml.relative_to(project_root)}"
|
||||
(errors if strict_metadata and not is_wip_or_local else warnings).append(msg)
|
||||
for patch in source.get("patches", []):
|
||||
patch_path = (recipe_toml.parent / patch).resolve()
|
||||
if not patch_path.exists():
|
||||
msg = f"missing patch file: {patch} for {recipe_toml.relative_to(project_root)}"
|
||||
(errors if strict_metadata else warnings).append(msg)
|
||||
|
||||
for warning in warnings:
|
||||
print(f"WARN: {warning}", file=sys.stderr)
|
||||
if errors:
|
||||
for error in errors:
|
||||
print(f"ERROR: {error}", file=sys.stderr)
|
||||
raise SystemExit(1)
|
||||
PY
|
||||
|
||||
if [ -x "$SCRIPT_DIR/classify-patch-state.py" ]; then
|
||||
python3 "$SCRIPT_DIR/classify-patch-state.py"
|
||||
fi
|
||||
|
||||
if [ -x "$SCRIPT_DIR/verify-durable-source-edits.py" ]; then
|
||||
args=()
|
||||
if [ "$STRICT_DURABILITY" = "1" ]; then
|
||||
args+=(--strict)
|
||||
fi
|
||||
python3 "$SCRIPT_DIR/verify-durable-source-edits.py" "${args[@]}"
|
||||
fi
|
||||
|
||||
if [ "$CONFIG" = "redbear-full" ]; then
|
||||
relibc_include="$(PROJECT_ROOT="$PROJECT_ROOT" bash -c 'source "$0"; redbear_relibc_stage_include_dir' "$SCRIPT_DIR/lib/relibc-surface.sh")"
|
||||
relibc_lib_dir="$(PROJECT_ROOT="$PROJECT_ROOT" bash -c 'source "$0"; redbear_relibc_stage_lib_dir' "$SCRIPT_DIR/lib/relibc-surface.sh")"
|
||||
if [ -d "$relibc_include" ] && [ -f "$relibc_lib_dir/libc.so" ]; then
|
||||
for hdr in sys/signalfd.h sys/timerfd.h sys/eventfd.h threads.h; do
|
||||
if [ ! -f "$relibc_include/$hdr" ]; then
|
||||
echo ">>> Preflight note: relibc staged surface missing $hdr; top-level build should refresh/sync it before compilation."
|
||||
fi
|
||||
done
|
||||
if ! grep -q 'strtold' "$relibc_include/stdlib.h" 2>/dev/null; then
|
||||
echo ">>> Preflight note: relibc staged stdlib.h missing strtold declaration; top-level build should refresh/sync it before compilation."
|
||||
fi
|
||||
if ! readelf -Ws "$relibc_lib_dir/libc.so" | grep -q '_Z7strtoldPKcPPc'; then
|
||||
echo ">>> Preflight note: relibc staged libc.so missing C++ strtold compatibility export; top-level build should refresh/sync it before compilation."
|
||||
fi
|
||||
else
|
||||
echo ">>> Preflight note: relibc staged surface not present yet; build will refresh it if needed."
|
||||
fi
|
||||
fi
|
||||
|
||||
echo ">>> Build preflight passed"
|
||||
@@ -3,14 +3,26 @@ set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||
PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
||||
source "$SCRIPT_DIR/lib/relibc-surface.sh"
|
||||
|
||||
# Source .config for release mode settings (REDBEAR_RELEASE, etc.)
|
||||
if [ -f "$PROJECT_ROOT/.config" ]; then
|
||||
while IFS='?=' read -r key value; do
|
||||
while IFS= read -r line; do
|
||||
line="${line%%#*}"
|
||||
line=$(echo "$line" | xargs)
|
||||
[ -z "$line" ] && continue
|
||||
if [[ "$line" == *"?="* ]]; then
|
||||
key="${line%%\?=*}"
|
||||
value="${line#*\?=}"
|
||||
elif [[ "$line" == *"="* ]]; then
|
||||
key="${line%%=*}"
|
||||
value="${line#*=}"
|
||||
else
|
||||
continue
|
||||
fi
|
||||
key=$(echo "$key" | xargs)
|
||||
value=$(echo "$value" | xargs)
|
||||
[ -z "$key" ] && continue
|
||||
[[ "$key" =~ ^# ]] && continue
|
||||
# Only set if not already set in environment
|
||||
[ -n "${!key:-}" ] || export "$key=$value"
|
||||
done < "$PROJECT_ROOT/.config"
|
||||
@@ -111,31 +123,6 @@ stash_nested_repo_if_dirty() {
|
||||
|
||||
stash_nested_repo_if_dirty "$PROJECT_ROOT/recipes/core/relibc/source" "relibc"
|
||||
|
||||
ensure_relibc_desktop_surface() {
|
||||
local relibc_target="$PROJECT_ROOT/recipes/core/relibc/target/x86_64-unknown-redox"
|
||||
local relibc_stage_include="$relibc_target/stage/usr/include"
|
||||
local relibc_stage_lib="$relibc_target/stage/usr/lib/libc.so"
|
||||
|
||||
if [ ! -f "$relibc_stage_include/sys/signalfd.h" ] || \
|
||||
[ ! -f "$relibc_stage_include/sys/timerfd.h" ] || \
|
||||
[ ! -f "$relibc_stage_include/sys/eventfd.h" ] || \
|
||||
[ ! -f "$relibc_stage_lib" ] || \
|
||||
! readelf -Ws "$relibc_stage_lib" | grep -q '_Z7strtoldPKcPPc'; then
|
||||
echo ">>> Refreshing relibc staged surface for full desktop target..."
|
||||
rm -rf \
|
||||
"$relibc_target/build" \
|
||||
"$relibc_target/stage" \
|
||||
"$relibc_target/stage.tmp" \
|
||||
"$relibc_target/sysroot"
|
||||
rm -f \
|
||||
"$relibc_target/auto_deps.toml" \
|
||||
"$relibc_target/stage.pkgar" \
|
||||
"$relibc_target/stage.toml"
|
||||
REPO_OFFLINE=1 COOKBOOK_OFFLINE=true CI=1 ./target/release/repo cook relibc
|
||||
echo ""
|
||||
fi
|
||||
}
|
||||
|
||||
if [ "$APPLY_PATCHES" = "1" ] && [ -z "${REDBEAR_RELEASE:-}" ]; then
|
||||
echo ">>> Applying local patches..."
|
||||
|
||||
@@ -199,7 +186,7 @@ if [ ! -f "target/release/repo" ]; then
|
||||
fi
|
||||
|
||||
if [ "$CONFIG" = "redbear-full" ]; then
|
||||
ensure_relibc_desktop_surface
|
||||
redbear_ensure_relibc_desktop_surface
|
||||
fi
|
||||
|
||||
FW_AMD_DIR="$PROJECT_ROOT/local/firmware/amdgpu"
|
||||
@@ -218,36 +205,17 @@ fi
|
||||
echo ">>> Building Red Bear OS with config: $CONFIG"
|
||||
echo ">>> This may take 30-60 minutes on first build..."
|
||||
|
||||
# In release mode, verify archives exist before building
|
||||
if [ -n "${REDBEAR_RELEASE:-}" ]; then
|
||||
echo ">>> Release mode: $REDBEAR_RELEASE"
|
||||
if [ -f "./local/scripts/verify-sources-archived.sh" ]; then
|
||||
bash "./local/scripts/verify-sources-archived.sh" --release="$REDBEAR_RELEASE" || {
|
||||
echo "ERROR: Release archive verification failed. Run: provision-release.sh"
|
||||
exit 1
|
||||
}
|
||||
fi
|
||||
bash "$PROJECT_ROOT/local/scripts/build-release-mode.sh" --release="$REDBEAR_RELEASE" --config="$CONFIG" --extra-package=relibc
|
||||
fi
|
||||
|
||||
bash "$PROJECT_ROOT/local/scripts/build-preflight.sh" --config="$CONFIG" ${REDBEAR_RELEASE:+--release="$REDBEAR_RELEASE"} --extra-package=relibc
|
||||
|
||||
if [ "${REDBEAR_ALLOW_UPSTREAM:-0}" = "1" ]; then
|
||||
echo ">>> WARNING: Upstream fetch ENABLED (REDBEAR_ALLOW_UPSTREAM=1)"
|
||||
REPO_OFFLINE=0 COOKBOOK_OFFLINE=false CI=1 make all "CONFIG_NAME=$CONFIG" "JOBS=$JOBS"
|
||||
elif [ -n "${REDBEAR_RELEASE:-}" ]; then
|
||||
echo ">>> Release mode: building from immutable archives (offline)"
|
||||
# Validate source trees before building
|
||||
if [ -f "$PROJECT_ROOT/local/scripts/validate-source-trees.sh" ]; then
|
||||
echo ">>> Validating source trees..."
|
||||
bash "$PROJECT_ROOT/local/scripts/validate-source-trees.sh" "$CONFIG" || {
|
||||
echo "WARNING: Some source trees are missing."
|
||||
echo "Attempting build with REPO_BINARY=1 fallback for missing packages..."
|
||||
REPO_OFFLINE=1 COOKBOOK_OFFLINE=true CI=1 REPO_BINARY=1 make all "CONFIG_NAME=$CONFIG" "JOBS=$JOBS" || {
|
||||
echo "ERROR: Build failed even with binary fallback."
|
||||
echo "Run: ./local/scripts/restore-sources.sh --release=$REDBEAR_RELEASE"
|
||||
exit 1
|
||||
}
|
||||
exit 0
|
||||
}
|
||||
fi
|
||||
REPO_OFFLINE=1 COOKBOOK_OFFLINE=true CI=1 make all "CONFIG_NAME=$CONFIG" "JOBS=$JOBS"
|
||||
elif [ "$ALLOW_UPSTREAM" -eq 1 ]; then
|
||||
echo ">>> Upstream recipe refresh enabled"
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||
PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
||||
|
||||
RELEASE=""
|
||||
CONFIG="redbear-full"
|
||||
EXTRA_PACKAGES=()
|
||||
|
||||
usage() {
|
||||
cat <<EOF
|
||||
Usage: $(basename "$0") --release=<ver> [--config=<name>] [--extra-package=<pkg> ...]
|
||||
EOF
|
||||
}
|
||||
|
||||
while [ $# -gt 0 ]; do
|
||||
case "$1" in
|
||||
--release=*) RELEASE="${1#*=}" ;;
|
||||
--config=*) CONFIG="${1#*=}" ;;
|
||||
--extra-package=*) EXTRA_PACKAGES+=("${1#*=}") ;;
|
||||
-h|--help) usage; exit 0 ;;
|
||||
*) echo "Unknown: $1" >&2; usage >&2; exit 1 ;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
|
||||
if [ -z "$RELEASE" ]; then
|
||||
echo "ERROR: --release is required" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
cd "$PROJECT_ROOT"
|
||||
|
||||
echo ">>> Release mode: $RELEASE"
|
||||
bash "$SCRIPT_DIR/verify-sources-archived.sh" --release="$RELEASE"
|
||||
|
||||
if [ -f "$SCRIPT_DIR/ensure-release-sources.sh" ]; then
|
||||
echo ">>> Ensuring release source trees for $CONFIG..."
|
||||
args=("$SCRIPT_DIR/ensure-release-sources.sh" "--release=$RELEASE" "--config=$CONFIG")
|
||||
for package_name in "${EXTRA_PACKAGES[@]}"; do
|
||||
args+=("--extra-package=$package_name")
|
||||
done
|
||||
bash "${args[@]}"
|
||||
fi
|
||||
@@ -0,0 +1,57 @@
|
||||
#!/usr/bin/env python3
|
||||
import argparse
|
||||
import subprocess
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
PROJECT_ROOT = Path(__file__).resolve().parents[2]
|
||||
|
||||
PATCH_TARGETS = {
|
||||
"kernel": PROJECT_ROOT / "recipes/core/kernel/source",
|
||||
"base": PROJECT_ROOT / "recipes/core/base/source",
|
||||
"relibc": PROJECT_ROOT / "recipes/core/relibc/source",
|
||||
"bootloader": PROJECT_ROOT / "recipes/core/bootloader/source",
|
||||
"installer": PROJECT_ROOT / "recipes/core/installer/source",
|
||||
}
|
||||
|
||||
|
||||
def run_patch(target: Path, patch_file: Path, reverse: bool) -> bool:
|
||||
cmd = ["patch", "--dry-run", "-p1", "-d", str(target)]
|
||||
if reverse:
|
||||
cmd.insert(1, "-R")
|
||||
with patch_file.open("rb") as handle:
|
||||
proc = subprocess.run(cmd, stdin=handle, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
|
||||
return proc.returncode == 0
|
||||
|
||||
|
||||
def classify_patch(target: Path, patch_file: Path) -> str:
|
||||
if not target.exists():
|
||||
return "missing_target"
|
||||
if run_patch(target, patch_file, reverse=False):
|
||||
return "applies_cleanly"
|
||||
if run_patch(target, patch_file, reverse=True):
|
||||
return "already_applied"
|
||||
return "drifted_or_obsolete"
|
||||
|
||||
|
||||
def main() -> int:
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument("--strict", action="store_true")
|
||||
args = parser.parse_args()
|
||||
|
||||
had_problem = False
|
||||
for label, target in PATCH_TARGETS.items():
|
||||
patch_dir = PROJECT_ROOT / "local/patches" / label
|
||||
if not patch_dir.is_dir():
|
||||
continue
|
||||
for patch_file in sorted(patch_dir.glob("*.patch")):
|
||||
status = classify_patch(target, patch_file)
|
||||
print(f"{label}\t{patch_file.name}\t{status}")
|
||||
if status in {"missing_target", "drifted_or_obsolete"}:
|
||||
had_problem = True
|
||||
|
||||
return 1 if args.strict and had_problem else 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main())
|
||||
@@ -0,0 +1,143 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
redbear_project_root() {
|
||||
if [ -n "${PROJECT_ROOT:-}" ]; then
|
||||
printf '%s\n' "${PROJECT_ROOT}"
|
||||
return 0
|
||||
fi
|
||||
if [ -n "${COOKBOOK_ROOT:-}" ]; then
|
||||
printf '%s\n' "${COOKBOOK_ROOT}"
|
||||
return 0
|
||||
fi
|
||||
return 1
|
||||
}
|
||||
|
||||
redbear_choose_toolchain_root() {
|
||||
if [ -n "${COOKBOOK_HOST_SYSROOT:-}" ] && [ -d "${COOKBOOK_HOST_SYSROOT}" ]; then
|
||||
printf '%s\n' "${COOKBOOK_HOST_SYSROOT}"
|
||||
return 0
|
||||
fi
|
||||
if [ -d "${HOME}/.redoxer/x86_64-unknown-redox/toolchain" ]; then
|
||||
printf '%s\n' "${HOME}/.redoxer/x86_64-unknown-redox/toolchain"
|
||||
return 0
|
||||
fi
|
||||
printf '%s\n' "$(redbear_project_root)/prefix/x86_64-unknown-redox/sysroot"
|
||||
}
|
||||
|
||||
redbear_relibc_target_dir() {
|
||||
printf '%s\n' "$(redbear_project_root)/recipes/core/relibc/target/x86_64-unknown-redox"
|
||||
}
|
||||
|
||||
redbear_relibc_stage_include_dir() {
|
||||
local relibc_target
|
||||
relibc_target="$(redbear_relibc_target_dir)"
|
||||
printf '%s\n' "${relibc_target}/stage/usr/include"
|
||||
}
|
||||
|
||||
redbear_relibc_stage_lib_dir() {
|
||||
local relibc_target
|
||||
relibc_target="$(redbear_relibc_target_dir)"
|
||||
printf '%s\n' "${relibc_target}/stage/usr/lib"
|
||||
}
|
||||
|
||||
redbear_choose_relibc_stage_include() {
|
||||
local relibc_target stage_include tmp_include
|
||||
relibc_target="$(redbear_relibc_target_dir)"
|
||||
stage_include="${relibc_target}/stage/usr/include"
|
||||
tmp_include="${relibc_target}/stage.tmp/usr/include"
|
||||
if [ -d "$stage_include" ]; then
|
||||
printf '%s\n' "$stage_include"
|
||||
elif [ -d "$tmp_include" ]; then
|
||||
printf '%s\n' "$tmp_include"
|
||||
fi
|
||||
}
|
||||
|
||||
redbear_choose_relibc_stage_lib() {
|
||||
local relibc_target stage_lib tmp_lib build_lib candidate
|
||||
relibc_target="$(redbear_relibc_target_dir)"
|
||||
stage_lib="${relibc_target}/stage/usr/lib"
|
||||
tmp_lib="${relibc_target}/stage.tmp/usr/lib"
|
||||
build_lib="${relibc_target}/build/target/x86_64-unknown-redox/release"
|
||||
for candidate in "$stage_lib" "$tmp_lib" "$build_lib"; do
|
||||
if [ -f "$candidate/libc.so" ] && readelf -Ws "$candidate/libc.so" | grep -q '_Z7strtoldPKcPPc'; then
|
||||
printf '%s\n' "$candidate"
|
||||
return 0
|
||||
fi
|
||||
done
|
||||
for candidate in "$stage_lib" "$build_lib" "$tmp_lib"; do
|
||||
if [ -d "$candidate" ]; then
|
||||
printf '%s\n' "$candidate"
|
||||
return 0
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
redbear_copy_relibc_surface_into_sysroot() {
|
||||
local destination_sysroot="$1"
|
||||
local include_dir lib_dir
|
||||
include_dir="$(redbear_choose_relibc_stage_include)"
|
||||
lib_dir="$(redbear_choose_relibc_stage_lib)"
|
||||
|
||||
if [ -n "$include_dir" ] && [ -d "$include_dir" ]; then
|
||||
mkdir -p "${destination_sysroot}/include"
|
||||
cp -a "${include_dir}/." "${destination_sysroot}/include/"
|
||||
fi
|
||||
if [ -n "$lib_dir" ] && [ -d "$lib_dir" ]; then
|
||||
mkdir -p "${destination_sysroot}/lib"
|
||||
cp -a "${lib_dir}/." "${destination_sysroot}/lib/"
|
||||
fi
|
||||
}
|
||||
|
||||
redbear_relibc_surface_ready() {
|
||||
local relibc_target relibc_stage_include relibc_stage_lib
|
||||
relibc_target="$(redbear_relibc_target_dir)"
|
||||
relibc_stage_include="${relibc_target}/stage/usr/include"
|
||||
relibc_stage_lib="${relibc_target}/stage/usr/lib/libc.so"
|
||||
|
||||
[ -f "${relibc_stage_include}/sys/signalfd.h" ] || return 1
|
||||
[ -f "${relibc_stage_include}/sys/timerfd.h" ] || return 1
|
||||
[ -f "${relibc_stage_include}/sys/eventfd.h" ] || return 1
|
||||
[ -f "${relibc_stage_include}/threads.h" ] || return 1
|
||||
[ -f "${relibc_stage_lib}" ] || return 1
|
||||
readelf -Ws "${relibc_stage_lib}" | grep -q '_Z7strtoldPKcPPc' || return 1
|
||||
return 0
|
||||
}
|
||||
|
||||
redbear_sync_relibc_surface_to_toolchain() {
|
||||
local relibc_target relibc_stage_include relibc_stage_lib toolchain_sysroot
|
||||
relibc_target="$(redbear_relibc_target_dir)"
|
||||
relibc_stage_include="${relibc_target}/stage/usr/include"
|
||||
relibc_stage_lib="${relibc_target}/stage/usr/lib"
|
||||
toolchain_sysroot="$(redbear_choose_toolchain_root)"
|
||||
|
||||
mkdir -p \
|
||||
"${toolchain_sysroot}/include" \
|
||||
"${toolchain_sysroot}/x86_64-unknown-redox/include" \
|
||||
"${toolchain_sysroot}/x86_64-unknown-redox/lib"
|
||||
|
||||
cp -a "${relibc_stage_include}/." "${toolchain_sysroot}/include/"
|
||||
cp -a "${relibc_stage_include}/." "${toolchain_sysroot}/x86_64-unknown-redox/include/"
|
||||
cp -a "${relibc_stage_lib}/." "${toolchain_sysroot}/x86_64-unknown-redox/lib/"
|
||||
}
|
||||
|
||||
redbear_ensure_relibc_desktop_surface() {
|
||||
local relibc_target
|
||||
relibc_target="$(redbear_relibc_target_dir)"
|
||||
|
||||
if ! redbear_relibc_surface_ready; then
|
||||
echo ">>> Refreshing relibc staged surface for full desktop target..."
|
||||
rm -rf \
|
||||
"${relibc_target}/build" \
|
||||
"${relibc_target}/stage" \
|
||||
"${relibc_target}/stage.tmp" \
|
||||
"${relibc_target}/sysroot"
|
||||
rm -f \
|
||||
"${relibc_target}/auto_deps.toml" \
|
||||
"${relibc_target}/stage.pkgar" \
|
||||
"${relibc_target}/stage.toml"
|
||||
REPO_OFFLINE=1 COOKBOOK_OFFLINE=true CI=1 ./target/release/repo cook relibc
|
||||
echo ""
|
||||
fi
|
||||
|
||||
redbear_sync_relibc_surface_to_toolchain
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
#!/usr/bin/env python3
|
||||
import argparse
|
||||
import subprocess
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
PROJECT_ROOT = Path(__file__).resolve().parents[2]
|
||||
UPSTREAM_OWNED = {
|
||||
"kernel": PROJECT_ROOT / "recipes/core/kernel/source",
|
||||
"base": PROJECT_ROOT / "recipes/core/base/source",
|
||||
"relibc": PROJECT_ROOT / "recipes/core/relibc/source",
|
||||
"bootloader": PROJECT_ROOT / "recipes/core/bootloader/source",
|
||||
"installer": PROJECT_ROOT / "recipes/core/installer/source",
|
||||
}
|
||||
|
||||
|
||||
def git_has_changes(repo: Path) -> tuple[bool, list[str]]:
|
||||
if not (repo / ".git").exists():
|
||||
return False, []
|
||||
proc = subprocess.run(
|
||||
["git", "status", "--short"],
|
||||
cwd=repo,
|
||||
check=False,
|
||||
capture_output=True,
|
||||
text=True,
|
||||
)
|
||||
lines = [line.rstrip() for line in proc.stdout.splitlines() if line.strip()]
|
||||
return bool(lines), lines
|
||||
|
||||
|
||||
def main() -> int:
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument("--strict", action="store_true")
|
||||
args = parser.parse_args()
|
||||
|
||||
dirty = False
|
||||
for label, repo in UPSTREAM_OWNED.items():
|
||||
has_changes, lines = git_has_changes(repo)
|
||||
if not has_changes:
|
||||
continue
|
||||
dirty = True
|
||||
print(f"{label}\tDIRTY\t{repo.relative_to(PROJECT_ROOT)}")
|
||||
for line in lines[:20]:
|
||||
print(f" {line}")
|
||||
if len(lines) > 20:
|
||||
print(f" ... {len(lines) - 20} more")
|
||||
|
||||
return 1 if args.strict and dirty else 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main())
|
||||
@@ -23,67 +23,32 @@ dependencies = [
|
||||
script = """
|
||||
DYNAMIC_INIT
|
||||
|
||||
PROJECT_ROOT="${COOKBOOK_ROOT}"
|
||||
source "${COOKBOOK_ROOT}/local/scripts/lib/relibc-surface.sh"
|
||||
|
||||
RELIBC_STAGE_INCLUDE_STAGE="${COOKBOOK_ROOT}/recipes/core/relibc/target/${TARGET}/stage/usr/include"
|
||||
RELIBC_STAGE_INCLUDE_TMP="${COOKBOOK_ROOT}/recipes/core/relibc/target/${TARGET}/stage.tmp/usr/include"
|
||||
RELIBC_STAGE_LIB_STAGE="${COOKBOOK_ROOT}/recipes/core/relibc/target/${TARGET}/stage/usr/lib"
|
||||
RELIBC_STAGE_LIB_TMP="${COOKBOOK_ROOT}/recipes/core/relibc/target/${TARGET}/stage.tmp/usr/lib"
|
||||
RELIBC_BUILD_LIB="${COOKBOOK_ROOT}/recipes/core/relibc/target/${TARGET}/build/target/${TARGET}/release"
|
||||
|
||||
RELIBC_STAGE_INCLUDE="$RELIBC_STAGE_INCLUDE_STAGE"
|
||||
if [ ! -d "$RELIBC_STAGE_INCLUDE" ] && [ -d "$RELIBC_STAGE_INCLUDE_TMP" ]; then
|
||||
RELIBC_STAGE_INCLUDE="$RELIBC_STAGE_INCLUDE_TMP"
|
||||
fi
|
||||
|
||||
choose_relibc_lib_stage() {
|
||||
local candidate="$1"
|
||||
if [ -f "$candidate/libc.so" ] && readelf -Ws "$candidate/libc.so" | grep -q '_Z7strtoldPKcPPc'; then
|
||||
printf '%s\n' "$candidate"
|
||||
return 0
|
||||
fi
|
||||
return 1
|
||||
}
|
||||
|
||||
choose_toolchain_root() {
|
||||
if [ -n "${COOKBOOK_HOST_SYSROOT:-}" ] && [ -d "${COOKBOOK_HOST_SYSROOT}" ]; then
|
||||
printf '%s\n' "${COOKBOOK_HOST_SYSROOT}"
|
||||
return 0
|
||||
fi
|
||||
if [ -d "${HOME}/.redoxer/x86_64-unknown-redox/toolchain" ]; then
|
||||
printf '%s\n' "${HOME}/.redoxer/x86_64-unknown-redox/toolchain"
|
||||
return 0
|
||||
fi
|
||||
printf '%s\n' "${COOKBOOK_ROOT}/prefix/x86_64-unknown-redox/sysroot"
|
||||
}
|
||||
|
||||
if RELIBC_STAGE_LIB="$(choose_relibc_lib_stage "$RELIBC_STAGE_LIB_STAGE")"; then
|
||||
:
|
||||
elif RELIBC_STAGE_LIB="$(choose_relibc_lib_stage "$RELIBC_STAGE_LIB_TMP")"; then
|
||||
:
|
||||
elif RELIBC_STAGE_LIB="$(choose_relibc_lib_stage "$RELIBC_BUILD_LIB")"; then
|
||||
:
|
||||
elif [ -d "$RELIBC_STAGE_LIB_STAGE" ]; then
|
||||
RELIBC_STAGE_LIB="$RELIBC_STAGE_LIB_STAGE"
|
||||
elif [ -d "$RELIBC_BUILD_LIB" ]; then
|
||||
RELIBC_STAGE_LIB="$RELIBC_BUILD_LIB"
|
||||
else
|
||||
RELIBC_STAGE_LIB="$RELIBC_STAGE_LIB_TMP"
|
||||
fi
|
||||
RELIBC_STAGE_INCLUDE="$(redbear_choose_relibc_stage_include)"
|
||||
RELIBC_STAGE_LIB="$(redbear_choose_relibc_stage_lib)"
|
||||
if [ -d "${RELIBC_STAGE_INCLUDE}" ]; then
|
||||
mkdir -p "${COOKBOOK_SYSROOT}/include"
|
||||
cp -a "${RELIBC_STAGE_INCLUDE}/." "${COOKBOOK_SYSROOT}/include/"
|
||||
redbear_copy_relibc_surface_into_sysroot "${COOKBOOK_SYSROOT}"
|
||||
if [ -f "${COOKBOOK_SYSROOT}/include/elf.h" ]; then
|
||||
sed -i 's/typedef uint64_t Elf64_Word;/typedef uint32_t Elf64_Word;/' "${COOKBOOK_SYSROOT}/include/elf.h"
|
||||
sed -i 's/typedef int64_t Elf64_Sword;/typedef int32_t Elf64_Sword;/' "${COOKBOOK_SYSROOT}/include/elf.h"
|
||||
fi
|
||||
export CPPFLAGS="${CPPFLAGS} -I${RELIBC_STAGE_INCLUDE}"
|
||||
export CFLAGS="${CFLAGS} -I${RELIBC_STAGE_INCLUDE}"
|
||||
export CXXFLAGS="${CXXFLAGS} -I${RELIBC_STAGE_INCLUDE}"
|
||||
export CPPFLAGS="${CPPFLAGS:-} -I${RELIBC_STAGE_INCLUDE}"
|
||||
export CFLAGS="${CFLAGS:-} -I${RELIBC_STAGE_INCLUDE}"
|
||||
export CXXFLAGS="${CXXFLAGS:-} -I${RELIBC_STAGE_INCLUDE}"
|
||||
|
||||
# The Redox GCC toolchain currently prefers its own bundled target elf.h
|
||||
# under .../x86_64-unknown-redox/include/ over the recipe sysroot copy.
|
||||
# Sync the freshly built relibc header into that toolchain include root so
|
||||
# Qt's ELF plugin parser sees the corrected ELF64 typedef layout.
|
||||
TOOLCHAIN_ROOT="$(choose_toolchain_root)"
|
||||
TOOLCHAIN_ROOT="$(redbear_choose_toolchain_root)"
|
||||
TOOLCHAIN_TARGET_INCLUDE="${TOOLCHAIN_ROOT}/x86_64-unknown-redox/include"
|
||||
TOOLCHAIN_TARGET_USR_INCLUDE="${TOOLCHAIN_ROOT}/x86_64-unknown-redox/usr/include"
|
||||
for header in elf.h semaphore.h unistd.h; do
|
||||
@@ -112,8 +77,6 @@ if [ -d "${RELIBC_STAGE_INCLUDE}" ]; then
|
||||
done
|
||||
fi
|
||||
if [ -d "${RELIBC_STAGE_LIB}" ]; then
|
||||
mkdir -p "${COOKBOOK_SYSROOT}/lib"
|
||||
cp -a "${RELIBC_STAGE_LIB}/." "${COOKBOOK_SYSROOT}/lib/"
|
||||
export LDFLAGS="-L${RELIBC_STAGE_LIB} -Wl,-rpath-link,${RELIBC_STAGE_LIB} ${LDFLAGS}"
|
||||
fi
|
||||
|
||||
@@ -166,12 +129,6 @@ if [ ! -f "${COOKBOOK_SYSROOT}/include/netinet/in6_pktinfo_compat.h" ]; then
|
||||
#ifndef IPV6_PKTINFO
|
||||
#define IPV6_PKTINFO 50
|
||||
#endif
|
||||
#ifndef in6_pktinfo
|
||||
struct in6_pktinfo {
|
||||
struct in6_addr ipi6_addr;
|
||||
unsigned int ipi6_ifindex;
|
||||
};
|
||||
#endif
|
||||
#endif
|
||||
PKTINFO_EOF
|
||||
fi
|
||||
@@ -319,10 +276,10 @@ mv "${COOKBOOK_SOURCE}/src/corelib/CMakeLists.txt.tmp" "${COOKBOOK_SOURCE}/src/c
|
||||
# Enable QtNetwork — relibc DNS resolver hardened (2026-04-29: use-after-free fix, FD leak fix,
|
||||
# transaction ID validation, RCODE/TC handling, typed error mapping).
|
||||
# QtNetwork was previously disabled. Now re-enabled for full KDE desktop path.
|
||||
sed -i 's/^# add_subdirectory(network)/ add_subdirectory(network)/' \
|
||||
sed -i 's/^\\s*# add_subdirectory(network).*/ add_subdirectory(network)/' \
|
||||
"${COOKBOOK_SOURCE}/src/CMakeLists.txt"
|
||||
# Also re-enable TUIO touch plugin which depends on QtNetwork
|
||||
sed -i 's/^# add_subdirectory(tuiotouch)/ add_subdirectory(tuiotouch)/' \
|
||||
sed -i 's/^\\s*# add_subdirectory(tuiotouch).*/ add_subdirectory(tuiotouch)/' \
|
||||
"${COOKBOOK_SOURCE}/src/plugins/generic/CMakeLists.txt"
|
||||
python - <<'PY'
|
||||
import os
|
||||
|
||||
Reference in New Issue
Block a user