Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Razes fails inside cargo workspace due to with 'failed to read' #361

Open
v3n opened this issue Feb 5, 2021 · 4 comments · May be fixed by #526
Open

Razes fails inside cargo workspace due to with 'failed to read' #361

v3n opened this issue Feb 5, 2021 · 4 comments · May be fixed by #526

Comments

@v3n
Copy link

v3n commented Feb 5, 2021

I think this is related to #136.

cargo-raze --manifest-path=rust/Cargo.toml 
Error: Failed to fetch Metadata with `cargo` from `/var/folders/79/kzg9qh1x6q54hfy11bfc6wlcx6bxx6/T/.tmpG26uYw`

Caused by:
    `cargo metadata` exited with an error: error: failed to read `/private/var/folders/79/kzg9qh1x6q54hfy11bfc6wlcx6bxx6/T/third-party/proxy-wasm/Cargo.toml`
    
    Caused by:
      No such file or directory (os error 2)

I've uploaded a minimal repro, which can be reproduced by running:

cargo-raze --manifest-path=rust/Cargo.toml
@UebelAndre
Copy link
Collaborator

This occurs because internally cargo metadata is run in a temporary director and only links in workspace members and their src directories. This could be expanded to the entire tree to potentially solve for this problem. The problem would lie in:

fn link_src_to_workspace(&self, no_deps_metadata: &Metadata, temp_dir: &Path) -> Result<()> {
let crate_member_id_re = Regex::new(r".+\(path\+file://(.+)\)")?;
for member in no_deps_metadata.workspace_members.iter() {
// Get a path to the workspace member directory
let workspace_member_directory = {
let crate_member_id_match = crate_member_id_re
.captures(&member.repr)
.and_then(|cap| cap.get(1));
if crate_member_id_match.is_none() {
continue;
}
// UNWRAP: guarded above
PathBuf::from(crate_member_id_match.unwrap().as_str())
};
// Sanity check: The assumption is that any crate with an `id` that matches
// the regex pattern above should contain a Cargo.toml file with which we
// can use to infer the existence of libraries from relative paths such as
// `src/lib.rs` and `src/main.rs`.
let toml_path = workspace_member_directory.join("Cargo.toml");
if !toml_path.exists() {
return Err(anyhow!(format!(
"The regex pattern `{}` found a path that did not contain a Cargo.toml file: `{}`",
crate_member_id_re.as_str(),
workspace_member_directory.display()
)));
}
// Copy the Cargo.toml files into the temp directory to match the directory structure on disk
let diff = diff_paths(
&workspace_member_directory,
&no_deps_metadata.workspace_root,
)
.ok_or(anyhow!(
"All workspace memebers are expected to be under the workspace root"
))?;
let new_path = temp_dir.join(diff);
fs::create_dir_all(&new_path)?;
fs::copy(
workspace_member_directory.join("Cargo.toml"),
new_path.join("Cargo.toml"),
)?;
// Additionally, symlink everything in some common source directories to ensure specified
// library targets can be relied on and won't prevent fetching metadata
for dir in vec!["bin", "src"].iter() {
let glob_pattern = format!("{}/**/*.rs", workspace_member_directory.join(dir).display());
for entry in glob(glob_pattern.as_str()).expect("Failed to read glob pattern") {
let path = entry?;
// Determine the difference between the workspace root and the current file
let diff = diff_paths(&path, &no_deps_metadata.workspace_root).ok_or(anyhow!(
"All workspace memebers are expected to be under the workspace root"
))?;
// Create a matching directory tree for the current file within the temp workspace
let new_path = temp_dir.join(diff);
if let Some(parent) = new_path.parent() {
fs::create_dir_all(parent)?;
}
make_symlink(&path, &new_path)?;
}
}
}
Ok(())
}

@UebelAndre
Copy link
Collaborator

@acmcarther @dfreese How do you guys feel about not copying source code into a temporary directory? I don't think Cargo will alter anything in the source tree when gathering metadata. I think this would solve for this issue and reduce code complexity. I know this has been brought up before but forgot the rationale.

@leggers
Copy link

leggers commented Jul 29, 2021

Hi! This is currently blocking me from building a Rust target in a multi-language monorepo. Is there a workaround available? I tried copying a Cargo.toml to the root of the workspace, which seemed to get a little farther, but then choked when trying to get metadata for a local dependency (i.e. one with the path attribute) with the same error about being unable to find Cargo.toml in a tmp dir.

Should I start hand-writing crate rules in my WORKSPACE file instead of trying to use cargo-raze to generate them? Are there other things I should try?

@bsilver8192
Copy link
Contributor

@acmcarther @dfreese How do you guys feel about not copying source code into a temporary directory? I don't think Cargo will alter anything in the source tree when gathering metadata. I think this would solve for this issue and reduce code complexity. I know this has been brought up before but forgot the rationale.

@UebelAndre I think the functionality around cloning binary dependencies still requires the temporary directory.

bsilver8192 added a commit to bsilver8192/cargo-raze that referenced this issue Sep 16, 2022
This is how I work around rust-lang/cargo#5042
to get path dependencies into vendored Rust dependencies.

The generated BUILD files are built with
google#524, because otherwise they
don't work.

This fixes google#361.
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 a pull request may close this issue.

4 participants