diff --git a/local/scripts/build-preflight.sh b/local/scripts/build-preflight.sh new file mode 100644 index 00000000..5300cb49 --- /dev/null +++ b/local/scripts/build-preflight.sh @@ -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 <] [--release=] [--strict-durability] [--strict-metadata] [--extra-package= ...] +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" diff --git a/local/scripts/build-redbear.sh b/local/scripts/build-redbear.sh index 04a956c4..454536e9 100755 --- a/local/scripts/build-redbear.sh +++ b/local/scripts/build-redbear.sh @@ -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" diff --git a/local/scripts/build-release-mode.sh b/local/scripts/build-release-mode.sh new file mode 100644 index 00000000..dc1c22bc --- /dev/null +++ b/local/scripts/build-release-mode.sh @@ -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 < [--config=] [--extra-package= ...] +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 diff --git a/local/scripts/classify-patch-state.py b/local/scripts/classify-patch-state.py new file mode 100644 index 00000000..71de29c8 --- /dev/null +++ b/local/scripts/classify-patch-state.py @@ -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()) diff --git a/local/scripts/lib/relibc-surface.sh b/local/scripts/lib/relibc-surface.sh new file mode 100644 index 00000000..56da6503 --- /dev/null +++ b/local/scripts/lib/relibc-surface.sh @@ -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 +} diff --git a/local/scripts/verify-durable-source-edits.py b/local/scripts/verify-durable-source-edits.py new file mode 100644 index 00000000..c6a72798 --- /dev/null +++ b/local/scripts/verify-durable-source-edits.py @@ -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()) diff --git a/recipes/wip/qt/qtbase/recipe.toml b/recipes/wip/qt/qtbase/recipe.toml index be7e8388..e8158197 100644 --- a/recipes/wip/qt/qtbase/recipe.toml +++ b/recipes/wip/qt/qtbase/recipe.toml @@ -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