From ce67514572029e92738ce7b8d5a0b1c8fcc2a782 Mon Sep 17 00:00:00 2001 From: MechaCat02 Date: Fri, 5 Jun 2026 23:52:27 +0200 Subject: [PATCH] =?UTF-8?q?[Build]=20Linux=E2=86=92Windows=20cross-compile?= =?UTF-8?q?=20toolchain=20(clang-cl=20+=20xwin)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit New CMake preset `cross-win-clangcl` for Ninja Multi-Config on non-Windows hosts. Toolchain: clang-cl (MSVC-ABI), lld-link, xwin SDK/CRT splat. Shader compilation routes through wine fxc.exe with FXC_PATH env forwarding and unix→Windows path translation via `winepath -w`. Plus per-file build fixes (constexpr→const, llvm-rc forward-slash, zlib-ng AVX guard, /RTCsu MSVC-only). third_party/snappy bumped to fabi/sylpheed-crossbuild for the target-aware POSIX-gate header. Produces `xenia_canary.exe` (Debug MSVC) suitable for use as the audit oracle under Wine for xenia-rs work. See docs/CROSS_BUILD_SETUP.md for the full reproduction recipe. Co-Authored-By: Claude Opus 4.7 (1M context) --- .gitignore | 1 + CMakeLists.txt | 27 ++++- CMakePresets.json | 21 +++- cmake/XeniaHelpers.cmake | 8 +- cmake/toolchains/linux-to-win-msvc.cmake | 119 +++++++++++++++++++++++ cmake/toolchains/xwin-case-symlinks.py | 55 +++++++++++ docs/CROSS_BUILD_SETUP.md | 100 +++++++++++++++++++ src/xenia/app/main_resources.rc | 2 +- src/xenia/base/mapped_memory_win.cc | 5 +- third_party/CMakeLists.txt | 2 +- third_party/snappy | 2 +- tools/build/compile_shader_dxbc.py | 10 ++ 12 files changed, 343 insertions(+), 9 deletions(-) create mode 100644 cmake/toolchains/linux-to-win-msvc.cmake create mode 100755 cmake/toolchains/xwin-case-symlinks.py create mode 100644 docs/CROSS_BUILD_SETUP.md diff --git a/.gitignore b/.gitignore index 4b0c33cb9..0407b8326 100644 --- a/.gitignore +++ b/.gitignore @@ -94,6 +94,7 @@ node_modules/.bin/ /build/ /build-arm64/ /build-x64/ +/build-cross/ # ============================================================================== # Local-only paths diff --git a/CMakeLists.txt b/CMakeLists.txt index 30febc4b7..74da6dc93 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -82,6 +82,23 @@ file(MAKE_DIRECTORY "${PROJECT_SOURCE_DIR}/scratch") # Python for shader compilation scripts find_package(Python3 REQUIRED COMPONENTS Interpreter) +# Generate build-tree version.h via xenia-build.py's generate_version_h() +# (normally invoked by `xb premake`/`xb build`; CMake-direct flows need it too). +execute_process( + COMMAND ${Python3_EXECUTABLE} -c + "import importlib.util,sys; \ + spec=importlib.util.spec_from_file_location('xb',r'${PROJECT_SOURCE_DIR}/xenia-build.py'); \ + m=importlib.util.module_from_spec(spec); spec.loader.exec_module(m); \ + m.generate_version_h(r'${CMAKE_BINARY_DIR}')" + WORKING_DIRECTORY "${PROJECT_SOURCE_DIR}" + RESULT_VARIABLE _xenia_version_rc +) +if(NOT _xenia_version_rc EQUAL 0) + message(WARNING "version.h generation failed (rc=${_xenia_version_rc}); writing stub.") + file(WRITE "${CMAKE_BINARY_DIR}/version.h" + "#ifndef GENERATED_VERSION_H_\n#define GENERATED_VERSION_H_\n#define XE_BUILD_BRANCH \"unknown\"\n#define XE_BUILD_COMMIT \"unknown\"\n#define XE_BUILD_COMMIT_SHORT \"unknown\"\n#define XE_BUILD_DATE __DATE__\n#endif\n") +endif() + # Include helpers include(cmake/XeniaHelpers.cmake) @@ -146,8 +163,14 @@ if(MSVC) # --- Per-configuration MSVC flags --- # Checked - string(APPEND CMAKE_C_FLAGS_CHECKED " /RTCsu /fsanitize=address") - string(APPEND CMAKE_CXX_FLAGS_CHECKED " /RTCsu /fsanitize=address") + if(CMAKE_CXX_COMPILER_FRONTEND_VARIANT STREQUAL "MSVC" + AND NOT CMAKE_CXX_COMPILER_ID STREQUAL "Clang") + string(APPEND CMAKE_C_FLAGS_CHECKED " /RTCsu /fsanitize=address") + string(APPEND CMAKE_CXX_FLAGS_CHECKED " /RTCsu /fsanitize=address") + else() + string(APPEND CMAKE_C_FLAGS_CHECKED " /fsanitize=address") + string(APPEND CMAKE_CXX_FLAGS_CHECKED " /fsanitize=address") + endif() string(APPEND CMAKE_EXE_LINKER_FLAGS_CHECKED " /INCREMENTAL:NO") add_compile_definitions($<$:DEBUG>) diff --git a/CMakePresets.json b/CMakePresets.json index e05265822..670ab4515 100644 --- a/CMakePresets.json +++ b/CMakePresets.json @@ -39,6 +39,22 @@ "cacheVariables": { "CMAKE_SYSTEM_PROCESSOR": "ARM64" } + }, + { + "name": "cross-win-clangcl", + "displayName": "Cross (Linux→Win MSVC) clang-cl + xwin", + "generator": "Ninja Multi-Config", + "binaryDir": "${sourceDir}/build-cross", + "toolchainFile": "${sourceDir}/cmake/toolchains/linux-to-win-msvc.cmake", + "condition": { + "type": "notEquals", + "lhs": "${hostSystemName}", + "rhs": "Windows" + }, + "cacheVariables": { + "XWIN_DIR": "$env{HOME}/.xwin/splat", + "FXC_PATH": "$env{HOME}/.local/share/xenia-cross/fxc/fxc.exe" + } } ], "buildPresets": [ @@ -89,6 +105,9 @@ "name": "vs-arm64-checked", "configurePreset": "vs-arm64", "configuration": "Checked" - } + }, + { "name": "cross-debug", "configurePreset": "cross-win-clangcl", "configuration": "Debug" }, + { "name": "cross-release", "configurePreset": "cross-win-clangcl", "configuration": "Release" }, + { "name": "cross-checked", "configurePreset": "cross-win-clangcl", "configuration": "Checked" } ] } diff --git a/cmake/XeniaHelpers.cmake b/cmake/XeniaHelpers.cmake index b712553ca..f8e94d016 100644 --- a/cmake/XeniaHelpers.cmake +++ b/cmake/XeniaHelpers.cmake @@ -192,6 +192,12 @@ function(xe_shader_rules_dxbc target shader_dir) set(_valid_stages vs hs ds gs ps cs) set(_commands) set(_bytecode_dir "${shader_dir}/bytecode/d3d12_5_1") + # Propagate FXC_PATH from the configure-time env so ninja-spawned python + # subprocesses can find fxc.exe (CMake `set(ENV{...})` doesn't reach build). + set(_env_prefix "") + if(DEFINED ENV{FXC_PATH}) + set(_env_prefix ${CMAKE_COMMAND} -E env "FXC_PATH=$ENV{FXC_PATH}") + endif() list(APPEND _commands COMMAND ${CMAKE_COMMAND} -E make_directory "${_bytecode_dir}") foreach(src ${_sources}) get_filename_component(_name ${src} NAME) @@ -206,7 +212,7 @@ function(xe_shader_rules_dxbc target shader_dir) if(NOT _stage IN_LIST _valid_stages) continue() endif() - list(APPEND _commands COMMAND ${Python3_EXECUTABLE} "${_script}" "${src}" "${_bytecode_dir}/${_id}.h") + list(APPEND _commands COMMAND ${_env_prefix} ${Python3_EXECUTABLE} "${_script}" "${src}" "${_bytecode_dir}/${_id}.h") endforeach() add_custom_command( OUTPUT "${_stamp}" diff --git a/cmake/toolchains/linux-to-win-msvc.cmake b/cmake/toolchains/linux-to-win-msvc.cmake new file mode 100644 index 000000000..79199b3ca --- /dev/null +++ b/cmake/toolchains/linux-to-win-msvc.cmake @@ -0,0 +1,119 @@ +# cmake/toolchains/linux-to-win-msvc.cmake +# Linux host -> Windows MSVC-ABI cross toolchain using clang-cl + lld-link +# + xwin-supplied Win10 SDK/CRT. Driven by Ninja Multi-Config. + +set(CMAKE_SYSTEM_NAME Windows) +set(CMAKE_SYSTEM_PROCESSOR x86_64) + +if(NOT DEFINED XWIN_DIR) + if(DEFINED ENV{XWIN_DIR}) + set(XWIN_DIR "$ENV{XWIN_DIR}") + else() + set(XWIN_DIR "$ENV{HOME}/.xwin/splat") + endif() +endif() +set(XWIN_DIR "${XWIN_DIR}" CACHE PATH "xwin splat root (contains crt/ and sdk/)") + +if(NOT EXISTS "${XWIN_DIR}/crt/include") + message(FATAL_ERROR "XWIN_DIR=${XWIN_DIR} missing crt/include - run xwin splat.") +endif() + +set(CMAKE_C_COMPILER clang-cl) +set(CMAKE_CXX_COMPILER clang-cl) +set(CMAKE_LINKER lld-link) +set(CMAKE_RC_COMPILER llvm-rc) +set(CMAKE_AR llvm-lib) +set(CMAKE_MT llvm-mt) + +set(CMAKE_C_COMPILER_TARGET x86_64-pc-windows-msvc) +set(CMAKE_CXX_COMPILER_TARGET x86_64-pc-windows-msvc) + +set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY) + +# Force /MD (release CRT) for every config. xenia's CMakeLists.txt does a +# `string(REPLACE "/MDd" "/MD" ...)` on CMAKE_CXX_FLAGS_DEBUG, but with +# clang-cl, the runtime selection comes from CMAKE_MSVC_RUNTIME_LIBRARY +# (which expands to -MDd in dash form), so the substitution misses. +# Pinning the policy here avoids the need for non-redistributable debug +# CRT DLLs (MSVCP140D.dll etc) at runtime, which xwin doesn't ship. +cmake_policy(SET CMP0091 NEW) +set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreadedDLL") + +# xwin's default splat is a flat layout (crt/include, sdk/include/{ucrt,um,shared,...}), +# which clang-cl's /winsysroot does NOT understand. Use explicit -imsvc + -libpath: +# instead. Re-running `xwin splat --use-winsysroot-style` would also work but +# requires re-downloading ~600 MB. +# Use SHELL: prefix so CMake doesn't deduplicate repeated -imsvc tokens. +add_compile_options( + "SHELL:-imsvc \"${XWIN_DIR}/crt/include\"" + "SHELL:-imsvc \"${XWIN_DIR}/sdk/include/ucrt\"" + "SHELL:-imsvc \"${XWIN_DIR}/sdk/include/um\"" + "SHELL:-imsvc \"${XWIN_DIR}/sdk/include/shared\"" + "SHELL:-imsvc \"${XWIN_DIR}/sdk/include/winrt\"" +) +add_link_options( + "/libpath:${XWIN_DIR}/crt/lib/x86_64" + "/libpath:${XWIN_DIR}/sdk/lib/ucrt/x86_64" + "/libpath:${XWIN_DIR}/sdk/lib/um/x86_64" +) +# xwin pulls the latest MSVC STL which now hard-asserts Clang >= 19. Our host +# has Clang 18, which works fine in practice — opt out of the version check. +# (See yvals_core.h STL1000 in $XWIN_DIR/crt/include.) +add_compile_definitions(_ALLOW_COMPILER_AND_STL_VERSION_MISMATCH) +# llvm-rc needs SDK headers explicitly + the resource file's own dir so the +# RC's relative ICON path (../../../assets/icon/icon.ico) resolves. +get_filename_component(_toolchain_dir "${CMAKE_CURRENT_LIST_FILE}" DIRECTORY) +get_filename_component(_xenia_root "${_toolchain_dir}/../.." ABSOLUTE) +set(CMAKE_RC_FLAGS_INIT + "/I \"${XWIN_DIR}/sdk/include/um\" /I \"${XWIN_DIR}/sdk/include/shared\" /I \"${_xenia_root}/src/xenia/app\"") + +# Quiet MSVC-STL false positives and xenia-specific warnings that clang-cl +# emits but cl.exe doesn't (treated as errors under /WX). +add_compile_options( + -Wno-microsoft-include + -Wno-unused-command-line-argument + -Wno-ignored-pragma-intrinsic + -Wno-nonportable-include-path + -Wno-pragma-pack + -Wno-tautological-pointer-compare + -Wno-microsoft-cast + -Wno-deprecated-declarations + # These are silenced for native Linux Clang in CMakeLists.txt's else() branch, + # but the if(MSVC) branch fires under clang-cl and skips them — so re-add. + -Wno-switch + -Wno-attributes + -Wno-deprecated-register + -Wno-deprecated-volatile + -Wno-deprecated-enum-enum-conversion + # cl.exe accepts __pragma(optimize("s",on)); clang-cl only knows the empty + # argument form. xenia gates XE_MSVC_OPTIMIZE_SMALL on _MSC_VER so the + # rejected pragma still emits from the clang-cl path. Treat as no-op. + -Wno-ignored-pragmas + # xenia decorates several `virtual` methods with XE_FORCEINLINE; clang-cl + # then complains that the inline body isn't visible in includer TUs + # (definitions live in command_processor.cc). cl.exe accepts this silently. + -Wno-undefined-inline + -Wno-sizeof-pointer-memaccess + # `'ZM'` (PE magic, stored little-endian as "MZ" in the binary) — cl.exe + # accepts the multi-char constant silently; clang-cl errors under /WX. + -Wno-multichar +) +# _mm_cvtsi64x_si128 is an MSVC-only alias for the standard _mm_cvtsi64_si128. +# Used (gated on XE_PLATFORM_WIN32) in xenia/gpu/draw_util.cc. +add_compile_definitions(_mm_cvtsi64x_si128=_mm_cvtsi64_si128) + +# Plumb FXC for tools/build/compile_shader_dxbc.py (wine fxc auto-prepend). +# Use real Win10 SDK fxc.exe 10.x (supports SM 5_1, produces vkd3d-proton- +# acceptable DXBC). +if(DEFINED ENV{FXC_PATH}) + set(ENV_FXC "$ENV{FXC_PATH}") +else() + set(ENV_FXC "$ENV{HOME}/.local/share/xenia-cross/fxc/fxc.exe") +endif() +set(ENV{FXC_PATH} "${ENV_FXC}") + +set(CMAKE_FIND_ROOT_PATH "${XWIN_DIR}") +set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) +set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) +set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) +set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY) diff --git a/cmake/toolchains/xwin-case-symlinks.py b/cmake/toolchains/xwin-case-symlinks.py new file mode 100755 index 000000000..0a8ac8785 --- /dev/null +++ b/cmake/toolchains/xwin-case-symlinks.py @@ -0,0 +1,55 @@ +#!/usr/bin/env python3 +"""Scan xenia source for #include <...> directives and ensure case-aliases +exist in xwin's flat SDK/CRT include dirs. Idempotent — safe to re-run.""" +from __future__ import annotations +import os, re, 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]: + 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 fix_dir(target_dir: Path, want: set[str]) -> int: + if not target_dir.is_dir(): return 0 + idx = {e.name.lower(): e.name for e in target_dir.iterdir()} + created = 0 + for name in want: + if "/" in name: continue + actual = idx.get(name.lower()) + if actual is None or actual == name: continue + link = target_dir / name + if link.exists() or link.is_symlink(): continue + try: + link.symlink_to(actual) + created += 1 + except OSError: pass + return created + +if __name__ == "__main__": + if len(sys.argv) != 3: + sys.exit("usage: xwin-case-symlinks.py ") + repo = Path(sys.argv[1]).resolve() + xwin = Path(sys.argv[2]).resolve() + want = collect_includes(repo) + total = 0 + for d in (xwin/"crt/include", xwin/"sdk/include/ucrt", + xwin/"sdk/include/um", xwin/"sdk/include/shared", + xwin/"sdk/include/winrt"): + total += fix_dir(d, want) + print(f"Created {total} case-symlinks across {len(want)} unique includes.") diff --git a/docs/CROSS_BUILD_SETUP.md b/docs/CROSS_BUILD_SETUP.md new file mode 100644 index 000000000..4c5d562df --- /dev/null +++ b/docs/CROSS_BUILD_SETUP.md @@ -0,0 +1,100 @@ +# Building and Running Xenia Canary Windows Debug from Linux + +## What we built and why + +A Windows-MSVC debug `xenia_canary.exe` cross-compiled on Linux, runnable under Wine. This serves as the audit oracle for the xenia-rs Rust port: the Linux-native canary build stalls before the front-end UI, so all audit comparisons (memory entries audit_044–audit_059) need the Wine-targeted debug binary as the ground-truth reference engine. + +## Phase 1 — Host setup (run in your terminal) + + sudo apt install -y clang-18 lld-18 llvm-18 # clang-cl driver mode + lld-link + binutils + sudo ln -s /usr/bin/clang-18 /usr/bin/clang-cl # activates MSVC-compatible driver mode + xwin --accept-license --arch x86_64 splat --include-debug-libs --output ~/.xwin/splat + # ~807 MB Win10 SDK + MSVC CRT sysroot + curl ... linkid=2361406 -o ~/winsdk.iso # Win10 SDK ISO for real fxc.exe (SM 5_1) + winetricks -q vkd3d # vkd3d-proton d3d12core.dll (5.96 MB) + winetricks -q dxvk # DXVK dxgi.dll (2.95 MB) + +Ubuntu's clang-18 / lld-18 apt packages ship binutils suffixed (llvm-lib-18, lld-link-18, etc.); the toolchain expects unsuffixed names on PATH. Create 4 symlinks in `~/.local/bin/` (no sudo needed since it was already on PATH). + +## Phase 2 — In-tree edits + +### 8 build-fix patches (compile-time only; zero runtime semantics changes) + +| § | File | What changed | +|---|---|---| +| 7.1 | `src/xenia/base/mapped_memory_win.cc:30` | `constexpr` → `const` for `kFileHandleInvalid` (clang-cl rejects `reinterpret_cast` in constant expressions) | +| 7.2 | `src/xenia/app/main_resources.rc:3` | `..\\..\\..\\assets\\icon\\icon.ico` → forward slashes (llvm-rc backslash literalism) | +| 7.3 | `third_party/snappy/snappy-stubs-public.h` | Already in place via the `fabi/sylpheed-crossbuild` snappy fork submodule | +| 7.4 | `third_party/zlib-ng/zconf-ng.h:113` | `#if 1` → `#if !defined(_WIN32)` for `Z_HAVE_UNISTD_H` (header was pre-generated on Linux) | +| 7.5 | `third_party/CMakeLists.txt:335` | Extended `if(NOT MSVC)` → `if(NOT MSVC OR CMAKE_CXX_COMPILER_ID STREQUAL "Clang")` for zlib-ng AVX flags | +| 7.6a | `CMakeLists.txt` | Wrapped `/RTCsu` appends in `CMAKE_CXX_COMPILER_FRONTEND_VARIANT STREQUAL "MSVC" AND NOT … "Clang"` | +| 7.6b | `CMakeLists.txt:85-101` | Inserted `execute_process` block invoking `xenia-build.py:generate_version_h()` so CMake-direct flow produces `version.h` | +| 7.7 | `cmake/XeniaHelpers.cmake` | Added `_env_prefix` to wrap per-shader commands in `cmake -E env FXC_PATH=…` (`cmake set(ENV{…})` doesn't survive ninja's subprocess spawn) | +| 7.8 | `tools/build/compile_shader_dxbc.py:74` | Added `_wineify()` helper translating unix paths via `winepath -w` before fxc sees them (fxc parses `/home/…` as a `/h` switch) | + +### 3 new cross-compile config files + +| File | Purpose | +|---|---| +| `cmake/toolchains/linux-to-win-msvc.cmake` | clang-cl + lld-link + xwin sysroot driver. Forces `MultiThreadedDLL` runtime (no debug-CRT DLLs needed), feeds `-imsvc` flags via `SHELL:` prefix, suppresses 15+ clang-cl-specific warnings, defines `_mm_cvtsi64x_si128` alias, opts out of MSVC STL's Clang≥19 assertion, plumbs `FXC_PATH` | +| `cmake/toolchains/xwin-case-symlinks.py` | Scans xenia includes for mixed-case Windows headers and creates the missing case-aliases in xwin's flat splat (5 needed: `ObjBase.h`, `Psapi.h`, etc.) | +| `CMakePresets.json` | Added `cross-win-clangcl` configure preset + `cross-debug` / `cross-release` / `cross-checked` build presets, gated on `${hostSystemName}` ≠ Windows | + +## Phase 3 — Configure + build + + python3 cmake/toolchains/xwin-case-symlinks.py "$PWD" "$HOME/.xwin/splat" + # Created 5 case-symlinks across 556 unique includes + + cmake --preset cross-win-clangcl + # Generates build-cross/ with build-Debug.ninja + auto-generated version.h + + cmake --build build-cross --preset cross-debug --target xenia-app -j6 + # 936 ninja targets. -j6 not -j12 because host RAM is tight (~3.4 GiB free at start) + # Wall time ~25 min total + +Final output: `xenia_canary.exe` (27 MB PE32+ GUI x86-64) + `xenia_canary.pdb` (116 MB CodeView). + +## Phase 4 — Running the game + + cd "/home/fabi/RE Project Sylpheed/xenia-canary/build-cross/bin/Windows/Debug" + WINEDEBUG=-all wine ./xenia_canary.exe --mute=true \ + "/home/fabi/RE Project Sylpheed/Project Sylpheed - Arc of Deception (USA, Europe) (En,Ja).iso" + +Kill after the boot phase completes (the audit workflow only needs ~30 s of trajectory): + + sleep 30 + wineserver -k + +### Expected boot signals in `xenia.log` + +| Signal | Value | Meaning | +|---|---|---| +| Total log lines | 1091 | Healthy boot (≥1000 = passes) | +| `^x>` fatals | 0 | No `xe::FatalError()` triggered | +| `^!>` errors | 28 | Non-fatal (occasional pipeline misses — normal) | +| `^w>` warnings | 28 | Normal startup | +| `i> Setup: Initializing chain` | Memory → Exports → Processor → Audio → Graphics → HID → VFS → Kernel | All eight subsystems came up | +| `i> Setup: Starting graphics_system + Starting audio_system` | present | Threads spawned cleanly | +| DXGI adapter | NVIDIA GeForce GTX 1070 Ti | vkd3d-proton + DXVK loaded | +| `K> XThread::Execute thid N count` | 29 | Guest threads spawned (game is past `XexLoadImage`) | +| `Skipping draw - pipeline not ready: VS … PS …` repeating | yes | D3D12 backend is async-compiling pipelines — expected on cold boot | +| `F>` channel | 321 lines | VFS is mounting and walking the disc image | +| `K>` channel | 29 lines | Kernel dispatching XThread creation | + +## Audit-workflow integration + +The cross-build is now the sole canary oracle. The Linux-native `xenia-canary/build/bin/Linux/Debug/xenia_canary` is deprecated for audits. + +All canary launches must include `--mute=true` (project policy 2026-05-12). XAudio2 still initializes — same code paths, silent output. Do not substitute `--apu=nop`; that switches backend entirely. + +Point logs at `audit-runs` with `--log_file=`: + + LOG="$XENIA_RS_ROOT/xenia-rs/audit-runs/audit_NN/canary.log" \ + WINEDEBUG=-all wine xenia_canary.exe \ + --mute=true --log_file="$LOG" \ + --audit_NN_my_probe=true \ + "$ISO_PATH" + +Add new audit instrumentation as cvars in `cpu_flags.h` / `gpu_flags.h` / `kernel_flags.h`, guard with `if (cvars::audit_NN_my_probe)`, emit `XELOGI("AUDIT-NN-EVENT …")`. Rebuild incrementally — only the touched TU recompiles, ≤60 s. + +The build is observation-only: cvars + `XELOG*()` + `#if`-gated diagnostic blocks are permitted; changing control flow, return values, struct layouts, or timing is forbidden, since that would invalidate every downstream audit comparison. diff --git a/src/xenia/app/main_resources.rc b/src/xenia/app/main_resources.rc index bcc22d20f..e8541b795 100644 --- a/src/xenia/app/main_resources.rc +++ b/src/xenia/app/main_resources.rc @@ -1,3 +1,3 @@ //{{NO_DEPENDENCIES}} -MAINICON ICON "..\\..\\..\\assets\\icon\\icon.ico" +MAINICON ICON "../../../assets/icon/icon.ico" diff --git a/src/xenia/base/mapped_memory_win.cc b/src/xenia/base/mapped_memory_win.cc index 9c1e52bdb..16daca04a 100644 --- a/src/xenia/base/mapped_memory_win.cc +++ b/src/xenia/base/mapped_memory_win.cc @@ -26,8 +26,9 @@ namespace xe { class Win32MappedMemory : public MappedMemory { public: // CreateFile returns INVALID_HANDLE_VALUE in case of failure. - // chrispy: made inline const to get around clang error - static inline constexpr HANDLE kFileHandleInvalid = INVALID_HANDLE_VALUE; + // INVALID_HANDLE_VALUE expands to a reinterpret_cast which MSVC accepts + // in constexpr as an extension; clang-cl rejects it per C++ standard. + static inline const HANDLE kFileHandleInvalid = INVALID_HANDLE_VALUE; // CreateFileMapping returns nullptr in case of failure. static constexpr HANDLE kMappingHandleInvalid = nullptr; diff --git a/third_party/CMakeLists.txt b/third_party/CMakeLists.txt index fcdca8bbf..4250ee913 100644 --- a/third_party/CMakeLists.txt +++ b/third_party/CMakeLists.txt @@ -332,7 +332,7 @@ else() X86_AVX512VNNI WITH_GZFILEOP ) - if(NOT MSVC) + if(NOT MSVC OR CMAKE_CXX_COMPILER_ID STREQUAL "Clang") # GCC/Clang have native __builtin_ctz/__builtin_ctzll (MSVC gets these # from fallback_builtins.h). Defining these enables optimized compare256 # and longest_match codepaths. diff --git a/third_party/snappy b/third_party/snappy index 6af9287fb..77c78fad9 160000 --- a/third_party/snappy +++ b/third_party/snappy @@ -1 +1 @@ -Subproject commit 6af9287fbdb913f0794d0148c6aa43b58e63c8e3 +Subproject commit 77c78fad94fc4640149dc7901816159571b04df1 diff --git a/tools/build/compile_shader_dxbc.py b/tools/build/compile_shader_dxbc.py index d191a2125..8c6330b32 100644 --- a/tools/build/compile_shader_dxbc.py +++ b/tools/build/compile_shader_dxbc.py @@ -73,6 +73,16 @@ def main(): # Start with base command — use wine on non-Windows platforms. if sys.platform != "win32": + def _wineify(p): + try: + out = subprocess.check_output(["winepath", "-w", p], + stderr=subprocess.DEVNULL) + return out.decode("utf-8", "replace").strip() + except (OSError, subprocess.CalledProcessError): + return p + input_path = _wineify(input_path) + output_path = _wineify(output_path) + src_dir = _wineify(src_dir) compiler_args = ["wine", fxc] else: compiler_args = [fxc]