Files
codex/scripts/codex_package/cargo.py
Channing Conger 014f19af5f ci: Use codex produced v8 artifacts for release builds (#23934)
Updates our build script to pull down the artifacts like we do in CI for
building v8 into our targets.

This changes the flow so that we now pre-install rusty v8 assets for all
of our release targets from pre-built in workflow.
Secondarily if running it locally we now optionally pull the assets down
on python run assuming the user hasn't set the proper values, it then
provides them.

Sorry for the miss here.
2026-05-22 09:42:08 -07:00

182 lines
5.3 KiB
Python

"""Cargo builds for source-built Codex package artifacts."""
import os
import subprocess
from dataclasses import dataclass
from pathlib import Path
from .targets import REPO_ROOT
from .targets import PackageVariant
from .targets import TargetSpec
from .v8 import resolve_codex_v8_cargo_env
CODEX_RS_ROOT = REPO_ROOT / "codex-rs"
@dataclass(frozen=True)
class SourceBuildOutputs:
entrypoint_bin: Path
bwrap_bin: Path | None
codex_command_runner_bin: Path | None
codex_windows_sandbox_setup_bin: Path | None
def build_source_binaries(
spec: TargetSpec,
variant: PackageVariant,
*,
cargo: str,
profile: str,
entrypoint_bin: Path | None,
bwrap_bin: Path | None,
codex_command_runner_bin: Path | None,
codex_windows_sandbox_setup_bin: Path | None,
) -> SourceBuildOutputs:
validate_prebuilt_resource_inputs(
spec,
bwrap_bin=bwrap_bin,
codex_command_runner_bin=codex_command_runner_bin,
codex_windows_sandbox_setup_bin=codex_windows_sandbox_setup_bin,
)
binaries = source_binaries_for_target(
spec,
variant,
build_entrypoint=entrypoint_bin is None,
build_bwrap=spec.is_linux and bwrap_bin is None,
build_codex_command_runner=spec.is_windows
and codex_command_runner_bin is None,
build_codex_windows_sandbox_setup=spec.is_windows
and codex_windows_sandbox_setup_bin is None,
)
if binaries:
cmd = [
cargo,
"build",
"--target",
spec.target,
"--profile",
profile,
]
for binary in binaries:
cmd.extend(["--bin", binary])
cargo_env = None
if entrypoint_bin is None:
codex_v8_env = resolve_codex_v8_cargo_env(spec)
if codex_v8_env:
cargo_env = {**os.environ, **codex_v8_env}
print("+", " ".join(cmd))
subprocess.run(
cmd,
cwd=CODEX_RS_ROOT,
check=True,
env=cargo_env,
)
output_dir = cargo_profile_output_dir(spec, profile)
outputs = SourceBuildOutputs(
entrypoint_bin=resolve_output_path(
entrypoint_bin,
output_dir / variant.entrypoint_name(spec),
),
bwrap_bin=resolve_output_path(
bwrap_bin,
output_dir / "bwrap" if spec.is_linux else None,
),
codex_command_runner_bin=resolve_output_path(
codex_command_runner_bin,
output_dir / "codex-command-runner.exe" if spec.is_windows else None,
),
codex_windows_sandbox_setup_bin=resolve_output_path(
codex_windows_sandbox_setup_bin,
output_dir / "codex-windows-sandbox-setup.exe" if spec.is_windows else None,
),
)
validate_source_outputs(outputs)
return outputs
def source_binaries_for_target(
spec: TargetSpec,
variant: PackageVariant,
*,
build_entrypoint: bool,
build_bwrap: bool,
build_codex_command_runner: bool,
build_codex_windows_sandbox_setup: bool,
) -> list[str]:
binaries = []
if build_entrypoint:
binaries.append(variant.cargo_bin)
if build_bwrap:
binaries.append("bwrap")
if build_codex_command_runner:
binaries.append("codex-command-runner")
if build_codex_windows_sandbox_setup:
binaries.append("codex-windows-sandbox-setup")
return binaries
def validate_prebuilt_resource_inputs(
spec: TargetSpec,
*,
bwrap_bin: Path | None,
codex_command_runner_bin: Path | None,
codex_windows_sandbox_setup_bin: Path | None,
) -> None:
if bwrap_bin is not None and not spec.is_linux:
raise RuntimeError("--bwrap-bin is only supported for Linux targets.")
if codex_command_runner_bin is not None and not spec.is_windows:
raise RuntimeError(
"--codex-command-runner-bin is only supported for Windows targets."
)
if codex_windows_sandbox_setup_bin is not None and not spec.is_windows:
raise RuntimeError(
"--codex-windows-sandbox-setup-bin is only supported for Windows targets."
)
def resolve_output_path(explicit_path: Path | None, default_path: Path | None) -> Path | None:
if explicit_path is not None:
return explicit_path.resolve()
return default_path
def cargo_profile_output_dir(spec: TargetSpec, profile: str) -> Path:
target_dir = cargo_target_dir()
return target_dir / spec.target / cargo_profile_dirname(profile)
def cargo_target_dir() -> Path:
target_dir = os.environ.get("CARGO_TARGET_DIR")
if target_dir is None:
return CODEX_RS_ROOT / "target"
path = Path(target_dir)
if path.is_absolute():
return path
return CODEX_RS_ROOT / path
def cargo_profile_dirname(profile: str) -> str:
if profile == "dev":
return "debug"
if profile == "release":
return "release"
return profile
def validate_source_outputs(outputs: SourceBuildOutputs) -> None:
for path in [
outputs.entrypoint_bin,
outputs.bwrap_bin,
outputs.codex_command_runner_bin,
outputs.codex_windows_sandbox_setup_bin,
]:
if path is not None and not path.is_file():
raise RuntimeError(f"cargo build did not produce expected binary: {path}")