Skip to content

Commit

Permalink
Replace symlinks in the output of cargo build scripts
Browse files Browse the repository at this point in the history
After #2948 we symlink the source files in sandbox for most external repositories.
When a native build system is involved (e.x.: cmake) it is possible that the installed
files will be symlinks especially when header files are installed.

This will be placed in the output dir of cargo build scripts and when copied back to
the repository cache they become dangling symlinks with references to the sandbox.

As a fix we replace symlinks with a copy of them in the output directory.
  • Loading branch information
havasd committed Dec 10, 2024
1 parent dcf0a57 commit 1d10ca0
Showing 1 changed file with 49 additions and 1 deletion.
50 changes: 49 additions & 1 deletion cargo/cargo_build_script_runner/bin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ fn run_buildrs() -> Result<(), String> {
command
.current_dir(&working_directory)
.envs(target_env_vars)
.env("OUT_DIR", out_dir_abs)
.env("OUT_DIR", out_dir_abs.clone())
.env("CARGO_MANIFEST_DIR", manifest_dir)
.env("RUSTC", rustc)
.env("RUST_BACKTRACE", "full");
Expand Down Expand Up @@ -231,6 +231,8 @@ fn run_buildrs() -> Result<(), String> {
cargo_manifest_maker.drain_runfiles_dir().unwrap();
}

replace_symlinks_in_out_dir(&out_dir_abs)?;

Ok(())
}

Expand Down Expand Up @@ -720,6 +722,52 @@ fn parse_rustc_cfg_output(stdout: &str) -> BTreeMap<String, String> {
.collect()
}

/// Iterates over the given directory recursively and resolves any symlinks
///
/// Symlinks shouldn't present in `out_dir` as those amy contain paths to sandboxes which doesn't exists anymore.
/// Therefore, bazel will fail because of dangling symlinks.
fn replace_symlinks_in_out_dir(out_dir: &Path) -> Result<(), String> {
if out_dir.is_dir() {
let out_dir_paths = std::fs::read_dir(out_dir).map_err(|e| {
format!(
"Failed to read directory `{}` with {:?}",
out_dir.display(),
e
)
})?;
for entry in out_dir_paths {
let entry =
entry.map_err(|e| format!("Failed to read directory entry with {:?}", e,))?;
let path = entry.path();

if path.is_symlink() {
let target_path = std::fs::read_link(&path).map_err(|e| {
format!("Failed to read symlink `{}` with {:?}", path.display(), e,)
})?;
std::fs::remove_file(&path)
.map_err(|e| format!("Failed remove file `{}` with {:?}", path.display(), e))?;
std::fs::copy(&target_path, &path).map_err(|e| {
format!(
"Failed to copy `{} -> {}` with {:?}",
target_path.display(),
path.display(),
e
)
})?;
} else if path.is_dir() {
replace_symlinks_in_out_dir(&path).map_err(|e| {
format!(
"Failed to normalize nested directory `{}` with {}",
path.display(),
e,
)
})?;
}
}
}
Ok(())
}

fn main() {
std::process::exit(match run_buildrs() {
Ok(_) => 0,
Expand Down

0 comments on commit 1d10ca0

Please sign in to comment.