Skip to content

Expand placeholders in bootstrap response files - #46

Closed
pdeva wants to merge 91 commits into
hermeticbuild:mainfrom
pdeva:codex/fix-bootstrap-response-files
Closed

pdeva wants to merge 91 commits into
hermeticbuild:mainfrom
pdeva:codex/fix-bootstrap-response-files

Conversation

@pdeva

@pdeva pdeva commented Aug 24, 2026

Copy link
Copy Markdown

Summary

  • Expand ${pwd}, ${output_base}, and ${exec_root} inside bootstrap @response files before invoking rustc.
  • Pass rustc a sibling .expanded response file while leaving Bazel's generated input untouched.
  • Add cross-platform regression coverage for substitution, byte preservation, paths containing spaces, and missing-file errors.

Problem

Bootstrap rustc actions force compiler flags through an @params file. bootstrap_process_wrapper currently substitutes placeholders only in direct arguments, so remap flags inside the response file remain literal. rustc can then embed output-base or sandbox paths in tinyjson metadata, making clean builds produce different .rlib bytes.

Refs hermeticbuild/rules_rs#233.

Validation

  • bazelisk test //test/process_wrapper_bootstrap:bootstrap_process_wrapper_test --test_output=errors --nocache_test_results
  • bazelisk test //util/process_wrapper:process_wrapper_test --test_output=errors --nocache_test_results
  • bazelisk test //... --test_output=errors (600 passed, 30 platform-specific tests skipped on Linux)
  • Built the bootstrap tinyjson artifact from two fresh output bases under both local and linux-sandbox execution. Both pairs had identical SHA-256 hashes, and neither artifact contained an output-base or sandbox path.
  • pre-commit run --files util/process_wrapper/private/bootstrap_process_wrapper.cc test/process_wrapper_bootstrap/bootstrap_process_wrapper_test.rs

