Add Bazel preparation for native voice runtimes (#43114) · just-every/code@a947db1 · GitHub
Skip to content

Commit a947db1

Browse files
bc-openaicopyberry
authored andcommitted
Add Bazel preparation for native voice runtimes (openai#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
1 parent fc748ab commit a947db1

9 files changed

Lines changed: 421 additions & 0 deletions

File tree

‎.bazelrc‎

Lines changed: 4 additions & 0 deletions

‎scripts/workspace-status.cmd‎

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
@echo off
2+
setlocal
3+
4+
if defined STABLE_GIT_COMMIT (
5+
echo STABLE_GIT_COMMIT %STABLE_GIT_COMMIT%
6+
exit /b 0
7+
)
8+
9+
for /f "delims=" %%I in ('git rev-parse --verify HEAD 2^>nul') do set "BUILD_COMMIT=%%I"
10+
if defined BUILD_COMMIT (
11+
echo STABLE_GIT_COMMIT %BUILD_COMMIT%
12+
exit /b 0
13+
)
14+
15+
if defined GITHUB_SHA (
16+
echo STABLE_GIT_COMMIT %GITHUB_SHA%
17+
exit /b 0
18+
)
19+
20+
echo STABLE_GIT_COMMIT unknown

‎scripts/workspace-status.sh‎

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
#!/usr/bin/env bash
2+
3+
set -euo pipefail
4+
5+
if [[ -n "${STABLE_GIT_COMMIT:-}" ]]; then
6+
build_commit="${STABLE_GIT_COMMIT}"
7+
elif build_commit="$(git rev-parse --verify HEAD 2>/dev/null)"; then
8+
:
9+
elif [[ -n "${GITHUB_SHA:-}" ]]; then
10+
build_commit="${GITHUB_SHA}"
11+
else
12+
build_commit="unknown"
13+
fi
14+
15+
printf 'STABLE_GIT_COMMIT %s\n' "${build_commit}"

‎third_party/voice/BUILD.bazel‎

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
load("@rules_foreign_cc//toolchains/native_tools:native_tools_toolchain.bzl", "native_tool_toolchain")
22
load(":native.bzl", "native_prefix")
33
load(":pkg_config.bzl", "pkg_config")
4+
load(":runtime.bzl", "native_runtime")
45

56
# All native build consumers must receive the same pinned source manifest.
67
exports_files(["opus-toolchain.cmake"])
@@ -177,3 +178,31 @@ alias(
177178
tags = ["manual"],
178179
visibility = ["//visibility:public"],
179180
)
181+
182+
[
183+
native_runtime(
184+
name = "native_runtime_" + os + "_" + cpu,
185+
exec_compatible_with = [
186+
"@platforms//os:" + os,
187+
"@platforms//cpu:" + cpu,
188+
],
189+
prefix = ":native_prefix_" + os + "_" + cpu,
190+
tags = ["manual"],
191+
target = cpu + "-" + suffix,
192+
target_compatible_with = select({
193+
":" + os + "_" + cpu: [],
194+
"//conditions:default": ["@platforms//:incompatible"],
195+
}),
196+
)
197+
for os, cpu, suffix in _NATIVE_PLATFORMS
198+
]
199+
200+
alias(
201+
name = "native_runtime",
202+
actual = select({
203+
":" + os + "_" + cpu: ":native_runtime_" + os + "_" + cpu
204+
for os, cpu, _ in _NATIVE_PLATFORMS
205+
}),
206+
tags = ["manual"],
207+
visibility = ["//visibility:public"],
208+
)

‎third_party/voice/README.md‎

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,18 @@ preparation or shipped in the runtime. The output is development-only, uses the
183183
host glibc, and does not establish musl or minimum-glibc support, dynamic-only
184184
dependency closure, helper loading policy or working voice.
185185

186+
## Prepare Bazel's native build output
187+
188+
`bazel build //third_party/voice:native_runtime` prepares the selected Mac or GNU
189+
Linux prefix archive using the existing platform inspection and preparation code.
190+
It checks the completed build receipt, records the current workspace build commit,
191+
inspects physical libraries, and prepares verified copies. These receipts describe
192+
build inputs and inspection; they are not signatures or release approval.
193+
194+
This manual target requires the same host inspection/signing tools as the standalone
195+
platform preparer. It does not link Rust, change Windows builds, assemble a CLI
196+
package, or enable voice. The prepared runtime is the input to those later steps.
197+
186198
## Private Windows runtime preparation
187199

188200
`windows_runtime.py` takes the same arguments for x64/ARM64 MSVC build prefixes.

‎third_party/voice/macos_runtime.py‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
SYSTEM_IMPORTS = frozenset(
1616
{
1717
"/usr/lib/libSystem.B.dylib",
18+
"/usr/lib/libc++.1.dylib",
1819
"/usr/lib/libobjc.A.dylib",
1920
"/usr/lib/libiconv.2.dylib",
2021
"/usr/lib/libresolv.9.dylib",
Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
"""Prepare an inspected build output using the existing platform runtime policy.
2+
3+
Receipts describe the declared build inputs and inspection, not authenticity or
4+
approval. The current build commit comes from Bazel's workspace status file.
5+
"""
6+
7+
import argparse
8+
import importlib
9+
import json
10+
from pathlib import Path
11+
import re
12+
import sys
13+
import tarfile
14+
import tempfile
15+
16+
sys.path.insert(0, str(Path(__file__).resolve().parent))
17+
from runtime import digest
18+
19+
20+
def prepare_built(prefix, build_receipt, status, target, output):
21+
prefix = prefix.resolve(strict=True)
22+
if build_receipt.stat().st_size > 1024 * 1024 or status.stat().st_size > 65536:
23+
raise ValueError("native build metadata exceeds limits")
24+
build = json.loads(build_receipt.read_text())
25+
commits = [
26+
line.removeprefix("STABLE_GIT_COMMIT ")
27+
for line in status.read_text().splitlines()
28+
if line.startswith("STABLE_GIT_COMMIT ")
29+
]
30+
manifest_hash = digest(Path(__file__).with_name("sources.json"))
31+
steps = build.get("steps", [])
32+
if (
33+
len(commits) != 1
34+
or not re.fullmatch(r"[0-9a-f]{40}", commits[0])
35+
or build.get("target") != target
36+
or build.get("manifest_sha256") != manifest_hash
37+
or not 1 <= len(steps) <= 128
38+
or any(step.get("exit_code") != 0 for step in steps)
39+
or steps[-1].get("name") != "gst-plugins-good-install"
40+
):
41+
raise ValueError("native build receipt is incomplete or mismatched")
42+
suffix = target.partition("-")[2]
43+
modules = {
44+
"apple-darwin": "macos_runtime",
45+
"unknown-linux-gnu": "linux_runtime",
46+
"pc-windows-msvc": "windows_runtime",
47+
}
48+
if suffix not in modules or target.partition("-")[0] not in ("aarch64", "x86_64"):
49+
raise ValueError("unsupported native runtime target")
50+
platform = importlib.import_module(modules[suffix])
51+
records = []
52+
for path in sorted(prefix.rglob("*")):
53+
if not re.fullmatch(r".+\.(?:dylib|dll|so(?:\.[0-9]+)*)", path.name):
54+
continue
55+
if path.is_symlink():
56+
if not path.resolve(strict=True).is_relative_to(prefix):
57+
raise ValueError("native library link escapes its prefix")
58+
continue
59+
if not path.is_file():
60+
continue
61+
if len(records) >= 128:
62+
raise ValueError("native inventory exceeds limits")
63+
platform.inspect(path, target)
64+
records.append(
65+
{
66+
"path": path.relative_to(prefix).as_posix(),
67+
"target": target,
68+
"sha256": digest(path),
69+
}
70+
)
71+
if not records:
72+
raise ValueError("native prefix contains no libraries")
73+
with tempfile.TemporaryDirectory(prefix="voice-receipts-") as temporary:
74+
receipts = Path(temporary)
75+
(receipts / "inspection").mkdir()
76+
(receipts / "inspection/binaries.json").write_text(json.dumps(records))
77+
(receipts / "ci.json").write_text(
78+
json.dumps(
79+
{
80+
"commit": commits[0],
81+
"target": target,
82+
"manifest_sha256": manifest_hash,
83+
"build_complete": True,
84+
"inspection_complete": True,
85+
}
86+
)
87+
)
88+
platform.project(prefix, receipts, target, output)
89+
90+
91+
def prepare_archive(archive, build_receipt, status, target, output):
92+
# Archives preserve native aliases through Bazel's cache and sandbox links.
93+
with tempfile.TemporaryDirectory(prefix="voice-prefix-") as temporary:
94+
prefix = Path(temporary)
95+
with tarfile.open(archive) as source:
96+
source.extractall(prefix, filter="data")
97+
prepare_built(prefix, build_receipt, status, target, output)
98+
99+
100+
if __name__ == "__main__":
101+
parser = argparse.ArgumentParser(description=__doc__)
102+
for name in ("prefix", "build-receipt", "status", "output"):
103+
parser.add_argument("--" + name, type=Path, required=True)
104+
parser.add_argument("--target", required=True)
105+
args = parser.parse_args()
106+
# Executors may leave the TreeArtifact absent or create an empty directory.
107+
try:
108+
args.output.rmdir()
109+
except FileNotFoundError:
110+
pass
111+
prepare_archive(
112+
args.prefix, args.build_receipt, args.status, args.target, args.output
113+
)

‎third_party/voice/runtime.bzl‎

Lines changed: 46 additions & 0 deletions

0 commit comments

Comments
 (0)