Skip to content

Commit

Permalink
Auto merge of #10281 - Gnurfos:depinfo_relative, r=ehuss
Browse files Browse the repository at this point in the history
Fix use of .. in dep-info-basedir

### Summary

This allows setting, in .cargo/config's dep-info-basedir, some relative path that goes above the crate's directory.

### Motivation

In a setup like this:

```
repo_root
├── Makefile
├── some_c_things
│   └── foo.c
└── rust_things
    ├── Cargo.toml
    └─── src
        └── lib.rs
```

If you want the generated .d files to be includable directly in the Makefile (without post-processing), you need them to mention paths relative to the root, like:

rust_things/target/....: rust_things/src/lib.rs

### Implementation

For this you need to have relative paths with parent directories (in this case ..) in dep-info-basedir, which does not work without the change in this PR (due to render_filename doing only strip_prefix, while the basedir still contains literal ..s).

Let me know if this change is acceptable. Another implementation could be to canonicalize in ConfigRelativePath::resolve_path instead, especially since that struct outputs absolute paths. But that would have it access the filesystem, while it currently doesn't.
  • Loading branch information
bors committed May 7, 2022
2 parents 7ed2769 + e5ff81b commit 9fa2bba
Show file tree
Hide file tree
Showing 2 changed files with 80 additions and 11 deletions.
26 changes: 16 additions & 10 deletions src/cargo/core/compiler/output_depinfo.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
//! dependencies are not included under the assumption that changes to them can
//! be detected via changes to `Cargo.lock`.
use cargo_util::paths::normalize_path;
use std::collections::{BTreeSet, HashSet};
use std::io::{BufWriter, Write};
use std::path::{Path, PathBuf};
Expand All @@ -33,16 +34,21 @@ use log::debug;

fn render_filename<P: AsRef<Path>>(path: P, basedir: Option<&str>) -> CargoResult<String> {
let path = path.as_ref();
let relpath = match basedir {
None => path,
Some(base) => match path.strip_prefix(base) {
Ok(relpath) => relpath,
_ => path,
},
};
relpath
.to_str()
.ok_or_else(|| internal(format!("path `{:?}` not utf-8", relpath)))
if let Some(basedir) = basedir {
let norm_path = normalize_path(path);
let norm_basedir = normalize_path(basedir.as_ref());
match norm_path.strip_prefix(norm_basedir) {
Ok(relpath) => wrap_path(relpath),
_ => wrap_path(path),
}
} else {
wrap_path(path)
}
}

fn wrap_path(path: &Path) -> CargoResult<String> {
path.to_str()
.ok_or_else(|| internal(format!("path `{:?}` not utf-8", path)))
.map(|f| f.replace(" ", "\\ "))
}

Expand Down
65 changes: 64 additions & 1 deletion tests/testsuite/build_script.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use cargo_test_support::compare::assert_match_exact;
use cargo_test_support::paths::CargoPathExt;
use cargo_test_support::registry::Package;
use cargo_test_support::tools;
use cargo_test_support::{basic_manifest, cross_compile, is_coarse_mtime, project};
use cargo_test_support::{basic_manifest, cross_compile, is_coarse_mtime, project, project_in};
use cargo_test_support::{rustc_host, sleep_ms, slow_cpu_multiplier, symlink_supported};
use cargo_util::paths::remove_dir_all;
use std::env;
Expand Down Expand Up @@ -3178,6 +3178,69 @@ fn generate_good_d_files() {
.any(|v| v == "barkbarkbark" || v == "build.rs"));
}

#[cargo_test]
fn generate_good_d_files_for_external_tools() {
// This tests having a relative paths going out of the
// project root in config's dep-info-basedir
let p = project_in("rust_things")
.file(
"awoo/Cargo.toml",
r#"
[project]
name = "awoo"
version = "0.5.0"
build = "build.rs"
"#,
)
.file("awoo/src/lib.rs", "")
.file(
"awoo/build.rs",
r#"
fn main() {
println!("cargo:rerun-if-changed=build.rs");
println!("cargo:rerun-if-changed=barkbarkbark");
}
"#,
)
.file(
"Cargo.toml",
r#"
[project]
name = "meow"
version = "0.5.0"
[dependencies]
awoo = { path = "awoo" }
"#,
)
.file("src/main.rs", "fn main() {}")
.file(
".cargo/config.toml",
r#"
[build]
dep-info-basedir="../.."
"#,
)
.build();

p.cargo("build -v").run();

let dot_d_path = p.bin("meow").with_extension("d");
let dot_d = fs::read_to_string(&dot_d_path).unwrap();

println!("*.d file content with dep-info-basedir*: {}", &dot_d);

assert_match_exact(
concat!(
"rust_things/foo/target/debug/meow[EXE]:",
" rust_things/foo/awoo/barkbarkbark",
" rust_things/foo/awoo/build.rs",
" rust_things/foo/awoo/src/lib.rs",
" rust_things/foo/src/main.rs",
),
&dot_d,
);
}

#[cargo_test]
fn rebuild_only_on_explicit_paths() {
let p = project()
Expand Down

0 comments on commit 9fa2bba

Please sign in to comment.