@@ -87,7 +87,8 @@ fn run_buildrs() -> Result<(), String> {
8787
8888 let working_directory = resolve_rundir ( & rundir, & exec_root, & manifest_dir) ?;
8989
90- let mut command = Command :: new ( exec_root. join ( progname) ) ;
90+ let script_path = exec_root. join ( & progname) ;
91+ let mut command = Command :: new ( & script_path) ;
9192 command
9293 . current_dir ( & working_directory)
9394 . envs ( target_env_vars)
@@ -96,6 +97,15 @@ fn run_buildrs() -> Result<(), String> {
9697 . env ( "RUSTC" , rustc)
9798 . env ( "RUST_BACKTRACE" , "full" ) ;
9899
100+ // The script binary may have a `<script>.runfiles/` tree or a
101+ // `<script>.runfiles_manifest` file materialized next to it by Bazel
102+ // (because the script was passed as a `FilesToRunProvider`). Expose
103+ // whichever exists so the runfiles library can locate the script's
104+ // runfiles (tools). Data files of `cargo_build_script` are intentionally
105+ // NOT in this tree — they must be looked up relative to
106+ // `CARGO_MANIFEST_DIR`.
107+ set_script_runfiles_env ( & script_path, & mut command) ;
108+
99109 for dep_env_path in input_dep_env_paths. iter ( ) {
100110 if let Ok ( contents) = read_to_string ( dep_env_path) {
101111 for line in contents. split ( '\n' ) {
@@ -313,6 +323,39 @@ fn should_symlink_exec_root() -> bool {
313323 . unwrap_or ( false )
314324}
315325
326+ /// Locate the runfiles materialized for `script_path` and expose them to the
327+ /// build script via the appropriate env var.
328+ ///
329+ /// Bazel materializes runfiles for a `FilesToRunProvider` tool either as a
330+ /// `<script>.runfiles/` directory tree, a `<script>.runfiles_manifest` file,
331+ /// or both. Both are checked; if neither is present, no env var is set and
332+ /// the runfiles library falls back to its own heuristics (e.g. argv[0]).
333+ ///
334+ /// `RUNFILES_MANIFEST_FILE` inherited from the parent process is cleared so
335+ /// it doesn't shadow what we're exposing.
336+ fn set_script_runfiles_env ( script_path : & Path , command : & mut Command ) {
337+ command. env_remove ( "RUNFILES_MANIFEST_FILE" ) ;
338+ command. env_remove ( "RUNFILES_DIR" ) ;
339+
340+ let Some ( file_name) = script_path. file_name ( ) else {
341+ return ;
342+ } ;
343+
344+ let mut runfiles_dir_name = file_name. to_owned ( ) ;
345+ runfiles_dir_name. push ( ".runfiles" ) ;
346+ let runfiles_dir = script_path. with_file_name ( & runfiles_dir_name) ;
347+ if runfiles_dir. is_dir ( ) {
348+ command. env ( "RUNFILES_DIR" , & runfiles_dir) ;
349+ }
350+
351+ let mut runfiles_manifest_name = file_name. to_owned ( ) ;
352+ runfiles_manifest_name. push ( ".runfiles_manifest" ) ;
353+ let runfiles_manifest = script_path. with_file_name ( & runfiles_manifest_name) ;
354+ if runfiles_manifest. is_file ( ) {
355+ command. env ( "RUNFILES_MANIFEST_FILE" , & runfiles_manifest) ;
356+ }
357+ }
358+
316359/// Create a symlink from `link` to `original` if `link` doesn't already exist.
317360fn symlink_if_not_exists ( original : & Path , link : & Path ) -> Result < ( ) , String > {
318361 symlink ( original, link)
0 commit comments