//! Generate the ordinal → export-name table that import resolution needs. //! //! 🔴 **THE SOURCE CHANGED, AND THE OLD ONE COULD FAIL SILENTLY.** In `xenia-rs` //! this parsed Canary's `xboxkrnl_table.inc` / `xam_table.inc` through a //! **relative path to a sibling checkout** — `../xenia-canary/src/…`. When that //! path was not there (a container, another machine, a fresh clone) it printed a //! `cargo:warning` and returned an empty table, and every import in the database //! came out unresolved. A build that quietly produces a worse artifact is the //! failure mode this project keeps meeting. //! //! The source is now `docs/reference/xbox360-exports.json`, which is **in this //! repository** — 2,913 exports across `xboxkrnl.exe`, `xam.xex` and `xbdm.xex`, //! adopted in Phase 2 of `docs/agents/CONSOLIDATION.md`. There is no sibling //! checkout to be missing, and if the file is unreadable this **fails the //! build** rather than degrading. use std::path::Path; use std::{env, fs, io::Write}; fn main() { let manifest = env::var("CARGO_MANIFEST_DIR").unwrap(); let json_path = Path::new(&manifest) .parent() .and_then(Path::parent) .unwrap() .join("docs/reference/xbox360-exports.json"); println!("cargo:rerun-if-changed={}", json_path.display()); let raw = fs::read_to_string(&json_path).unwrap_or_else(|e| { panic!( "sylpheed-xexdb: cannot read the export table at {} ({e}).\n\ Import names would all resolve to None and the database would be \ silently poorer, so this is a hard error rather than a warning.", json_path.display() ) }); let doc: serde_json::Value = serde_json::from_str(&raw).expect("export table is not valid JSON"); let out = Path::new(&env::var("OUT_DIR").unwrap()).join("ordinals.rs"); let mut f = fs::File::create(&out).unwrap(); writeln!( f, "/// Auto-generated from `docs/reference/xbox360-exports.json`." ) .unwrap(); writeln!( f, "pub fn resolve_ordinal(lib: &str, ordinal: u16) -> Option<&'static str> {{" ) .unwrap(); writeln!(f, " match lib {{").unwrap(); let mut total = 0usize; for (module, file) in [ ("xboxkrnl", "xboxkrnl.exe"), ("xam", "xam.xex"), ("xbdm", "xbdm.xex"), ] { writeln!(f, " \"{file}\" => match ordinal {{").unwrap(); let exports = doc["modules"][module]["exports"] .as_array() .unwrap_or_else(|| panic!("no exports array for module {module}")); for e in exports { let (Some(ord), Some(name)) = (e["ordinal"].as_u64(), e["name"].as_str()) else { continue; }; if ord > u16::MAX as u64 { continue; } writeln!(f, " 0x{ord:04X} => Some(\"{name}\"),").unwrap(); total += 1; } writeln!(f, " _ => None,\n }},").unwrap(); } writeln!(f, " _ => None,\n }}\n}}").unwrap(); // A count in the build log, so "the table is there" is observable rather // than assumed. 2,913 is what Phase 2 adopted. println!("cargo:warning=sylpheed-xexdb: {total} ordinals from xbox360-exports.json"); }