The shared marching-cubes mesher applies its 8-cell block proofs at step 2 for standalone shape contexts and skips density-grid fills outside certified-uniform blocks (plus a one-sample normal halo); mixed and unknown blocks still sample exactly. FI certified-air boxes 1,959 -> 14,119; FI LOD1 samples -63%. FI whole view 7.08 -> 5.61 s (-21%), moving p50 about -33%; SW unchanged. Geometry hashes identical (no version bump); proof audit 36.9 M samples, 0 violations, Clang and GCC. Source stamp now covers the standalone mesher copy. Research R21 (deepened): native Core cave generator design. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016dhxM43dnWvUu2B5Ph1iG1
113 lines
4.3 KiB
Python
113 lines
4.3 KiB
Python
#!/usr/bin/env python3
|
|
"""Build and verify the final-source manifest used by Linux executables."""
|
|
from __future__ import annotations
|
|
|
|
import argparse
|
|
import hashlib
|
|
from pathlib import Path
|
|
import sys
|
|
|
|
|
|
def sha256(data: bytes) -> str:
|
|
return hashlib.sha256(data).hexdigest()
|
|
|
|
|
|
def manifest_entries(root: Path, include_unreal: bool = False) -> list[tuple[str, bytes]]:
|
|
standalone = root / "Standalone"
|
|
files: set[Path] = set()
|
|
|
|
core = standalone / "Core"
|
|
for suffix in ("*.h", "*.hpp", "*.cpp", "*.txt"):
|
|
files.update(core.rglob(suffix))
|
|
|
|
source = standalone / "Source"
|
|
for suffix in ("*.h", "*.hpp", "*.cpp"):
|
|
files.update(source.glob(suffix))
|
|
|
|
# The standalone BuildLinux wrapper compiles the plugin mesher sources from this tree.
|
|
# Include their contents, not only the generated wrapper paths, in the executable stamp.
|
|
standalone_plugin_source = source / "VoxelForge"
|
|
for suffix in ("*.h", "*.hpp", "*.cpp", "*.inl"):
|
|
files.update(standalone_plugin_source.rglob(suffix))
|
|
|
|
for path in standalone.glob("Build*"):
|
|
if path.is_file():
|
|
files.add(path)
|
|
for suffix in ("*.cmake", "*.mk", "Makefile", "CMakeLists.txt"):
|
|
files.update(standalone.glob(suffix))
|
|
core_build = standalone / "Core"
|
|
for suffix in ("*.cmake", "*.mk", "Makefile", "CMakeLists.txt"):
|
|
files.update(core_build.glob(suffix))
|
|
helper = standalone / "Tools/verify/source_stamp.py"
|
|
if helper.is_file():
|
|
files.add(helper)
|
|
|
|
# Plugin sources listed in core_sources.txt are compiled into the Linux binaries, and their
|
|
# headers are included by Core, so the whole plugin Source tree is always part of the stamp.
|
|
plugin_source = root / "Source" / "VoxelForge"
|
|
for suffix in ("*.h", "*.hpp", "*.cpp", "*.inl"):
|
|
files.update(plugin_source.rglob(suffix))
|
|
compat = standalone / "Compat"
|
|
for suffix in ("*.h", "*.hpp", "*.cpp"):
|
|
files.update(compat.rglob(suffix))
|
|
|
|
if include_unreal:
|
|
for suffix in ("*.cs",):
|
|
files.update(plugin_source.rglob(suffix))
|
|
|
|
entries = [(path.relative_to(root).as_posix(), path.read_bytes())
|
|
for path in files if path.is_file()]
|
|
|
|
# BuildLinux creates one namespace wrapper per listed Core implementation.
|
|
# Include each exact generated wrapper as a virtual source input.
|
|
source_list = core / "core_sources.txt"
|
|
for raw in source_list.read_text(encoding="utf-8").splitlines():
|
|
name = raw.split("#", 1)[0].strip()
|
|
if not name or name == "Core/src/VoxelForgeCore.cpp":
|
|
continue
|
|
source_path = standalone / name
|
|
if not source_path.is_file():
|
|
raise SystemExit(f"missing source listed in Core/core_sources.txt: {name}")
|
|
wrapper_name = "vfcore_" + "".join(c if c.isalnum() else "_" for c in name)
|
|
wrapper = ('#include "CoreNamespacePreamble.h"\n'
|
|
"namespace vfcore::detail\n{\n"
|
|
f'#include "{source_path}"\n'
|
|
"}\n").encode("utf-8")
|
|
entries.append((f"generated/wrappers/{wrapper_name}.cpp", wrapper))
|
|
|
|
return sorted(entries, key=lambda item: item[0])
|
|
|
|
|
|
def rendered_manifest(root: Path, include_unreal: bool = False) -> bytes:
|
|
lines = [f"{sha256(data)} {name}" for name, data in
|
|
manifest_entries(root, include_unreal)]
|
|
return ("\n".join(lines) + "\n").encode("utf-8")
|
|
|
|
|
|
def source_stamp(root: Path, include_unreal: bool = False) -> str:
|
|
return sha256(rendered_manifest(root, include_unreal))
|
|
|
|
|
|
def main() -> int:
|
|
parser = argparse.ArgumentParser(description=__doc__)
|
|
parser.add_argument("command", choices=("stamp", "write-manifest"))
|
|
parser.add_argument("--root", type=Path,
|
|
default=Path(__file__).resolve().parents[3])
|
|
parser.add_argument("--output", type=Path)
|
|
parser.add_argument("--include-unreal-adapter", action="store_true")
|
|
args = parser.parse_args()
|
|
root = args.root.resolve()
|
|
manifest = rendered_manifest(root, args.include_unreal_adapter)
|
|
stamp = sha256(manifest)
|
|
if args.command == "write-manifest":
|
|
if args.output is None:
|
|
parser.error("write-manifest requires --output")
|
|
args.output.parent.mkdir(parents=True, exist_ok=True)
|
|
args.output.write_bytes(manifest)
|
|
print(stamp)
|
|
return 0
|
|
|
|
|
|
if __name__ == "__main__":
|
|
raise SystemExit(main())
|