From 55bf4ab1d490126d38ec747d6437cac2f3e17244 Mon Sep 17 00:00:00 2001 From: Channing Conger Date: Wed, 10 Jun 2026 17:22:31 -0700 Subject: [PATCH] Add Bazel launcher for code mode host --- BUILD.bazel | 2 + codex-rs/cli/BUILD.bazel | 10 ++++- defs.bzl | 60 +++++++++++++++++++++++++++++ justfile | 6 ++- runfile_env_binary_launcher.bat.tpl | 51 ++++++++++++++++++++++++ runfile_env_binary_launcher.sh.tpl | 57 +++++++++++++++++++++++++++ 6 files changed, 183 insertions(+), 3 deletions(-) create mode 100644 runfile_env_binary_launcher.bat.tpl create mode 100644 runfile_env_binary_launcher.sh.tpl diff --git a/BUILD.bazel b/BUILD.bazel index a82126e6f1..3f5d4f3f33 100644 --- a/BUILD.bazel +++ b/BUILD.bazel @@ -71,6 +71,8 @@ alias( exports_files([ "AGENTS.md", + "runfile_env_binary_launcher.bat.tpl", + "runfile_env_binary_launcher.sh.tpl", "workspace_root_test_launcher.bat.tpl", "workspace_root_test_launcher.sh.tpl", ]) diff --git a/codex-rs/cli/BUILD.bazel b/codex-rs/cli/BUILD.bazel index 97c868845b..c7671f92a5 100644 --- a/codex-rs/cli/BUILD.bazel +++ b/codex-rs/cli/BUILD.bazel @@ -1,4 +1,4 @@ -load("//:defs.bzl", "MACOS_WEBRTC_RUSTC_LINK_FLAGS", "codex_rust_crate") +load("//:defs.bzl", "MACOS_WEBRTC_RUSTC_LINK_FLAGS", "codex_rust_crate", "runfile_env_binary") load("//bazel/platforms:release_binaries.bzl", "multiplatform_binaries") codex_rust_crate( @@ -13,3 +13,11 @@ codex_rust_crate( multiplatform_binaries( name = "codex", ) + +runfile_env_binary( + name = "codex-with-code-mode", + binary = ":codex", + runfile_env = { + "//codex-rs/code-mode-host:codex-code-mode-host": "CODEX_CODE_MODE_HOST_PATH", + }, +) diff --git a/defs.bzl b/defs.bzl index b255160b09..d710c4b265 100644 --- a/defs.bzl +++ b/defs.bzl @@ -125,6 +125,66 @@ def _windows_workspace_root_setup(ctx): return """set "INSTA_WORKSPACE_ROOT=%workspace_root%" cd /d "%workspace_root%" || exit /b 1""" +def _runfile_env_binary_impl(ctx): + is_windows = ctx.target_platform_has_constraint(ctx.attr._windows_constraint[platform_common.ConstraintValueInfo]) + launcher = ctx.actions.declare_file(ctx.label.name + ".bat" if is_windows else ctx.label.name) + binary = ctx.executable.binary + launcher_template = ctx.file._windows_launcher_template if is_windows else ctx.file._bash_launcher_template + runfile_env_exports = _windows_runfile_env_exports(ctx) if is_windows else _bash_runfile_env_exports(ctx) + ctx.actions.expand_template( + template = launcher_template, + output = launcher, + is_executable = True, + substitutions = { + "__BINARY__": binary.short_path, + "__RUNFILE_ENV_EXPORTS__": runfile_env_exports, + "__WORKSPACE_NAME__": ctx.workspace_name, + }, + ) + + runfiles = ctx.runfiles(files = [binary]).merge(ctx.attr.binary[DefaultInfo].default_runfiles) + for runfile_dep in ctx.attr.runfile_env: + executable = runfile_dep[DefaultInfo].files_to_run.executable + if executable == None: + fail("{} does not provide an executable for runfile_env".format(runfile_dep.label)) + runfiles = runfiles.merge(ctx.runfiles(files = [executable])) + runfiles = runfiles.merge(runfile_dep[DefaultInfo].default_runfiles) + + return [DefaultInfo( + executable = launcher, + files = depset([launcher]), + runfiles = runfiles, + )] + +runfile_env_binary = rule( + implementation = _runfile_env_binary_impl, + executable = True, + toolchains = ["@bazel_tools//tools/test:default_test_toolchain_type"], + attrs = { + "binary": attr.label( + cfg = "target", + executable = True, + mandatory = True, + ), + "runfile_env": attr.label_keyed_string_dict( + cfg = "target", + ), + "_windows_constraint": attr.label( + default = "@platforms//os:windows", + providers = [platform_common.ConstraintValueInfo], + ), + "_bash_launcher_template": attr.label( + allow_single_file = True, + default = "//:runfile_env_binary_launcher.sh.tpl", + ), + "_windows_launcher_template": attr.label( + allow_single_file = True, + default = "//:runfile_env_binary_launcher.bat.tpl", + ), + }, + doc = "Runs a binary with environment variables resolved from executable runfiles.", +) + workspace_root_test = rule( implementation = _workspace_root_test_impl, test = True, diff --git a/justfile b/justfile index fa32a19e7d..153fc7bd97 100644 --- a/justfile +++ b/justfile @@ -96,16 +96,18 @@ bench-smoke: just bench -- --test # Build and run Codex from source using Bazel. +# The launcher target also builds the code-mode host and injects its runfile +# path, so Bazel can rebuild either binary incrementally. # On Unix, use `[no-cd]` and `--run_under="cd $PWD &&"` to ensure Bazel runs # the command in the current working directory. [no-cd] [unix] bazel-codex *args: - bazel run //codex-rs/cli:codex --run_under="cd $PWD &&" -- "$@" + bazel run //codex-rs/cli:codex-with-code-mode --run_under="cd $PWD &&" -- "$@" [windows] bazel-codex *args: - bazel run //codex-rs/cli:codex --run_under='cd /d "{{ invocation_directory_native() }}" &&' -- @($args | Select-Object -Skip 1) + bazel run //codex-rs/cli:codex-with-code-mode --run_under='cd /d "{{ invocation_directory_native() }}" &&' -- @($args | Select-Object -Skip 1) [no-cd] bazel-lock-update: diff --git a/runfile_env_binary_launcher.bat.tpl b/runfile_env_binary_launcher.bat.tpl new file mode 100644 index 0000000000..2d322e5677 --- /dev/null +++ b/runfile_env_binary_launcher.bat.tpl @@ -0,0 +1,51 @@ +@echo off +setlocal EnableExtensions EnableDelayedExpansion + +call :resolve_runfile binary "__BINARY__" +if errorlevel 1 exit /b 1 + +__RUNFILE_ENV_EXPORTS__ + +"%binary%" %* +exit /b %ERRORLEVEL% + +:resolve_runfile +setlocal EnableExtensions EnableDelayedExpansion +set "logical_path=%~2" +set "native_logical_path=%logical_path:/=\%" +set "workspace_name=__WORKSPACE_NAME__" + +for %%R in ("%RUNFILES_DIR%" "%TEST_SRCDIR%" "%~f0.runfiles") do ( + set "runfiles_root=%%~R" + if defined runfiles_root ( + for %%P in ("!native_logical_path!" "%TEST_WORKSPACE%\!native_logical_path!" "!workspace_name!\!native_logical_path!" "_main\!native_logical_path!") do ( + if exist "!runfiles_root!\%%~P" ( + endlocal & set "%~1=!runfiles_root!\%%~P" & exit /b 0 + ) + ) + ) +) + +set "manifest=%RUNFILES_MANIFEST_FILE%" +if not defined manifest if exist "%~f0.runfiles_manifest" set "manifest=%~f0.runfiles_manifest" +if not defined manifest if exist "%~f0.exe.runfiles_manifest" set "manifest=%~f0.exe.runfiles_manifest" + +if defined manifest if exist "%manifest%" ( + for /f "usebackq tokens=1,* delims= " %%A in ("%manifest%") do ( + if "%%A"=="%logical_path%" ( + endlocal & set "%~1=%%B" & exit /b 0 + ) + if "%%A"=="%TEST_WORKSPACE%/%logical_path%" ( + endlocal & set "%~1=%%B" & exit /b 0 + ) + if "%%A"=="%workspace_name%/%logical_path%" ( + endlocal & set "%~1=%%B" & exit /b 0 + ) + if "%%A"=="_main/%logical_path%" ( + endlocal & set "%~1=%%B" & exit /b 0 + ) + ) +) + +>&2 echo failed to resolve runfile: %logical_path% +endlocal & exit /b 1 diff --git a/runfile_env_binary_launcher.sh.tpl b/runfile_env_binary_launcher.sh.tpl new file mode 100644 index 0000000000..105118f7f9 --- /dev/null +++ b/runfile_env_binary_launcher.sh.tpl @@ -0,0 +1,57 @@ +#!/usr/bin/env bash +set -euo pipefail + +resolve_runfile() { + local logical_path="$1" + local launcher_runfiles="$0.runfiles" + local workspace_name="__WORKSPACE_NAME__" + local runfiles_root + + for runfiles_root in "${RUNFILES_DIR:-}" "${TEST_SRCDIR:-}" "${launcher_runfiles}"; do + if [[ -z "${runfiles_root}" ]]; then + continue + fi + for candidate in \ + "${runfiles_root}/${logical_path}" \ + "${runfiles_root}/${TEST_WORKSPACE:-}/${logical_path}" \ + "${runfiles_root}/${workspace_name}/${logical_path}" \ + "${runfiles_root}/_main/${logical_path}"; do + if [[ -e "${candidate}" ]]; then + printf '%s\n' "${candidate}" + return 0 + fi + done + done + + local manifest="${RUNFILES_MANIFEST_FILE:-}" + if [[ -z "${manifest}" ]]; then + if [[ -f "$0.runfiles_manifest" ]]; then + manifest="$0.runfiles_manifest" + elif [[ -f "$0.exe.runfiles_manifest" ]]; then + manifest="$0.exe.runfiles_manifest" + fi + fi + + if [[ -n "${manifest}" && -f "${manifest}" ]]; then + local resolved + resolved="$(awk -v path="${logical_path}" '$1 == path || substr($1, length($1) - length(path), length(path) + 1) == "/" path { $1 = ""; sub(/^ /, ""); print; exit }' "${manifest}")" + if [[ -n "${resolved}" ]]; then + printf '%s\n' "${resolved}" + return 0 + fi + fi + + echo "failed to resolve runfile: ${logical_path}" >&2 + return 1 +} + +binary="$(resolve_runfile "__BINARY__")" +RUNFILE_ENV_ARGS=() + +__RUNFILE_ENV_EXPORTS__ + +if (( ${#RUNFILE_ENV_ARGS[@]} > 0 )); then + exec env "${RUNFILE_ENV_ARGS[@]}" "${binary}" "$@" +else + exec "${binary}" "$@" +fi