Skip to content

Commit 9fa2bba

Browse files
committed
Auto merge of #10281 - Gnurfos:depinfo_relative, r=ehuss
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.
2 parents 7ed2769 + e5ff81b commit 9fa2bba

File tree

2 files changed

+80
-11
lines changed

2 files changed

+80
-11
lines changed

src/cargo/core/compiler/output_depinfo.rs

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
//! dependencies are not included under the assumption that changes to them can
2323
//! be detected via changes to `Cargo.lock`.
2424
25+
use cargo_util::paths::normalize_path;
2526
use std::collections::{BTreeSet, HashSet};
2627
use std::io::{BufWriter, Write};
2728
use std::path::{Path, PathBuf};
@@ -33,16 +34,21 @@ use log::debug;
3334

3435
fn render_filename<P: AsRef<Path>>(path: P, basedir: Option<&str>) -> CargoResult<String> {
3536
let path = path.as_ref();
36-
let relpath = match basedir {
37-
None => path,
38-
Some(base) => match path.strip_prefix(base) {
39-
Ok(relpath) => relpath,
40-
_ => path,
41-
},
42-
};
43-
relpath
44-
.to_str()
45-
.ok_or_else(|| internal(format!("path `{:?}` not utf-8", relpath)))
37+
if let Some(basedir) = basedir {
38+
let norm_path = normalize_path(path);
39+
let norm_basedir = normalize_path(basedir.as_ref());
40+
match norm_path.strip_prefix(norm_basedir) {
41+
Ok(relpath) => wrap_path(relpath),
42+
_ => wrap_path(path),
43+
}
44+
} else {
45+
wrap_path(path)
46+
}
47+
}
48+
49+
fn wrap_path(path: &Path) -> CargoResult<String> {
50+
path.to_str()
51+
.ok_or_else(|| internal(format!("path `{:?}` not utf-8", path)))
4652
.map(|f| f.replace(" ", "\\ "))
4753
}
4854

tests/testsuite/build_script.rs

Lines changed: 64 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use cargo_test_support::compare::assert_match_exact;
44
use cargo_test_support::paths::CargoPathExt;
55
use cargo_test_support::registry::Package;
66
use cargo_test_support::tools;
7-
use cargo_test_support::{basic_manifest, cross_compile, is_coarse_mtime, project};
7+
use cargo_test_support::{basic_manifest, cross_compile, is_coarse_mtime, project, project_in};
88
use cargo_test_support::{rustc_host, sleep_ms, slow_cpu_multiplier, symlink_supported};
99
use cargo_util::paths::remove_dir_all;
1010
use std::env;
@@ -3178,6 +3178,69 @@ fn generate_good_d_files() {
31783178
.any(|v| v == "barkbarkbark" || v == "build.rs"));
31793179
}
31803180

3181+
#[cargo_test]
3182+
fn generate_good_d_files_for_external_tools() {
3183+
// This tests having a relative paths going out of the
3184+
// project root in config's dep-info-basedir
3185+
let p = project_in("rust_things")
3186+
.file(
3187+
"awoo/Cargo.toml",
3188+
r#"
3189+
[project]
3190+
name = "awoo"
3191+
version = "0.5.0"
3192+
build = "build.rs"
3193+
"#,
3194+
)
3195+
.file("awoo/src/lib.rs", "")
3196+
.file(
3197+
"awoo/build.rs",
3198+
r#"
3199+
fn main() {
3200+
println!("cargo:rerun-if-changed=build.rs");
3201+
println!("cargo:rerun-if-changed=barkbarkbark");
3202+
}
3203+
"#,
3204+
)
3205+
.file(
3206+
"Cargo.toml",
3207+
r#"
3208+
[project]
3209+
name = "meow"
3210+
version = "0.5.0"
3211+
[dependencies]
3212+
awoo = { path = "awoo" }
3213+
"#,
3214+
)
3215+
.file("src/main.rs", "fn main() {}")
3216+
.file(
3217+
".cargo/config.toml",
3218+
r#"
3219+
[build]
3220+
dep-info-basedir="../.."
3221+
"#,
3222+
)
3223+
.build();
3224+
3225+
p.cargo("build -v").run();
3226+
3227+
let dot_d_path = p.bin("meow").with_extension("d");
3228+
let dot_d = fs::read_to_string(&dot_d_path).unwrap();
3229+
3230+
println!("*.d file content with dep-info-basedir*: {}", &dot_d);
3231+
3232+
assert_match_exact(
3233+
concat!(
3234+
"rust_things/foo/target/debug/meow[EXE]:",
3235+
" rust_things/foo/awoo/barkbarkbark",
3236+
" rust_things/foo/awoo/build.rs",
3237+
" rust_things/foo/awoo/src/lib.rs",
3238+
" rust_things/foo/src/main.rs",
3239+
),
3240+
&dot_d,
3241+
);
3242+
}
3243+
31813244
#[cargo_test]
31823245
fn rebuild_only_on_explicit_paths() {
31833246
let p = project()

0 commit comments

Comments
 (0)