"""Pinned Windows-x64 Vulkan build tools and app-local loader, no GPU execution. SDK copy-only mode does not install drivers or change system environment/registry. Checksums are from https://vulkan.lunarg.com/sdk/home/ (2026-10-12). """ import hashlib import json import os from pathlib import Path import platform import subprocess import urllib.request import uuid import zipfile ROOT = Path(__file__).resolve().parents[2] VERSION = "1.4.363.0" SDK_SHA = "94a82d378f7a5e3e54c9db7d2fb7016af136e14ac0a18dbf0f2f67a36352d141" LOADER_SHA = "a25a927aa8b9f0371048f1861cf88ac3b9bc9b1fb332c42d897c8ab32695769a" def digest(path): with path.open("rb") as stream: return hashlib.file_digest(stream, "sha256").hexdigest() def download(path, remote, expected, limit): if path.is_file() and digest(path) == expected: return temporary = path.with_suffix(path.suffix + ".partial") url = f"https://sdk.lunarg.com/sdk/download/{VERSION}/windows/{remote}?Human=true" try: request = urllib.request.Request(url, headers={"User-Agent": "searchi-build-tooling/1.0"}) with urllib.request.urlopen(request, timeout=120) as response, temporary.open("wb") as output: count = 0 while block := response.read(1024 * 1024): count += len(block) if count > limit: raise ValueError("Vulkan download exceeds size ceiling") output.write(block) if digest(temporary) != expected: raise ValueError("Vulkan download checksum mismatch") os.replace(temporary, path) finally: temporary.unlink(missing_ok=True) def sdk_files(sdk): required = [sdk / "Bin/glslc.exe", sdk / "Lib/vulkan-1.lib", sdk / "Include/vulkan/vulkan.h", sdk / "Include/vulkan/vulkan_core.h"] if not all(path.is_file() for path in required): raise RuntimeError("SDK copy did not provide required tools and headers") files = set(required) for directory in [sdk / "Include/vulkan", sdk / "Include/vk_video"]: files.update(path for path in directory.rglob("*") if path.is_file()) files.update((sdk / "Bin").glob("*.dll")) if len(files) > 4096: raise ValueError("Vulkan SDK manifest exceeds file count ceiling") return {path.relative_to(sdk).as_posix(): digest(path) for path in sorted(files)} def sdk_verified(sdk): manifest = sdk / "searchi-provenance.json" try: if manifest.stat().st_size > 1024 * 1024: return False value = json.loads(manifest.read_text(encoding="utf-8")) return (value.get("version") == VERSION and value.get("installer_sha256") == SDK_SHA and value.get("files") == sdk_files(sdk)) except (OSError, ValueError, RuntimeError, TypeError, AttributeError): return False def write_sdk_provenance(sdk): value = {"version": VERSION, "installer_sha256": SDK_SHA, "files": sdk_files(sdk)} temporary = sdk / "searchi-provenance.json.partial" try: temporary.write_text(json.dumps(value, sort_keys=True), encoding="utf-8") os.replace(temporary, sdk / "searchi-provenance.json") finally: temporary.unlink(missing_ok=True) def owned_path(directory, path): """Resolve and reject escaped/reparse targets before directory moves.""" owner = directory.resolve() target = path.resolve() if target == owner or not target.is_relative_to(owner): raise ValueError("Vulkan SDK path escapes owned toolchains directory") return target def install_sdk(directory, sdk, installer): # Qt's copy-only installer refuses an existing root. Use a fresh sibling, # validate it fully, then swap; preserve previous/failed trees for recovery. sdk = owned_path(directory, sdk) staging = owned_path(directory, directory / f"vulkan-sdk-{VERSION}-staging-{uuid.uuid4().hex}") backup = owned_path(directory, directory / f"vulkan-sdk-{VERSION}-backup-{uuid.uuid4().hex}") if staging.exists() or backup.exists(): raise RuntimeError("Generated Vulkan staging or backup directory already exists") environment = dict(os.environ, QT_OPENGL="software", SEARCHI_FORCE_CPU="1") subprocess.run([str(installer), "--root", str(staging), "--accept-licenses", "--default-answer", "--confirm-command", "install", "copy_only=1"], env=environment, check=True, creationflags=subprocess.CREATE_NO_WINDOW) write_sdk_provenance(staging) if not sdk_verified(staging): raise RuntimeError("Fresh Vulkan SDK failed provenance validation") # Re-resolve immediately before mutation; no recursive removal is performed. owned_path(directory, staging) owned_path(directory, sdk) owned_path(directory, backup) previous = sdk.exists() if previous: os.replace(sdk, backup) try: os.replace(staging, sdk) except OSError: if previous and not sdk.exists(): owned_path(directory, backup) owned_path(directory, sdk) os.replace(backup, sdk) raise def stage_loader(archive, loader): if digest(archive) != LOADER_SHA: raise ValueError("Vulkan runtime archive checksum mismatch") prefix = f"VulkanRT-X64-{VERSION}-Components/" members = [] with zipfile.ZipFile(archive) as package: for source, name in [("x64/vulkan-1.dll", "vulkan-1.dll"), ("VulkanRT-License.txt", "VULKAN-LICENSE.txt")]: member = package.getinfo(prefix + source) if member.file_size > 16 * 1024 * 1024: raise ValueError("Vulkan runtime member exceeds bound") with package.open(member) as stream: data = stream.read(16 * 1024 * 1024 + 1) if len(data) != member.file_size or len(data) > 16 * 1024 * 1024: raise ValueError("Vulkan runtime member exceeds bound or is truncated") members.append((name, data)) loader.mkdir(exist_ok=True) for name, data in members: destination = loader / name if destination.is_file() and digest(destination) == hashlib.sha256(data).hexdigest(): continue # Never rewrite a verified DLL mapped by another process. temporary = destination.with_suffix(destination.suffix + ".partial") try: temporary.write_bytes(data) os.replace(temporary, destination) finally: temporary.unlink(missing_ok=True) def provision(): if os.name != "nt" or platform.machine().lower() not in {"amd64", "x86_64"}: raise RuntimeError("Automatic Vulkan tooling provisioning is verified for Windows x64 only") directory = ROOT / ".searchi/toolchains" directory.mkdir(parents=True, exist_ok=True) sdk = directory / f"vulkan-sdk-{VERSION}" if not sdk_verified(sdk): installer = directory / f"vulkansdk-windows-X64-{VERSION}.exe" download(installer, installer.name, SDK_SHA, 400 * 1024 * 1024) install_sdk(directory, sdk, installer) archive = directory / f"VulkanRT-X64-{VERSION}-Components.zip" download(archive, "vulkan-runtime-components.zip", LOADER_SHA, 50 * 1024 * 1024) loader = directory / "vulkan-loader" stage_loader(archive, loader) return sdk, loader if __name__ == "__main__": sdk, loader = provision() print(f"Verified SDK: {sdk}\nApp-local loader: {loader}")