dzbarsky and others added 30 commits August 14, 2026 12:17
Add support for tier 3 targets bpfeb-unknown-none and bpfel-unknown-none
(see

https://github.com/rust-lang/rust/blob/f5e2df7/src/doc/rustc/src/platform-support.md?plain=1#L311-L312).

This is modeled after bazelbuild#3507
and
should probably be updated if/when
bazelbuild/platforms#131 is merged.

(please use rebase merge when landing this as the proper commit message
is in the commit, rather than the PR description)

/cc @avrabe
…hollow rlibs: the RustcMetadata action runs rustc to completion with -Zno-codegen, emitting a .rlib archive. This approach mirrors the one used by buck2 and avoids needing to kill rustc mid-output in order to produce metadata.

While not fixing problems with SVH mismatches when non-determinism, this does simplify the codepath and uses a production tested technique that doesn't have any of the dangers associated with killing the rustc process while it's still active.
Port the sharding wrapper feature from bazelbuild#3774 into the hermeticbuild fork. The implementation wraps rust_test executables when experimental_enable_sharding is set while keeping rustc_compile_action's existing provider-list API for internal and extension callers.

rust_test now scans the returned providers to replace DefaultInfo for the wrapper, so extensions such as prost and wasm-bindgen continue to consume rustc_compile_action without API churn.

Co-authored-by: Brian Duff <bduff@linkedin.com>

Co-authored-by: Codex <noreply@openai.com>
Rustc emits GNU-like Windows staticlibs as lib<crate>.a, but rules_rust was stripping the lib prefix for all Windows non-rlib library outputs. Keep the prefix for staticlib outputs when the target ABI is gnu or gnullvm so declared outputs match rustc.
dzbarsky and others added 23 commits August 14, 2026 12:20
Add documentation extraction targets for the public cargo and rust Starlark packages. Declare the bazel_features, selects, and cc_debug_helper_bzl dependencies required by those targets.
Scan code-generating rustc outputs for the resolved ${pwd} value after successful compilation. Reject embedded CARGO_MANIFEST_DIR, OUT_DIR, and other sandbox paths while preserving compile-time include_str! and relative paths.

Inspect cargo_build_script OUT_DIR through test runfiles instead of retaining compile-action paths.

Assisted-by: OpenAI Codex
* rustc: stage cc dynamic libraries in test runfiles

The cc dynamic libraries a target loads at runtime were collected into its
runfiles only when the crate type was bin, cdylib or staticlib. A rust_test
reports the type of the crate under test -- "lib" for rust_test(crate = ":foo")
-- so tests were skipped entirely. The collection also walked only `deps`, never
`crate`, so even a bin built that way would have missed them.

A rust_test depending on a cc_import shared library therefore produced runfiles
containing just the executable and the repo mapping. Its RUNPATH is
$ORIGIN/../../_solib_<cpu>/..., so it runs only where that execroot directory
happens to sit beside the binary. Locally it does, and the test passes. Under
remote execution the input tree is exactly the declared runfiles, and the test
dies at load time with `cannot open shared object file`.

Gate on crate_info.is_test as well, and scan `crate` alongside `deps`.

* test: cover imported dylibs in rust_test runfiles

A cc_binary(linkshared = True) in `deps` already reached a consumer's runfiles
through the generic deps traversal, so the existing check_runfiles cases passed
regardless of the dynamic library collection. A cc_import contributes no
runfiles of its own -- the dylib is only in its CcInfo linking context -- so it
isolates that collection.

Adds two cases over an imported dylib: a rust_binary (which reaches it through
`deps`) and a rust_test (through `crate`). The rust_test case fails without the
preceding commit and passes with it.

* ci: bump llvm to 0.8.4 for web.archive.org id_ URL fix

llvm 0.7.7 pins the macOS SDK archive at a web.archive.org URL without the
id_ modifier (web/20260430051604/...), which now serves the Wayback HTML
wrapper page instead of the raw pkg. The download checksum-mismatches and
the build aborts during analysis of any target that transitively fetches
@macos_sdk (e.g. //test/genquery:bar_deps), skipping every test.

llvm 0.8.4+ uses the id_ modifier (web/20260430051604id_/...) which returns
the raw file with the correct sha256. Bump the bazel_dep to unblock CI.
Allow disabling the default hermetic macOS SDKROOT globally.

Preserve explicit SDKROOT values and C/C++ toolchain SDKROOT.
Bootstrap rustc actions force flags into response files, but the minimal wrapper only substituted direct arguments. Rewrite response files with the same substitutions before invoking rustc and cover success and failure behavior.

Refs hermeticbuild/rules_rs#233

Assisted-by: OpenAI Codex
The MSVC spawn API splits embedded spaces unless the caller supplies quotes. Quote generated response-file arguments when needed so the child receives the expanded path as one argv entry.

Assisted-by: OpenAI Codex
dzbarsky added a commit that referenced this pull request Sep 5, 2026
Bootstrap actions pass rustc flags through @params, but the C++ bootstrap
process wrapper substitutes only direct arguments. The literal remap
placeholders leave execution directories in tinyjson crate metadata.

Use -Zremap-cwd-prefix for bootstrap compilation so rustc resolves its own
working directory. Default RUSTC_BOOTSTRAP to the bootstrap crate's name,
preserving explicit environment settings. Keep the existing response files
and SDKROOT expansion without changing the C++ wrapper.

Add a regression test that reads the actual bootstrap tinyjson archive.
The test fails before the fix. Sandboxed and local builds in different
output bases now produce identical archives without execution directories.
Validation: Bazel 9.1.0, Rust 1.98.0, macOS arm64; bazel test //... passed
621 tests and skipped 37 platform-incompatible tests.

Refs hermeticbuild/rules_rs#233 and #46.

Co-authored-by: Codex <noreply@openai.com>
@dzbarsky

dzbarsky commented Sep 5, 2026

Copy link
Copy Markdown
Member

@pdeva Thanks for filing the issue and sending the PR! I'm going with a slighly different solution here #53 and will be releasing shortly!

@dzbarsky dzbarsky closed this Sep 5, 2026
dzbarsky added a commit that referenced this pull request Sep 5, 2026
Bootstrap actions pass rustc flags through @params, but the C++ bootstrap
process wrapper substitutes only direct arguments. The literal remap
placeholders leave execution directories in tinyjson crate metadata.

Use -Zremap-cwd-prefix for bootstrap compilation so rustc resolves its own
working directory. Default RUSTC_BOOTSTRAP to the bootstrap crate's name,
preserving explicit environment settings. Keep the existing response files
and SDKROOT expansion without changing the C++ wrapper.

Add a regression test that reads the actual bootstrap tinyjson archive.
The test fails before the fix. Sandboxed and local builds in different
output bases now produce identical archives without execution directories.
Validation: Bazel 9.1.0, Rust 1.98.0, macOS arm64; bazel test //... passed
621 tests and skipped 37 platform-incompatible tests.

Refs hermeticbuild/rules_rs#233 and #46.

Co-authored-by: Codex <noreply@openai.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.