Files
Xenia-Canary/cmake/toolchains/xwin-case-symlinks.py
Claude (auto-RE) 30d05ee97b
Some checks failed
Orchestrator / Commit Message Validation (push) Has been skipped
Orchestrator / Lint (push) Failing after 2m0s
Orchestrator / Windows (x86-64) (push) Has been skipped
Orchestrator / Linux (x86-64) (push) Has been skipped
Orchestrator / Create Release (push) Has been skipped
snapshot: preserve the uncommitted Canary instrumentation (not authored here)
Working-tree snapshot taken 2026-07-28 so this work is not lost. To be clear
about provenance: NONE of this was written in the session that committed it —
it is pre-existing uncommitted work on phase-a-tracing, last committed 2026-07-09,
from the xenia-rs decoder/deadlock investigation. It is recorded verbatim, not
reviewed and not tested.

Contents: 24 tracked modifications (ppc_emit_memory, xex_module, object_table,
shim_utils, xboxkrnl threading/rtl, xevent/xobject/xthread, memory) plus the
untracked probe sources audit_68_host_mem_watch, audit_69_event_signal_watch,
audit_70_semaphore_release_watch, phase_b_snapshot, and cmake/toolchains.

Deliberately excluded: build-cross/ (51 GB of build output) and
vkd3d-proton.cache. Note third_party/snappy is a submodule pointer change whose
target may not be pushed anywhere, so this branch is a preservation record rather
than a guaranteed-buildable tree.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-28 20:03:33 +00:00

127 lines
4.1 KiB
Python

#!/usr/bin/env python3
"""Scan xenia source for #include directives and ensure case-aliases exist
in xwin's flat SDK/CRT include dirs. xwin's default splat adds lowercase
aliases for headers that ship with uppercase names (e.g. Windows.h),
but does NOT add aliases in the reverse direction. xenia (and its
third_party deps) include some headers using historical Microsoft casing
(<ObjBase.h>, <Psapi.h>) that don't match the lowercase filenames the
SDK ships with. This helper creates the missing symlinks.
Idempotent: re-running is safe.
"""
from __future__ import annotations
import os
import re
import sys
from pathlib import Path
INCLUDE_RE = re.compile(r'^\s*#\s*include\s*<([A-Za-z][A-Za-z0-9_/.\-]*\.h)>',
re.MULTILINE)
SOURCE_ROOTS = [
"src",
"third_party/SDL2/src",
"third_party/SDL2/include",
"third_party/discord-rpc/src",
"third_party/fmt",
"third_party/imgui",
]
SOURCE_EXTS = {".h", ".hpp", ".inc", ".c", ".cc", ".cpp", ".cxx"}
def collect_includes(repo_root: Path) -> set[str]:
"""Return set of all <foo.h>-style include targets found in source."""
seen: set[str] = set()
for root in SOURCE_ROOTS:
base = repo_root / root
if not base.exists():
continue
for path in base.rglob("*"):
if path.suffix.lower() not in SOURCE_EXTS:
continue
try:
txt = path.read_text(encoding="utf-8", errors="ignore")
except OSError:
continue
for m in INCLUDE_RE.finditer(txt):
seen.add(m.group(1))
return seen
def index_dir(d: Path) -> dict[str, str]:
"""Return mapping lowercased-basename -> actual basename for files in d."""
if not d.is_dir():
return {}
idx: dict[str, str] = {}
for entry in d.iterdir():
idx.setdefault(entry.name.lower(), entry.name)
return idx
def fix_dir(target_dir: Path, want: set[str]) -> tuple[int, int, list[str]]:
"""For each header name in `want` (basename only), create a symlink to
the case-folded sibling if the exact case doesn't exist. Returns
(created, already_ok, missing-from-sdk)."""
if not target_dir.is_dir():
return 0, 0, []
idx = index_dir(target_dir)
created = 0
already_ok = 0
missing: list[str] = []
for name in want:
# Only look at single-segment names; subdir/foo.h handled separately
if "/" in name:
continue
actual = idx.get(name.lower())
if actual is None:
missing.append(name)
continue
if actual == name:
already_ok += 1
continue
link = target_dir / name
if link.exists() or link.is_symlink():
already_ok += 1
continue
try:
link.symlink_to(actual)
created += 1
except OSError as e:
print(f" ! failed to symlink {link} -> {actual}: {e}",
file=sys.stderr)
return created, already_ok, missing
def main() -> int:
if len(sys.argv) != 3:
print("usage: xwin-case-symlinks.py <xenia-canary-root> <xwin-splat-dir>",
file=sys.stderr)
return 2
repo_root = Path(sys.argv[1]).resolve()
xwin_root = Path(sys.argv[2]).resolve()
if not (xwin_root / "crt" / "include").exists():
print(f"error: {xwin_root}/crt/include missing", file=sys.stderr)
return 1
want = collect_includes(repo_root)
print(f"Collected {len(want)} unique #include <...> targets")
sdk_dirs = [
xwin_root / "crt" / "include",
xwin_root / "sdk" / "include" / "ucrt",
xwin_root / "sdk" / "include" / "um",
xwin_root / "sdk" / "include" / "shared",
xwin_root / "sdk" / "include" / "winrt",
]
total_created = 0
for d in sdk_dirs:
created, ok, _missing = fix_dir(d, want)
if created:
print(f" {d}: created {created} case-symlinks")
total_created += created
print(f"Done: created {total_created} case-symlinks total")
return 0
if __name__ == "__main__":
sys.exit(main())