Files
codex/third_party/voice/macos_runtime.py
Benjamin Carlsson a947db131b Add Bazel preparation for native voice runtimes (#43114)
## What changed

Add the manual `//third_party/voice:native_runtime` target for macOS and GNU Linux. It consumes the native prefix archive, validates the completed build receipt against the target and source manifest, inspects libraries, and prepares verified copies using the existing platform policies.

Record the build commit through Bazel workspace status and include it in runtime receipts. Reject invalid or ambiguous commit metadata and escaping library aliases. Keep macOS preparation local and allow the system `libc++.1.dylib` dependency.

## Testing

Add tests for receipt validation, inspection ordering and failures, invalid commit metadata, and escaping archive links. Add a macOS integration test for preparing real libraries from a sandbox-linked archive with native aliases and either an absent or empty output directory.

GitOrigin-RevId: 23717ab33d1d3da5fb0042c1cc8e8efcd333c386
2026-09-05 22:27:22 +00:00

169 lines
5.9 KiB
Python

"""Project a verified macOS prefix into a private, relocatable development runtime."""
import argparse
import os
from pathlib import Path
import re
import subprocess
import sys
# Import only this script's siblings, including under PYTHONSAFEPATH.
sys.path.insert(0, str(Path(__file__).resolve().parent))
from runtime import Binary as MachO
from runtime import PLUGINS, RuntimeFormat, digest, prepare, required_library_paths
SYSTEM_IMPORTS = frozenset(
{
"/usr/lib/libSystem.B.dylib",
"/usr/lib/libc++.1.dylib",
"/usr/lib/libobjc.A.dylib",
"/usr/lib/libiconv.2.dylib",
"/usr/lib/libresolv.9.dylib",
"/System/Library/Frameworks/AppKit.framework/Versions/C/AppKit",
"/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation",
"/System/Library/Frameworks/CoreServices.framework/Versions/A/CoreServices",
"/System/Library/Frameworks/Foundation.framework/Versions/C/Foundation",
}
)
def run(command):
return subprocess.check_output(
command, text=True, stderr=subprocess.STDOUT, timeout=30
)
def inspect(path, target):
cpu = {"aarch64-apple-darwin": "ARM64", "x86_64-apple-darwin": "X86_64"}[target]
try:
output = run(
[
"/usr/bin/xcrun",
"llvm-objdump",
"--macho",
"--universal-headers",
"--private-headers",
str(path),
]
)
except subprocess.CalledProcessError as error:
raise ValueError("LLVM rejected the Mach-O library") from error
header, *commands = re.split(r"(?m)^Load command [0-9]+\n", output)
match = re.fullmatch(
r"Mach header\n[^\n]+\nMH_MAGIC_64 +"
+ cpu
+ r" +\S+ +\S+ +DYLIB +(\d+) +(\d+) +[^\n]+\n",
header.removeprefix(str(path) + ":\n"),
)
if not match or len(commands) != int(match[1]) or int(match[2]) > 1024 * 1024:
raise ValueError(f"expected a thin {target} dylib with bounded load commands")
identities, imports, rpaths = [], [], []
for block in commands:
match = re.match(r" +cmd (\S+)\n +cmdsize ([0-9]+)\n", block)
if not match:
raise ValueError("unrecognized LLVM load-command output")
command = match[1]
if command in {
"LC_PREBOUND_DYLIB",
"LC_REEXPORT_DYLIB",
"LC_LAZY_LOAD_DYLIB",
"LC_LOAD_UPWARD_DYLIB",
"LC_DYLD_ENVIRONMENT",
"LC_DYLIB_CODE_SIGN_DRS",
"LC_LAZY_LOAD_DYLIB_INFO",
"?(0x0000003a)",
}:
raise ValueError(f"unsupported loader command: {command}")
if command not in {
"LC_ID_DYLIB",
"LC_LOAD_DYLIB",
"LC_LOAD_WEAK_DYLIB",
"LC_RPATH",
}:
continue
# Match the entire command to reject multiline names masquerading as metadata.
pattern = r" +path ([^\r\n]+) \(offset [0-9]+\)\n"
if command != "LC_RPATH":
pattern = (
r" +name ([^\r\n]+) \(offset [0-9]+\)\n"
r" +time stamp [^\n]+\n +current version [^\n]+\ncompatibility version [^\n]+\n"
)
value = re.fullmatch(pattern, block[match.end() :])
if not value:
raise ValueError(
"undeclared native dependency or unrecognized LLVM loader output"
)
if command == "LC_ID_DYLIB":
identities.append(value[1])
elif command == "LC_RPATH":
rpaths.append(value[1])
else:
imports.append(value[1])
if len(identities) != 1 or not re.fullmatch(
r"[A-Za-z0-9_+.-]+\.dylib", Path(identities[0]).name
):
raise ValueError("expected one valid native library identity")
return MachO(identities[0], tuple(imports), tuple(rpaths))
def finalize_copy(destination, metadata, dependency_paths):
identity = f"@rpath/{destination.name}"
command = ["/usr/bin/install_name_tool", "-id", identity]
imports = []
for dependency in metadata.imports:
rewritten = dependency
if dependency not in SYSTEM_IMPORTS:
rewritten = "@loader_path/" + os.path.relpath(
dependency_paths[dependency], destination.parent
)
command.extend(["-change", dependency, rewritten])
imports.append(rewritten)
for rpath in metadata.rpaths:
command.extend(["-delete_rpath", rpath])
run([*command, str(destination)])
# Development code signatures only; no identity, entitlement or trust-policy changes.
run(
[
"/usr/bin/codesign",
"--force",
"--sign",
"-",
"--timestamp=none",
str(destination),
]
)
run(["/usr/bin/codesign", "--verify", "--strict", str(destination)])
return MachO(identity, tuple(imports), ())
def project(prefix, receipts, target, output):
if sys.platform != "darwin" or target not in (
"aarch64-apple-darwin",
"x86_64-apple-darwin",
):
raise ValueError(
"runtime projection requires macOS and an explicit macOS target"
)
format = RuntimeFormat(
tuple(
Path(f"lib/gstreamer-1.0/libgst{name}.dylib") for name in sorted(PLUGINS)
),
SYSTEM_IMPORTS,
inspect,
finalize_copy,
required_libraries=tuple(
Path(path).name for path in required_library_paths(target)
),
)
prepare(prefix, receipts, target, output, format)
if __name__ == "__main__":
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("--prefix", type=Path, required=True)
parser.add_argument("--receipts", type=Path, required=True)
parser.add_argument("--target", required=True)
parser.add_argument("--output", type=Path, required=True)
args = parser.parse_args()
project(args.prefix, args.receipts, args.target, args.output)