mirror of
https://github.com/openai/codex.git
synced 2026-02-01 14:44:17 +00:00
[bazel] Improve runfiles handling (#10098)
we can't use runfiles directory on Windows due to path lengths, so swap to manifest strategy. Parsing the manifest is a bit complex and the format is changing in Bazel upstream, so pull in the official Rust library (via a small hack to make it importable...) and cleanup all the associated logic to work cleanly in both bazel and cargo without extra confusion
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
# Without this, Bazel will consider BUILD.bazel files in
|
||||
# .git/sl/origbackups (which can be populated by Sapling SCM).
|
||||
.git
|
||||
codex-rs/target
|
||||
|
||||
6
.bazelrc
6
.bazelrc
@@ -1,5 +1,7 @@
|
||||
common --repo_env=BAZEL_DO_NOT_DETECT_CPP_TOOLCHAIN=1
|
||||
common --repo_env=BAZEL_NO_APPLE_CPP_TOOLCHAIN=1
|
||||
# Dummy xcode config so we don't need to build xcode_locator in repo rule.
|
||||
common --xcode_version_config=//:disable_xcode
|
||||
|
||||
common --disk_cache=~/.cache/bazel-disk-cache
|
||||
common --repo_contents_cache=~/.cache/bazel-repo-contents-cache
|
||||
@@ -9,6 +11,9 @@ startup --experimental_remote_repo_contents_cache
|
||||
|
||||
common --experimental_platform_in_output_dir
|
||||
|
||||
# Runfiles strategy rationale: codex-rs/utils/cargo-bin/README.md
|
||||
common --noenable_runfiles
|
||||
|
||||
common --enable_platform_specific_config
|
||||
# TODO(zbarsky): We need to untangle these libc constraints to get linux remote builds working.
|
||||
common:linux --host_platform=//:local
|
||||
@@ -44,4 +49,3 @@ common --jobs=30
|
||||
common:remote --extra_execution_platforms=//:rbe
|
||||
common:remote --remote_executor=grpcs://remote.buildbuddy.io
|
||||
common:remote --jobs=800
|
||||
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
load("@apple_support//xcode:xcode_config.bzl", "xcode_config")
|
||||
|
||||
xcode_config(name = "disable_xcode")
|
||||
|
||||
# We mark the local platform as glibc-compatible so that rust can grab a toolchain for us.
|
||||
# TODO(zbarsky): Upstream a better libc constraint into rules_rust.
|
||||
# We only enable this on linux though for sanity, and because it breaks remote execution.
|
||||
|
||||
@@ -27,6 +27,8 @@ register_toolchains(
|
||||
"@toolchains_llvm_bootstrapped//toolchain:all",
|
||||
)
|
||||
|
||||
# Needed to disable xcode...
|
||||
bazel_dep(name = "apple_support", version = "2.1.0")
|
||||
bazel_dep(name = "rules_cc", version = "0.2.16")
|
||||
bazel_dep(name = "rules_platform", version = "0.1.0")
|
||||
bazel_dep(name = "rules_rust", version = "0.68.1")
|
||||
@@ -90,6 +92,11 @@ crate.annotation(
|
||||
|
||||
inject_repo(crate, "openssl")
|
||||
|
||||
crate.annotation(
|
||||
crate = "runfiles",
|
||||
workspace_cargo_toml = "rust/runfiles/Cargo.toml",
|
||||
)
|
||||
|
||||
# Fix readme inclusions
|
||||
crate.annotation(
|
||||
crate = "windows-link",
|
||||
|
||||
4
MODULE.bazel.lock
generated
4
MODULE.bazel.lock
generated
@@ -21,7 +21,8 @@
|
||||
"https://bcr.bazel.build/modules/apple_support/1.23.0/MODULE.bazel": "317d47e3f65b580e7fb4221c160797fda48e32f07d2dfff63d754ef2316dcd25",
|
||||
"https://bcr.bazel.build/modules/apple_support/1.24.1/MODULE.bazel": "f46e8ddad60aef170ee92b2f3d00ef66c147ceafea68b6877cb45bd91737f5f8",
|
||||
"https://bcr.bazel.build/modules/apple_support/1.24.2/MODULE.bazel": "0e62471818affb9f0b26f128831d5c40b074d32e6dda5a0d3852847215a41ca4",
|
||||
"https://bcr.bazel.build/modules/apple_support/1.24.2/source.json": "2c22c9827093250406c5568da6c54e6fdf0ef06238def3d99c71b12feb057a8d",
|
||||
"https://bcr.bazel.build/modules/apple_support/2.1.0/MODULE.bazel": "b15c125dabed01b6803c129cd384de4997759f02f8ec90dc5136bcf6dfc5086a",
|
||||
"https://bcr.bazel.build/modules/apple_support/2.1.0/source.json": "78064cfefe18dee4faaf51893661e0d403784f3efe88671d727cdcdc67ed8fb3",
|
||||
"https://bcr.bazel.build/modules/aspect_bazel_lib/2.14.0/MODULE.bazel": "2b31ffcc9bdc8295b2167e07a757dbbc9ac8906e7028e5170a3708cecaac119f",
|
||||
"https://bcr.bazel.build/modules/aspect_bazel_lib/2.19.3/MODULE.bazel": "253d739ba126f62a5767d832765b12b59e9f8d2bc88cc1572f4a73e46eb298ca",
|
||||
"https://bcr.bazel.build/modules/aspect_bazel_lib/2.19.3/source.json": "ffab9254c65ba945f8369297ad97ca0dec213d3adc6e07877e23a48624a8b456",
|
||||
@@ -790,6 +791,7 @@
|
||||
"gimli_0.31.1": "{\"dependencies\":[{\"name\":\"alloc\",\"optional\":true,\"package\":\"rustc-std-workspace-alloc\",\"req\":\"^1.0.0\"},{\"name\":\"compiler_builtins\",\"optional\":true,\"req\":\"^0.1.2\"},{\"name\":\"core\",\"optional\":true,\"package\":\"rustc-std-workspace-core\",\"req\":\"^1.0.0\"},{\"default_features\":false,\"name\":\"fallible-iterator\",\"optional\":true,\"req\":\"^0.3.0\"},{\"name\":\"indexmap\",\"optional\":true,\"req\":\"^2.0.0\"},{\"default_features\":false,\"name\":\"stable_deref_trait\",\"optional\":true,\"req\":\"^1.1.0\"},{\"kind\":\"dev\",\"name\":\"test-assembler\",\"req\":\"^0.1.3\"}],\"features\":{\"default\":[\"read-all\",\"write\"],\"endian-reader\":[\"read\",\"dep:stable_deref_trait\"],\"fallible-iterator\":[\"dep:fallible-iterator\"],\"read\":[\"read-core\"],\"read-all\":[\"read\",\"std\",\"fallible-iterator\",\"endian-reader\"],\"read-core\":[],\"rustc-dep-of-std\":[\"dep:core\",\"dep:alloc\",\"dep:compiler_builtins\"],\"std\":[\"fallible-iterator?/std\",\"stable_deref_trait?/std\"],\"write\":[\"dep:indexmap\"]}}",
|
||||
"git+https://github.com/JakkuSakura/tokio-tungstenite?rev=2ae536b0de793f3ddf31fc2f22d445bf1ef2023d#2ae536b0de793f3ddf31fc2f22d445bf1ef2023d_tokio-tungstenite": "{\"dependencies\":[{\"default_features\":false,\"features\":[\"sink\",\"std\"],\"name\":\"futures-util\",\"optional\":false},{\"name\":\"log\"},{\"default_features\":true,\"features\":[],\"name\":\"native-tls-crate\",\"optional\":true,\"package\":\"native-tls\"},{\"default_features\":false,\"features\":[],\"name\":\"rustls\",\"optional\":true},{\"default_features\":true,\"features\":[],\"name\":\"rustls-native-certs\",\"optional\":true},{\"default_features\":true,\"features\":[],\"name\":\"rustls-pki-types\",\"optional\":true},{\"default_features\":false,\"features\":[\"io-util\"],\"name\":\"tokio\",\"optional\":false},{\"default_features\":true,\"features\":[],\"name\":\"tokio-native-tls\",\"optional\":true},{\"default_features\":false,\"features\":[],\"name\":\"tokio-rustls\",\"optional\":true},{\"default_features\":false,\"features\":[],\"name\":\"tungstenite\",\"optional\":false},{\"default_features\":true,\"features\":[],\"name\":\"webpki-roots\",\"optional\":true}],\"features\":{\"__rustls-tls\":[\"rustls\",\"rustls-pki-types\",\"tokio-rustls\",\"stream\",\"tungstenite/__rustls-tls\",\"handshake\"],\"connect\":[\"stream\",\"tokio/net\",\"handshake\"],\"default\":[\"connect\",\"handshake\"],\"handshake\":[\"tungstenite/handshake\"],\"native-tls\":[\"native-tls-crate\",\"tokio-native-tls\",\"stream\",\"tungstenite/native-tls\",\"handshake\"],\"native-tls-vendored\":[\"native-tls\",\"native-tls-crate/vendored\",\"tungstenite/native-tls-vendored\"],\"proxy\":[\"tungstenite/proxy\",\"tokio/net\",\"handshake\"],\"rustls-tls-native-roots\":[\"__rustls-tls\",\"rustls-native-certs\"],\"rustls-tls-webpki-roots\":[\"__rustls-tls\",\"webpki-roots\"],\"stream\":[],\"url\":[\"tungstenite/url\"]},\"strip_prefix\":\"\"}",
|
||||
"git+https://github.com/JakkuSakura/tungstenite-rs?rev=f514de8644821113e5d18a027d6d28a5c8cc0a6e#f514de8644821113e5d18a027d6d28a5c8cc0a6e_tungstenite": "{\"dependencies\":[{\"name\":\"bytes\"},{\"default_features\":true,\"features\":[],\"name\":\"data-encoding\",\"optional\":true},{\"default_features\":true,\"features\":[],\"name\":\"http\",\"optional\":true},{\"default_features\":true,\"features\":[],\"name\":\"httparse\",\"optional\":true},{\"name\":\"log\"},{\"default_features\":true,\"features\":[],\"name\":\"native-tls-crate\",\"optional\":true,\"package\":\"native-tls\"},{\"name\":\"rand\"},{\"default_features\":false,\"features\":[\"std\"],\"name\":\"rustls\",\"optional\":true},{\"default_features\":true,\"features\":[],\"name\":\"rustls-native-certs\",\"optional\":true},{\"default_features\":true,\"features\":[],\"name\":\"rustls-pki-types\",\"optional\":true},{\"default_features\":true,\"features\":[],\"name\":\"sha1\",\"optional\":true},{\"name\":\"thiserror\"},{\"default_features\":true,\"features\":[],\"name\":\"url\",\"optional\":true},{\"name\":\"utf-8\"},{\"default_features\":true,\"features\":[],\"name\":\"webpki-roots\",\"optional\":true}],\"features\":{\"__rustls-tls\":[\"rustls\",\"rustls-pki-types\"],\"default\":[\"handshake\"],\"handshake\":[\"data-encoding\",\"http\",\"httparse\",\"sha1\"],\"native-tls\":[\"native-tls-crate\"],\"native-tls-vendored\":[\"native-tls\",\"native-tls-crate/vendored\"],\"proxy\":[\"handshake\"],\"rustls-tls-native-roots\":[\"__rustls-tls\",\"rustls-native-certs\"],\"rustls-tls-webpki-roots\":[\"__rustls-tls\",\"webpki-roots\"],\"url\":[\"dep:url\"]},\"strip_prefix\":\"\"}",
|
||||
"git+https://github.com/dzbarsky/rules_rust?rev=b56cbaa8465e74127f1ea216f813cd377295ad81#b56cbaa8465e74127f1ea216f813cd377295ad81_runfiles": "{\"dependencies\":[],\"features\":{},\"strip_prefix\":\"\"}",
|
||||
"git+https://github.com/helix-editor/nucleo.git?rev=4253de9faabb4e5c6d81d946a5e35a90f87347ee#4253de9faabb4e5c6d81d946a5e35a90f87347ee_nucleo": "{\"dependencies\":[{\"default_features\":true,\"features\":[],\"name\":\"nucleo-matcher\",\"optional\":false},{\"default_features\":true,\"features\":[\"send_guard\",\"arc_lock\"],\"name\":\"parking_lot\",\"optional\":false},{\"name\":\"rayon\"}],\"features\":{},\"strip_prefix\":\"\"}",
|
||||
"git+https://github.com/helix-editor/nucleo.git?rev=4253de9faabb4e5c6d81d946a5e35a90f87347ee#4253de9faabb4e5c6d81d946a5e35a90f87347ee_nucleo-matcher": "{\"dependencies\":[{\"name\":\"memchr\"},{\"default_features\":true,\"features\":[],\"name\":\"unicode-segmentation\",\"optional\":true}],\"features\":{\"default\":[\"unicode-normalization\",\"unicode-casefold\",\"unicode-segmentation\"],\"unicode-casefold\":[],\"unicode-normalization\":[],\"unicode-segmentation\":[\"dep:unicode-segmentation\"]},\"strip_prefix\":\"matcher\"}",
|
||||
"git+https://github.com/nornagon/crossterm?branch=nornagon%2Fcolor-query#87db8bfa6dc99427fd3b071681b07fc31c6ce995_crossterm": "{\"dependencies\":[{\"default_features\":true,\"features\":[],\"name\":\"bitflags\",\"optional\":false},{\"default_features\":false,\"features\":[],\"name\":\"futures-core\",\"optional\":true},{\"name\":\"parking_lot\"},{\"default_features\":true,\"features\":[\"derive\"],\"name\":\"serde\",\"optional\":true},{\"default_features\":true,\"features\":[],\"name\":\"filedescriptor\",\"optional\":true,\"target\":\"cfg(unix)\"},{\"default_features\":false,\"features\":[],\"name\":\"libc\",\"optional\":true,\"target\":\"cfg(unix)\"},{\"default_features\":true,\"features\":[\"os-poll\"],\"name\":\"mio\",\"optional\":true,\"target\":\"cfg(unix)\"},{\"default_features\":false,\"features\":[\"std\",\"stdio\",\"termios\"],\"name\":\"rustix\",\"optional\":false,\"target\":\"cfg(unix)\"},{\"default_features\":true,\"features\":[],\"name\":\"signal-hook\",\"optional\":true,\"target\":\"cfg(unix)\"},{\"default_features\":true,\"features\":[\"support-v1_0\"],\"name\":\"signal-hook-mio\",\"optional\":true,\"target\":\"cfg(unix)\"},{\"default_features\":true,\"features\":[],\"name\":\"crossterm_winapi\",\"optional\":true,\"target\":\"cfg(windows)\"},{\"default_features\":true,\"features\":[\"winuser\",\"winerror\"],\"name\":\"winapi\",\"optional\":true,\"target\":\"cfg(windows)\"}],\"features\":{\"bracketed-paste\":[],\"default\":[\"bracketed-paste\",\"windows\",\"events\"],\"event-stream\":[\"dep:futures-core\",\"events\"],\"events\":[\"dep:mio\",\"dep:signal-hook\",\"dep:signal-hook-mio\"],\"serde\":[\"dep:serde\",\"bitflags/serde\"],\"use-dev-tty\":[\"filedescriptor\",\"rustix/process\"],\"windows\":[\"dep:winapi\",\"dep:crossterm_winapi\"]},\"strip_prefix\":\"\"}",
|
||||
|
||||
7
codex-rs/Cargo.lock
generated
7
codex-rs/Cargo.lock
generated
@@ -1975,7 +1975,7 @@ name = "codex-utils-cargo-bin"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"assert_cmd",
|
||||
"path-absolutize",
|
||||
"runfiles",
|
||||
"thiserror 2.0.17",
|
||||
]
|
||||
|
||||
@@ -6592,6 +6592,11 @@ dependencies = [
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "runfiles"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/dzbarsky/rules_rust?rev=b56cbaa8465e74127f1ea216f813cd377295ad81#b56cbaa8465e74127f1ea216f813cd377295ad81"
|
||||
|
||||
[[package]]
|
||||
name = "rustc-demangle"
|
||||
version = "0.1.25"
|
||||
|
||||
@@ -186,6 +186,7 @@ regex = "1.12.2"
|
||||
regex-lite = "0.1.8"
|
||||
reqwest = "0.12"
|
||||
rmcp = { version = "0.12.0", default-features = false }
|
||||
runfiles = { git = "https://github.com/dzbarsky/rules_rust", rev = "b56cbaa8465e74127f1ea216f813cd377295ad81" }
|
||||
schemars = "0.8.22"
|
||||
seccompiler = "0.5.0"
|
||||
sentry = "0.46.0"
|
||||
|
||||
@@ -16,7 +16,7 @@ use wiremock::matchers::path;
|
||||
|
||||
fn repo_root() -> std::path::PathBuf {
|
||||
#[expect(clippy::expect_used)]
|
||||
find_resource!(".").expect("failed to resolve repo root")
|
||||
codex_utils_cargo_bin::repo_root().expect("failed to resolve repo root")
|
||||
}
|
||||
|
||||
fn cli_responses_fixture() -> std::path::PathBuf {
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
#![allow(clippy::unwrap_used, clippy::expect_used)]
|
||||
use codex_utils_cargo_bin::find_resource;
|
||||
use core_test_support::responses::ev_completed;
|
||||
use core_test_support::responses::mount_sse_once_match;
|
||||
use core_test_support::responses::sse;
|
||||
@@ -11,7 +10,7 @@ use wiremock::matchers::header;
|
||||
async fn exec_uses_codex_api_key_env_var() -> anyhow::Result<()> {
|
||||
let test = test_codex_exec();
|
||||
let server = start_mock_server().await;
|
||||
let repo_root = find_resource!(".")?;
|
||||
let repo_root = codex_utils_cargo_bin::repo_root()?;
|
||||
|
||||
mount_sse_once_match(
|
||||
&server,
|
||||
|
||||
@@ -113,7 +113,7 @@ fn exec_fixture() -> anyhow::Result<std::path::PathBuf> {
|
||||
}
|
||||
|
||||
fn exec_repo_root() -> anyhow::Result<std::path::PathBuf> {
|
||||
Ok(find_resource!(".")?)
|
||||
Ok(codex_utils_cargo_bin::repo_root()?)
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
@@ -3,4 +3,10 @@ load("//:defs.bzl", "codex_rust_crate")
|
||||
codex_rust_crate(
|
||||
name = "cargo-bin",
|
||||
crate_name = "codex_utils_cargo_bin",
|
||||
compile_data = ["repo_root.marker"],
|
||||
lib_data_extra = ["repo_root.marker"],
|
||||
test_data_extra = ["repo_root.marker"],
|
||||
rustc_env = {
|
||||
"CODEX_REPO_ROOT_MARKER": "$(rlocationpath :repo_root.marker)",
|
||||
},
|
||||
)
|
||||
|
||||
@@ -9,5 +9,5 @@ workspace = true
|
||||
|
||||
[dependencies]
|
||||
assert_cmd = { workspace = true }
|
||||
path-absolutize = { workspace = true }
|
||||
runfiles = { workspace = true }
|
||||
thiserror = { workspace = true }
|
||||
|
||||
20
codex-rs/utils/cargo-bin/README.md
Normal file
20
codex-rs/utils/cargo-bin/README.md
Normal file
@@ -0,0 +1,20 @@
|
||||
# codex-utils-cargo-bin runfiles strategy
|
||||
|
||||
We disable the directory-based runfiles strategy and rely on the manifest
|
||||
strategy across all platforms. This avoids Windows path length issues and keeps
|
||||
behavior consistent in local and remote builds on all platforms. Bazel sets
|
||||
`RUNFILES_MANIFEST_FILE`, and the `codex-utils-cargo-bin` helpers use the
|
||||
`runfiles` crate to resolve runfiles via that manifest.
|
||||
|
||||
Function behavior:
|
||||
- `cargo_bin`: reads `CARGO_BIN_EXE_*` environment variables (set by Cargo or
|
||||
Bazel) and resolves them via the runfiles manifest when `RUNFILES_MANIFEST_FILE`
|
||||
is present. When not under runfiles, it only accepts absolute paths from
|
||||
`CARGO_BIN_EXE_*` and returns an error otherwise.
|
||||
- `find_resource!`: used by tests to locate fixtures. It chooses the Bazel
|
||||
runfiles resolution path when `RUNFILES_MANIFEST_FILE` is set, otherwise it
|
||||
falls back to a `CARGO_MANIFEST_DIR`-relative path for Cargo runs.
|
||||
|
||||
Background:
|
||||
- https://bazel.build/docs/runfiles
|
||||
- https://bazel.build/docs/runfiles#runfiles-manifest
|
||||
1
codex-rs/utils/cargo-bin/repo_root.marker
Normal file
1
codex-rs/utils/cargo-bin/repo_root.marker
Normal file
@@ -0,0 +1 @@
|
||||
|
||||
@@ -1,7 +1,12 @@
|
||||
use std::ffi::OsString;
|
||||
use std::io;
|
||||
use std::path::Path;
|
||||
use std::path::PathBuf;
|
||||
|
||||
pub use path_absolutize;
|
||||
pub use runfiles;
|
||||
|
||||
/// Bazel sets this when runfiles directories are disabled, which we do on all platforms for consistency.
|
||||
const RUNFILES_MANIFEST_ONLY_ENV: &str = "RUNFILES_MANIFEST_ONLY";
|
||||
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
pub enum CargoBinError {
|
||||
@@ -27,10 +32,9 @@ pub enum CargoBinError {
|
||||
|
||||
/// Returns an absolute path to a binary target built for the current test run.
|
||||
///
|
||||
/// In `cargo test`, `CARGO_BIN_EXE_*` env vars are absolute, but Buck2 may set
|
||||
/// them to project-relative paths (e.g. `buck-out/...`). Those paths break if a
|
||||
/// test later changes its working directory. This helper makes the path
|
||||
/// absolute up-front so callers can safely `chdir` afterwards.
|
||||
/// In `cargo test`, `CARGO_BIN_EXE_*` env vars are absolute.
|
||||
/// In `bazel test`, `CARGO_BIN_EXE_*` env vars are rlocationpaths, intended to be consumed by `rlocation`.
|
||||
/// This helper allows callers to transparently support both.
|
||||
pub fn cargo_bin(name: &str) -> Result<PathBuf, CargoBinError> {
|
||||
let env_keys = cargo_bin_env_keys(name);
|
||||
for key in &env_keys {
|
||||
@@ -38,16 +42,20 @@ pub fn cargo_bin(name: &str) -> Result<PathBuf, CargoBinError> {
|
||||
return resolve_bin_from_env(key, value);
|
||||
}
|
||||
}
|
||||
|
||||
match assert_cmd::Command::cargo_bin(name) {
|
||||
Ok(cmd) => {
|
||||
let abs = absolutize_from_buck_or_cwd(PathBuf::from(cmd.get_program()))?;
|
||||
if abs.exists() {
|
||||
Ok(abs)
|
||||
let mut path = PathBuf::from(cmd.get_program());
|
||||
if !path.is_absolute() {
|
||||
path = std::env::current_dir()
|
||||
.map_err(|source| CargoBinError::CurrentDir { source })?
|
||||
.join(path);
|
||||
}
|
||||
if path.exists() {
|
||||
Ok(path)
|
||||
} else {
|
||||
Err(CargoBinError::ResolvedPathDoesNotExist {
|
||||
key: "assert_cmd::Command::cargo_bin".to_owned(),
|
||||
path: abs,
|
||||
path,
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -72,6 +80,31 @@ fn cargo_bin_env_keys(name: &str) -> Vec<String> {
|
||||
keys
|
||||
}
|
||||
|
||||
pub fn runfiles_available() -> bool {
|
||||
std::env::var_os(RUNFILES_MANIFEST_ONLY_ENV).is_some()
|
||||
}
|
||||
|
||||
fn resolve_bin_from_env(key: &str, value: OsString) -> Result<PathBuf, CargoBinError> {
|
||||
let raw = PathBuf::from(&value);
|
||||
if runfiles_available() {
|
||||
let runfiles = runfiles::Runfiles::create().map_err(|err| CargoBinError::CurrentExe {
|
||||
source: std::io::Error::other(err),
|
||||
})?;
|
||||
if let Some(resolved) = runfiles::rlocation!(runfiles, &raw)
|
||||
&& resolved.exists()
|
||||
{
|
||||
return Ok(resolved);
|
||||
}
|
||||
} else if raw.is_absolute() && raw.exists() {
|
||||
return Ok(raw);
|
||||
}
|
||||
|
||||
Err(CargoBinError::ResolvedPathDoesNotExist {
|
||||
key: key.to_owned(),
|
||||
path: raw,
|
||||
})
|
||||
}
|
||||
|
||||
/// Macro that derives the path to a test resource at runtime, the value of
|
||||
/// which depends on whether Cargo or Bazel is being used to build and run a
|
||||
/// test. Note the return value may be a relative or absolute path.
|
||||
@@ -84,97 +117,109 @@ fn cargo_bin_env_keys(name: &str) -> Vec<String> {
|
||||
#[macro_export]
|
||||
macro_rules! find_resource {
|
||||
($resource:expr) => {{
|
||||
// When this code is built and run with Bazel:
|
||||
// - we inject `BAZEL_PACKAGE` as a compile-time environment variable
|
||||
// that points to native.package_name()
|
||||
// - at runtime, Bazel will set `RUNFILES_DIR` to the runfiles directory
|
||||
//
|
||||
// Therefore, the compile-time value of `BAZEL_PACKAGE` will always be
|
||||
// included in the compiled binary (even if it is built with Cargo), but
|
||||
// we only check it at runtime if `RUNFILES_DIR` is set.
|
||||
let resource = std::path::Path::new(&$resource);
|
||||
match std::env::var("RUNFILES_DIR") {
|
||||
Ok(bazel_runtime_files) => match option_env!("BAZEL_PACKAGE") {
|
||||
Some(bazel_package) => {
|
||||
use $crate::path_absolutize::Absolutize;
|
||||
|
||||
let manifest_dir = std::path::PathBuf::from(bazel_runtime_files)
|
||||
.join("_main")
|
||||
.join(bazel_package)
|
||||
.join(resource);
|
||||
// Note we also have to normalize (but not canonicalize!)
|
||||
// the path for _Bazel_ because the original value ends with
|
||||
// `codex-rs/exec-server/tests/common/../suite/bash`, but
|
||||
// the `tests/common` folder will not exist at runtime under
|
||||
// Bazel. As such, we have to normalize it before passing it
|
||||
// to `dotslash fetch`.
|
||||
manifest_dir.absolutize().map(|p| p.to_path_buf())
|
||||
}
|
||||
None => Err(std::io::Error::new(
|
||||
std::io::ErrorKind::NotFound,
|
||||
"BAZEL_PACKAGE not set in Bazel build",
|
||||
)),
|
||||
},
|
||||
Err(_) => {
|
||||
let manifest_dir = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR"));
|
||||
Ok(manifest_dir.join(resource))
|
||||
}
|
||||
if $crate::runfiles_available() {
|
||||
// When this code is built and run with Bazel:
|
||||
// - we inject `BAZEL_PACKAGE` as a compile-time environment variable
|
||||
// that points to native.package_name()
|
||||
// - at runtime, Bazel will set runfiles-related env vars
|
||||
$crate::resolve_bazel_runfile(option_env!("BAZEL_PACKAGE"), resource)
|
||||
} else {
|
||||
let manifest_dir = std::path::Path::new(env!("CARGO_MANIFEST_DIR"));
|
||||
Ok(manifest_dir.join(resource))
|
||||
}
|
||||
}};
|
||||
}
|
||||
|
||||
fn resolve_bin_from_env(key: &str, value: OsString) -> Result<PathBuf, CargoBinError> {
|
||||
let abs = absolutize_from_buck_or_cwd(PathBuf::from(value))?;
|
||||
|
||||
if abs.exists() {
|
||||
Ok(abs)
|
||||
} else {
|
||||
Err(CargoBinError::ResolvedPathDoesNotExist {
|
||||
key: key.to_owned(),
|
||||
path: abs,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
fn absolutize_from_buck_or_cwd(path: PathBuf) -> Result<PathBuf, CargoBinError> {
|
||||
if path.is_absolute() {
|
||||
return Ok(path);
|
||||
}
|
||||
|
||||
if let Some(root) =
|
||||
buck_project_root().map_err(|source| CargoBinError::CurrentExe { source })?
|
||||
pub fn resolve_bazel_runfile(
|
||||
bazel_package: Option<&str>,
|
||||
resource: &Path,
|
||||
) -> std::io::Result<PathBuf> {
|
||||
let runfiles = runfiles::Runfiles::create()
|
||||
.map_err(|err| std::io::Error::other(format!("failed to create runfiles: {err}")))?;
|
||||
let runfile_path = match bazel_package {
|
||||
Some(bazel_package) => PathBuf::from("_main").join(bazel_package).join(resource),
|
||||
None => {
|
||||
return Err(std::io::Error::new(
|
||||
std::io::ErrorKind::NotFound,
|
||||
"BAZEL_PACKAGE was not set at compile time",
|
||||
));
|
||||
}
|
||||
};
|
||||
let runfile_path = normalize_runfile_path(&runfile_path);
|
||||
if let Some(resolved) = runfiles::rlocation!(runfiles, &runfile_path)
|
||||
&& resolved.exists()
|
||||
{
|
||||
return Ok(root.join(path));
|
||||
return Ok(resolved);
|
||||
}
|
||||
|
||||
Ok(std::env::current_dir()
|
||||
.map_err(|source| CargoBinError::CurrentDir { source })?
|
||||
.join(path))
|
||||
let runfile_path_display = runfile_path.display();
|
||||
Err(std::io::Error::new(
|
||||
std::io::ErrorKind::NotFound,
|
||||
format!("runfile does not exist at: {runfile_path_display}"),
|
||||
))
|
||||
}
|
||||
|
||||
/// Best-effort attempt to find the Buck project root for the currently running
|
||||
/// process.
|
||||
///
|
||||
/// Prefer this over `env!("CARGO_MANIFEST_DIR")` when running under Buck2: our
|
||||
/// Buck generator sets `CARGO_MANIFEST_DIR="."` for compilation, which makes
|
||||
/// `env!("CARGO_MANIFEST_DIR")` unusable for locating workspace files.
|
||||
pub fn buck_project_root() -> Result<Option<PathBuf>, std::io::Error> {
|
||||
if let Some(root) = std::env::var_os("BUCK_PROJECT_ROOT") {
|
||||
let root = PathBuf::from(root);
|
||||
if root.is_absolute() {
|
||||
return Ok(Some(root));
|
||||
pub fn resolve_cargo_runfile(resource: &Path) -> std::io::Result<PathBuf> {
|
||||
let manifest_dir = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR"));
|
||||
Ok(manifest_dir.join(resource))
|
||||
}
|
||||
|
||||
pub fn repo_root() -> io::Result<PathBuf> {
|
||||
let marker = if runfiles_available() {
|
||||
let runfiles = runfiles::Runfiles::create()
|
||||
.map_err(|err| io::Error::other(format!("failed to create runfiles: {err}")))?;
|
||||
let marker_path = option_env!("CODEX_REPO_ROOT_MARKER")
|
||||
.map(PathBuf::from)
|
||||
.ok_or_else(|| {
|
||||
io::Error::new(
|
||||
io::ErrorKind::NotFound,
|
||||
"CODEX_REPO_ROOT_MARKER was not set at compile time",
|
||||
)
|
||||
})?;
|
||||
runfiles::rlocation!(runfiles, &marker_path).ok_or_else(|| {
|
||||
io::Error::new(
|
||||
io::ErrorKind::NotFound,
|
||||
"repo_root.marker not available in runfiles",
|
||||
)
|
||||
})?
|
||||
} else {
|
||||
resolve_cargo_runfile(Path::new("repo_root.marker"))?
|
||||
};
|
||||
let mut root = marker;
|
||||
for _ in 0..4 {
|
||||
root = root
|
||||
.parent()
|
||||
.ok_or_else(|| {
|
||||
io::Error::new(
|
||||
io::ErrorKind::NotFound,
|
||||
"repo_root.marker did not have expected parent depth",
|
||||
)
|
||||
})?
|
||||
.to_path_buf();
|
||||
}
|
||||
Ok(root)
|
||||
}
|
||||
|
||||
fn normalize_runfile_path(path: &Path) -> PathBuf {
|
||||
let mut components = Vec::new();
|
||||
for component in path.components() {
|
||||
match component {
|
||||
std::path::Component::CurDir => {}
|
||||
std::path::Component::ParentDir => {
|
||||
if matches!(components.last(), Some(std::path::Component::Normal(_))) {
|
||||
components.pop();
|
||||
} else {
|
||||
components.push(component);
|
||||
}
|
||||
}
|
||||
_ => components.push(component),
|
||||
}
|
||||
}
|
||||
|
||||
// Fall back to deriving the project root from the location of the test
|
||||
// runner executable:
|
||||
// <project>/buck-out/v2/gen/.../__tests__/test-binary
|
||||
let exe = std::env::current_exe()?;
|
||||
for ancestor in exe.ancestors() {
|
||||
if ancestor.file_name().is_some_and(|name| name == "buck-out") {
|
||||
return Ok(ancestor.parent().map(PathBuf::from));
|
||||
}
|
||||
}
|
||||
|
||||
Ok(None)
|
||||
components
|
||||
.into_iter()
|
||||
.fold(PathBuf::new(), |mut acc, component| {
|
||||
acc.push(component.as_os_str());
|
||||
acc
|
||||
})
|
||||
}
|
||||
|
||||
11
defs.bzl
11
defs.bzl
@@ -36,6 +36,8 @@ def codex_rust_crate(
|
||||
crate_edition = None,
|
||||
build_script_data = [],
|
||||
compile_data = [],
|
||||
lib_data_extra = [],
|
||||
rustc_env = {},
|
||||
deps_extra = [],
|
||||
integration_deps_extra = [],
|
||||
integration_compile_data_extra = [],
|
||||
@@ -63,6 +65,8 @@ def codex_rust_crate(
|
||||
You probably don't want this, it's only here for a single caller.
|
||||
build_script_data: Data files exposed to the build script at runtime.
|
||||
compile_data: Non-Rust compile-time data for the library target.
|
||||
lib_data_extra: Extra runtime data for the library target.
|
||||
rustc_env: Extra rustc_env entries to merge with defaults.
|
||||
deps_extra: Extra normal deps beyond @crates resolution.
|
||||
Typically only needed when features add additional deps.
|
||||
integration_deps_extra: Extra deps for integration tests only.
|
||||
@@ -85,7 +89,7 @@ def codex_rust_crate(
|
||||
|
||||
rustc_env = {
|
||||
"BAZEL_PACKAGE": native.package_name(),
|
||||
}
|
||||
} | rustc_env
|
||||
|
||||
binaries = DEP_DATA.get(native.package_name())["binaries"]
|
||||
|
||||
@@ -112,6 +116,7 @@ def codex_rust_crate(
|
||||
deps = deps,
|
||||
proc_macro_deps = proc_macro_deps,
|
||||
compile_data = compile_data,
|
||||
data = lib_data_extra,
|
||||
srcs = lib_srcs,
|
||||
edition = crate_edition,
|
||||
rustc_env = rustc_env,
|
||||
@@ -138,7 +143,7 @@ def codex_rust_crate(
|
||||
for binary, main in binaries.items():
|
||||
#binary = binary.replace("-", "_")
|
||||
sanitized_binaries.append(binary)
|
||||
cargo_env["CARGO_BIN_EXE_" + binary] = "$(rootpath :%s)" % binary
|
||||
cargo_env["CARGO_BIN_EXE_" + binary] = "$(rlocationpath :%s)" % binary
|
||||
|
||||
rust_binary(
|
||||
name = binary,
|
||||
@@ -154,7 +159,7 @@ def codex_rust_crate(
|
||||
for binary_label in extra_binaries:
|
||||
sanitized_binaries.append(binary_label)
|
||||
binary = Label(binary_label).name
|
||||
cargo_env["CARGO_BIN_EXE_" + binary] = "$(rootpath %s)" % binary_label
|
||||
cargo_env["CARGO_BIN_EXE_" + binary] = "$(rlocationpath %s)" % binary_label
|
||||
|
||||
for test in native.glob(["tests/*.rs"], allow_empty = True):
|
||||
test_name = name + "-" + test.removeprefix("tests/").removesuffix(".rs").replace("/", "-")
|
||||
|
||||
@@ -31,4 +31,4 @@ index a28ad50b7..af627fe50 100644
|
||||
+ make_link_flags = _make_link_flags_default_direct if use_direct_link_driver else _make_link_flags_default_indirect
|
||||
|
||||
return (make_link_flags, get_lib_name)
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user