mirror of
https://github.com/rust-lang/cargo
synced 2024-10-30 22:57:17 +00:00
69eb49194b
See https://doc.crates.io/contrib/implementation/console.html#style By fixing existing cases, we make it more likely people will copy a case they should. I left out multi-sentance cases because I was unsure how to handle those r? @weighanglo
3031 lines
86 KiB
Rust
3031 lines
86 KiB
Rust
//! Tests specific to artifact dependencies, designated using
|
|
//! the new `dep = { artifact = "bin", … }` syntax in manifests.
|
|
|
|
use cargo_test_support::compare::match_exact;
|
|
use cargo_test_support::registry::{Package, RegistryBuilder};
|
|
use cargo_test_support::{
|
|
basic_bin_manifest, basic_manifest, cross_compile, project, publish, registry, rustc_host,
|
|
Project,
|
|
};
|
|
|
|
#[cargo_test]
|
|
fn check_with_invalid_artifact_dependency() {
|
|
// invalid name
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "0.0.0"
|
|
authors = []
|
|
resolver = "2"
|
|
|
|
[dependencies]
|
|
bar = { path = "bar/", artifact = "unknown" }
|
|
"#,
|
|
)
|
|
.file("src/lib.rs", "extern crate bar;") // this would fail but we don't get there, artifacts are no libs
|
|
.file("bar/Cargo.toml", &basic_manifest("bar", "0.0.1"))
|
|
.file("bar/src/lib.rs", "")
|
|
.build();
|
|
p.cargo("check -Z bindeps")
|
|
.masquerade_as_nightly_cargo(&["bindeps"])
|
|
.with_stderr(
|
|
"\
|
|
[ERROR] failed to parse manifest at `[..]/Cargo.toml`
|
|
|
|
Caused by:
|
|
'unknown' is not a valid artifact specifier
|
|
",
|
|
)
|
|
.with_status(101)
|
|
.run();
|
|
|
|
fn run_cargo_with_and_without_bindeps_feature(
|
|
p: &Project,
|
|
cmd: &str,
|
|
assert: &dyn Fn(&mut cargo_test_support::Execs),
|
|
) {
|
|
assert(
|
|
p.cargo(&format!("{} -Z bindeps", cmd))
|
|
.masquerade_as_nightly_cargo(&["bindeps"]),
|
|
);
|
|
assert(&mut p.cargo(cmd));
|
|
}
|
|
|
|
// lib specified without artifact
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "0.0.0"
|
|
authors = []
|
|
|
|
[dependencies]
|
|
bar = { path = "bar/", lib = true }
|
|
"#,
|
|
)
|
|
.file("src/lib.rs", "")
|
|
.file("bar/Cargo.toml", &basic_manifest("bar", "0.0.1"))
|
|
.file("bar/src/lib.rs", "")
|
|
.build();
|
|
run_cargo_with_and_without_bindeps_feature(&p, "check", &|cargo| {
|
|
cargo
|
|
.with_stderr(
|
|
"\
|
|
[ERROR] failed to parse manifest at `[..]/Cargo.toml`
|
|
|
|
Caused by:
|
|
'lib' specifier cannot be used without an 'artifact = …' value (bar)
|
|
",
|
|
)
|
|
.with_status(101)
|
|
.run();
|
|
});
|
|
|
|
// target specified without artifact
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "0.0.0"
|
|
authors = []
|
|
|
|
[dependencies]
|
|
bar = { path = "bar/", target = "target" }
|
|
"#,
|
|
)
|
|
.file("src/lib.rs", "")
|
|
.file("bar/Cargo.toml", &basic_manifest("bar", "0.0.1"))
|
|
.file("bar/src/lib.rs", "")
|
|
.build();
|
|
run_cargo_with_and_without_bindeps_feature(&p, "check", &|cargo| {
|
|
cargo
|
|
.with_stderr(
|
|
"\
|
|
[ERROR] failed to parse manifest at `[..]/Cargo.toml`
|
|
|
|
Caused by:
|
|
'target' specifier cannot be used without an 'artifact = …' value (bar)
|
|
",
|
|
)
|
|
.with_status(101)
|
|
.run();
|
|
})
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn check_with_invalid_target_triple() {
|
|
// invalid name
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "0.0.0"
|
|
authors = []
|
|
resolver = "2"
|
|
|
|
[dependencies]
|
|
bar = { path = "bar/", artifact = "bin", target = "unknown-target-triple" }
|
|
"#,
|
|
)
|
|
.file("src/lib.rs", "")
|
|
.file("bar/Cargo.toml", &basic_manifest("bar", "0.0.1"))
|
|
.file("bar/src/main.rs", "fn main() {}")
|
|
.build();
|
|
p.cargo("check -Z bindeps")
|
|
.masquerade_as_nightly_cargo(&["bindeps"])
|
|
.with_stderr_contains(
|
|
r#"[..]Could not find specification for target "unknown-target-triple"[..]"#,
|
|
)
|
|
.with_status(101)
|
|
.run();
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn build_without_nightly_aborts_with_error() {
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "0.0.0"
|
|
authors = []
|
|
resolver = "2"
|
|
|
|
[dependencies]
|
|
bar = { path = "bar/", artifact = "bin" }
|
|
"#,
|
|
)
|
|
.file("src/lib.rs", "extern crate bar;")
|
|
.file("bar/Cargo.toml", &basic_manifest("bar", "0.0.1"))
|
|
.file("bar/src/lib.rs", "")
|
|
.build();
|
|
p.cargo("check")
|
|
.with_status(101)
|
|
.with_stderr(
|
|
"\
|
|
[ERROR] failed to parse manifest at [..]
|
|
|
|
Caused by:
|
|
`artifact = …` requires `-Z bindeps` (bar)
|
|
",
|
|
)
|
|
.run();
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn disallow_artifact_and_no_artifact_dep_to_same_package_within_the_same_dep_category() {
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "0.0.0"
|
|
authors = []
|
|
resolver = "2"
|
|
|
|
[dependencies]
|
|
bar = { path = "bar/", artifact = "bin" }
|
|
bar_stable = { path = "bar/", package = "bar" }
|
|
"#,
|
|
)
|
|
.file("src/lib.rs", "")
|
|
.file("bar/Cargo.toml", &basic_bin_manifest("bar"))
|
|
.file("bar/src/main.rs", "fn main() {}")
|
|
.build();
|
|
p.cargo("check -Z bindeps")
|
|
.masquerade_as_nightly_cargo(&["bindeps"])
|
|
.with_status(101)
|
|
.with_stderr("\
|
|
[WARNING] foo v0.0.0 ([CWD]) ignoring invalid dependency `bar_stable` which is missing a lib target
|
|
[ERROR] the crate `foo v0.0.0 ([CWD])` depends on crate `bar v0.5.0 ([CWD]/bar)` multiple times with different names",
|
|
)
|
|
.run();
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn features_are_unified_among_lib_and_bin_dep_of_same_target() {
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "0.0.1"
|
|
authors = []
|
|
resolver = "2"
|
|
|
|
[dependencies.d1]
|
|
path = "d1"
|
|
features = ["d1f1"]
|
|
artifact = "bin"
|
|
lib = true
|
|
|
|
[dependencies.d2]
|
|
path = "d2"
|
|
features = ["d2f2"]
|
|
"#,
|
|
)
|
|
.file(
|
|
"src/main.rs",
|
|
r#"
|
|
fn main() {
|
|
d1::f1();
|
|
d1::f2();
|
|
d2::f1();
|
|
d2::f2();
|
|
}
|
|
"#,
|
|
)
|
|
.file(
|
|
"d1/Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "d1"
|
|
version = "0.0.1"
|
|
authors = []
|
|
|
|
[features]
|
|
d1f1 = ["d2"]
|
|
|
|
[dependencies.d2]
|
|
path = "../d2"
|
|
features = ["d2f1"]
|
|
optional = true
|
|
"#,
|
|
)
|
|
.file(
|
|
"d1/src/main.rs",
|
|
r#"fn main() {
|
|
#[cfg(feature = "d1f1")]
|
|
d2::f1();
|
|
|
|
// Using f2 is only possible as features are unififed across the same target.
|
|
// Our own manifest would only enable f1, and f2 comes in because a parent crate
|
|
// enables the feature in its manifest.
|
|
#[cfg(feature = "d1f1")]
|
|
d2::f2();
|
|
}"#,
|
|
)
|
|
.file(
|
|
"d1/src/lib.rs",
|
|
r#"
|
|
#[cfg(feature = "d2")]
|
|
extern crate d2;
|
|
/// Importing f2 here shouldn't be possible as unless features are unified.
|
|
#[cfg(feature = "d1f1")]
|
|
pub use d2::{f1, f2};
|
|
"#,
|
|
)
|
|
.file(
|
|
"d2/Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "d2"
|
|
version = "0.0.1"
|
|
authors = []
|
|
|
|
[features]
|
|
d2f1 = []
|
|
d2f2 = []
|
|
"#,
|
|
)
|
|
.file(
|
|
"d2/src/lib.rs",
|
|
r#"
|
|
#[cfg(feature = "d2f1")] pub fn f1() {}
|
|
#[cfg(feature = "d2f2")] pub fn f2() {}
|
|
"#,
|
|
)
|
|
.build();
|
|
|
|
p.cargo("build -Z bindeps")
|
|
.masquerade_as_nightly_cargo(&["bindeps"])
|
|
.with_stderr(
|
|
"\
|
|
[COMPILING] d2 v0.0.1 ([CWD]/d2)
|
|
[COMPILING] d1 v0.0.1 ([CWD]/d1)
|
|
[COMPILING] foo v0.0.1 ([CWD])
|
|
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
|
|
",
|
|
)
|
|
.run();
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn features_are_not_unified_among_lib_and_bin_dep_of_different_target() {
|
|
if cross_compile::disabled() {
|
|
return;
|
|
}
|
|
let target = cross_compile::alternate();
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
&r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "0.0.1"
|
|
authors = []
|
|
resolver = "2"
|
|
|
|
[dependencies.d1]
|
|
path = "d1"
|
|
features = ["d1f1"]
|
|
artifact = "bin"
|
|
lib = true
|
|
target = "$TARGET"
|
|
|
|
[dependencies.d2]
|
|
path = "d2"
|
|
features = ["d2f2"]
|
|
"#
|
|
.replace("$TARGET", target),
|
|
)
|
|
.file(
|
|
"src/main.rs",
|
|
r#"
|
|
fn main() {
|
|
// the lib = true part always builds for our current target, unifying dependencies
|
|
d1::d2::f1();
|
|
d1::d2::f2();
|
|
d2::f1();
|
|
d2::f2();
|
|
}
|
|
"#,
|
|
)
|
|
.file(
|
|
"d1/Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "d1"
|
|
version = "0.0.1"
|
|
authors = []
|
|
|
|
[features]
|
|
d1f1 = ["d2"]
|
|
|
|
[dependencies.d2]
|
|
path = "../d2"
|
|
features = ["d2f1"]
|
|
optional = true
|
|
"#,
|
|
)
|
|
.file("d1/src/main.rs", r#"fn main() {
|
|
// f1 we set ourselves
|
|
d2::f1();
|
|
// As 'main' is only compiled as part of the artifact dependency and since that is not unified
|
|
// if the target differs, trying to access f2 is a compile time error as the feature isn't enabled in our dependency tree.
|
|
d2::f2();
|
|
}"#)
|
|
.file(
|
|
"d1/src/lib.rs",
|
|
r#"
|
|
#[cfg(feature = "d2")]
|
|
pub extern crate d2;
|
|
"#,
|
|
)
|
|
.file(
|
|
"d2/Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "d2"
|
|
version = "0.0.1"
|
|
authors = []
|
|
|
|
[features]
|
|
d2f1 = []
|
|
d2f2 = []
|
|
"#,
|
|
)
|
|
.file(
|
|
"d2/src/lib.rs",
|
|
r#"
|
|
#[cfg(feature = "d2f1")] pub fn f1() {}
|
|
#[cfg(feature = "d2f2")] pub fn f2() {}
|
|
"#,
|
|
)
|
|
.build();
|
|
|
|
p.cargo("build -Z bindeps")
|
|
.masquerade_as_nightly_cargo(&["bindeps"])
|
|
.with_status(101)
|
|
.with_stderr_contains(
|
|
"error[E0425]: cannot find function `f2` in crate `d2`\n --> d1/src/main.rs:6:17",
|
|
)
|
|
.run();
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn feature_resolution_works_for_cfg_target_specification() {
|
|
if cross_compile::disabled() {
|
|
return;
|
|
}
|
|
let target = cross_compile::alternate();
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
&r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "0.0.1"
|
|
authors = []
|
|
resolver = "2"
|
|
|
|
[dependencies.d1]
|
|
path = "d1"
|
|
artifact = "bin"
|
|
target = "$TARGET"
|
|
"#
|
|
.replace("$TARGET", target),
|
|
)
|
|
.file(
|
|
"src/main.rs",
|
|
r#"
|
|
fn main() {
|
|
let _b = include_bytes!(env!("CARGO_BIN_FILE_D1"));
|
|
}
|
|
"#,
|
|
)
|
|
.file(
|
|
"d1/Cargo.toml",
|
|
&r#"
|
|
[package]
|
|
name = "d1"
|
|
version = "0.0.1"
|
|
authors = []
|
|
|
|
[target.'$TARGET'.dependencies]
|
|
d2 = { path = "../d2" }
|
|
"#
|
|
.replace("$TARGET", target),
|
|
)
|
|
.file(
|
|
"d1/src/main.rs",
|
|
r#"fn main() {
|
|
d1::f();
|
|
}"#,
|
|
)
|
|
.file("d1/build.rs", r#"fn main() { }"#)
|
|
.file(
|
|
"d1/src/lib.rs",
|
|
&r#"pub fn f() {
|
|
#[cfg(target = "$TARGET")]
|
|
d2::f();
|
|
}
|
|
"#
|
|
.replace("$TARGET", target),
|
|
)
|
|
.file(
|
|
"d2/Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "d2"
|
|
version = "0.0.1"
|
|
authors = []
|
|
"#,
|
|
)
|
|
.file("d2/build.rs", r#"fn main() { }"#)
|
|
.file("d2/src/lib.rs", "pub fn f() {}")
|
|
.build();
|
|
|
|
p.cargo("test -Z bindeps")
|
|
.masquerade_as_nightly_cargo(&["bindeps"])
|
|
.run();
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn build_script_with_bin_artifacts() {
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "0.0.0"
|
|
authors = []
|
|
resolver = "2"
|
|
|
|
[build-dependencies]
|
|
bar = { path = "bar/", artifact = ["bin", "staticlib", "cdylib"] }
|
|
"#,
|
|
)
|
|
.file("src/lib.rs", "")
|
|
.file("build.rs", r#"
|
|
fn main() {
|
|
let baz: std::path::PathBuf = std::env::var("CARGO_BIN_FILE_BAR_baz").expect("CARGO_BIN_FILE_BAR_baz").into();
|
|
println!("{}", baz.display());
|
|
assert!(&baz.is_file());
|
|
|
|
let lib: std::path::PathBuf = std::env::var("CARGO_STATICLIB_FILE_BAR_bar").expect("CARGO_STATICLIB_FILE_BAR_bar").into();
|
|
println!("{}", lib.display());
|
|
assert!(&lib.is_file());
|
|
|
|
let lib: std::path::PathBuf = std::env::var("CARGO_CDYLIB_FILE_BAR_bar").expect("CARGO_CDYLIB_FILE_BAR_bar").into();
|
|
println!("{}", lib.display());
|
|
assert!(&lib.is_file());
|
|
|
|
let dir: std::path::PathBuf = std::env::var("CARGO_BIN_DIR_BAR").expect("CARGO_BIN_DIR_BAR").into();
|
|
println!("{}", dir.display());
|
|
assert!(dir.is_dir());
|
|
|
|
let bar: std::path::PathBuf = std::env::var("CARGO_BIN_FILE_BAR").expect("CARGO_BIN_FILE_BAR").into();
|
|
println!("{}", bar.display());
|
|
assert!(&bar.is_file());
|
|
|
|
let bar2: std::path::PathBuf = std::env::var("CARGO_BIN_FILE_BAR_bar").expect("CARGO_BIN_FILE_BAR_bar").into();
|
|
println!("{}", bar2.display());
|
|
assert_eq!(bar, bar2);
|
|
}
|
|
"#)
|
|
.file(
|
|
"bar/Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "bar"
|
|
version = "0.5.0"
|
|
authors = []
|
|
|
|
[lib]
|
|
crate-type = ["staticlib", "cdylib"]
|
|
"#,
|
|
)
|
|
// compilation target is native for build scripts unless overridden
|
|
.file("bar/src/bin/bar.rs", &format!(r#"fn main() {{ assert_eq!(std::env::var("TARGET").unwrap(), "{}"); }}"#, cross_compile::native()))
|
|
.file("bar/src/bin/baz.rs", "fn main() {}")
|
|
.file("bar/src/lib.rs", "")
|
|
.build();
|
|
p.cargo("build -Z bindeps")
|
|
.masquerade_as_nightly_cargo(&["bindeps"])
|
|
.with_stderr_contains("[COMPILING] foo [..]")
|
|
.with_stderr_contains("[COMPILING] bar v0.5.0 ([CWD]/bar)")
|
|
.with_stderr_contains("[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]")
|
|
.run();
|
|
|
|
let build_script_output = build_script_output_string(&p, "foo");
|
|
let msg = "we need the binary directory for this artifact along with all binary paths";
|
|
if cfg!(target_env = "msvc") {
|
|
match_exact(
|
|
"[..]/artifact/bar-[..]/bin/baz.exe\n\
|
|
[..]/artifact/bar-[..]/staticlib/bar-[..].lib\n\
|
|
[..]/artifact/bar-[..]/cdylib/bar.dll\n\
|
|
[..]/artifact/bar-[..]/bin\n\
|
|
[..]/artifact/bar-[..]/bin/bar.exe\n\
|
|
[..]/artifact/bar-[..]/bin/bar.exe",
|
|
&build_script_output,
|
|
msg,
|
|
"",
|
|
None,
|
|
)
|
|
.unwrap();
|
|
} else {
|
|
match_exact(
|
|
"[..]/artifact/bar-[..]/bin/baz-[..]\n\
|
|
[..]/artifact/bar-[..]/staticlib/libbar-[..].a\n\
|
|
[..]/artifact/bar-[..]/cdylib/[..]bar.[..]\n\
|
|
[..]/artifact/bar-[..]/bin\n\
|
|
[..]/artifact/bar-[..]/bin/bar-[..]\n\
|
|
[..]/artifact/bar-[..]/bin/bar-[..]",
|
|
&build_script_output,
|
|
msg,
|
|
"",
|
|
None,
|
|
)
|
|
.unwrap();
|
|
}
|
|
|
|
assert!(
|
|
!p.bin("bar").is_file(),
|
|
"artifacts are located in their own directory, exclusively, and won't be lifted up"
|
|
);
|
|
assert!(!p.bin("baz").is_file(),);
|
|
assert_artifact_executable_output(&p, "debug", "bar", "bar");
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn build_script_with_bin_artifact_and_lib_false() {
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "0.0.0"
|
|
authors = []
|
|
resolver = "2"
|
|
|
|
[build-dependencies]
|
|
bar = { path = "bar/", artifact = "bin" }
|
|
"#,
|
|
)
|
|
.file("src/lib.rs", "")
|
|
.file(
|
|
"build.rs",
|
|
r#"
|
|
fn main() {
|
|
bar::doit()
|
|
}
|
|
"#,
|
|
)
|
|
.file("bar/Cargo.toml", &basic_bin_manifest("bar"))
|
|
.file("bar/src/main.rs", "fn main() { bar::doit(); }")
|
|
.file(
|
|
"bar/src/lib.rs",
|
|
r#"
|
|
pub fn doit() {
|
|
panic!("sentinel");
|
|
}
|
|
"#,
|
|
)
|
|
.build();
|
|
p.cargo("build -Z bindeps")
|
|
.masquerade_as_nightly_cargo(&["bindeps"])
|
|
.with_status(101)
|
|
.with_stderr_does_not_contain("[..]sentinel[..]")
|
|
.run();
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn lib_with_bin_artifact_and_lib_false() {
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "0.0.0"
|
|
authors = []
|
|
resolver = "2"
|
|
|
|
[dependencies]
|
|
bar = { path = "bar/", artifact = "bin" }
|
|
"#,
|
|
)
|
|
.file(
|
|
"src/lib.rs",
|
|
r#"
|
|
pub fn foo() {
|
|
bar::doit()
|
|
}"#,
|
|
)
|
|
.file("bar/Cargo.toml", &basic_bin_manifest("bar"))
|
|
.file("bar/src/main.rs", "fn main() { bar::doit(); }")
|
|
.file(
|
|
"bar/src/lib.rs",
|
|
r#"
|
|
pub fn doit() {
|
|
panic!("sentinel");
|
|
}
|
|
"#,
|
|
)
|
|
.build();
|
|
p.cargo("build -Z bindeps")
|
|
.masquerade_as_nightly_cargo(&["bindeps"])
|
|
.with_status(101)
|
|
.with_stderr_does_not_contain("[..]sentinel[..]")
|
|
.run();
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn build_script_with_selected_dashed_bin_artifact_and_lib_true() {
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "0.0.0"
|
|
authors = []
|
|
resolver = "2"
|
|
|
|
[build-dependencies]
|
|
bar-baz = { path = "bar/", artifact = "bin:baz-suffix", lib = true }
|
|
"#,
|
|
)
|
|
.file("src/lib.rs", "")
|
|
.file("build.rs", r#"
|
|
fn main() {
|
|
bar_baz::print_env()
|
|
}
|
|
"#)
|
|
.file(
|
|
"bar/Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "bar-baz"
|
|
version = "0.5.0"
|
|
authors = []
|
|
|
|
[[bin]]
|
|
name = "bar"
|
|
|
|
[[bin]]
|
|
name = "baz-suffix"
|
|
"#,
|
|
)
|
|
.file("bar/src/main.rs", "fn main() {}")
|
|
.file("bar/src/lib.rs", r#"
|
|
pub fn print_env() {
|
|
let dir: std::path::PathBuf = std::env::var("CARGO_BIN_DIR_BAR_BAZ").expect("CARGO_BIN_DIR_BAR_BAZ").into();
|
|
let bin: std::path::PathBuf = std::env::var("CARGO_BIN_FILE_BAR_BAZ_baz-suffix").expect("CARGO_BIN_FILE_BAR_BAZ_baz-suffix").into();
|
|
println!("{}", dir.display());
|
|
println!("{}", bin.display());
|
|
assert!(dir.is_dir());
|
|
assert!(&bin.is_file());
|
|
assert!(std::env::var("CARGO_BIN_FILE_BAR_BAZ").is_err(), "CARGO_BIN_FILE_BAR_BAZ isn't set due to name mismatch");
|
|
assert!(std::env::var("CARGO_BIN_FILE_BAR_BAZ_bar").is_err(), "CARGO_BIN_FILE_BAR_BAZ_bar isn't set as binary isn't selected");
|
|
}
|
|
"#)
|
|
.build();
|
|
p.cargo("build -Z bindeps")
|
|
.masquerade_as_nightly_cargo(&["bindeps"])
|
|
.with_stderr(
|
|
"\
|
|
[COMPILING] bar-baz v0.5.0 ([CWD]/bar)
|
|
[COMPILING] foo [..]
|
|
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]",
|
|
)
|
|
.run();
|
|
|
|
let build_script_output = build_script_output_string(&p, "foo");
|
|
let msg = "we need the binary directory for this artifact and the binary itself";
|
|
|
|
if cfg!(target_env = "msvc") {
|
|
cargo_test_support::compare::match_exact(
|
|
&format!(
|
|
"[..]/artifact/bar-baz-[..]/bin\n\
|
|
[..]/artifact/bar-baz-[..]/bin/baz_suffix{}",
|
|
std::env::consts::EXE_SUFFIX,
|
|
),
|
|
&build_script_output,
|
|
msg,
|
|
"",
|
|
None,
|
|
)
|
|
.unwrap();
|
|
} else {
|
|
cargo_test_support::compare::match_exact(
|
|
"[..]/artifact/bar-baz-[..]/bin\n\
|
|
[..]/artifact/bar-baz-[..]/bin/baz_suffix-[..]",
|
|
&build_script_output,
|
|
msg,
|
|
"",
|
|
None,
|
|
)
|
|
.unwrap();
|
|
}
|
|
|
|
assert!(
|
|
!p.bin("bar").is_file(),
|
|
"artifacts are located in their own directory, exclusively, and won't be lifted up"
|
|
);
|
|
assert_artifact_executable_output(&p, "debug", "bar", "baz_suffix");
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn lib_with_selected_dashed_bin_artifact_and_lib_true() {
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "0.0.0"
|
|
authors = []
|
|
resolver = "2"
|
|
|
|
[dependencies]
|
|
bar-baz = { path = "bar/", artifact = ["bin:baz-suffix", "staticlib", "cdylib"], lib = true }
|
|
"#,
|
|
)
|
|
.file(
|
|
"src/lib.rs",
|
|
r#"
|
|
pub fn foo() {
|
|
bar_baz::exists();
|
|
|
|
env!("CARGO_BIN_DIR_BAR_BAZ");
|
|
let _b = include_bytes!(env!("CARGO_BIN_FILE_BAR_BAZ_baz-suffix"));
|
|
let _b = include_bytes!(env!("CARGO_STATICLIB_FILE_BAR_BAZ"));
|
|
let _b = include_bytes!(env!("CARGO_STATICLIB_FILE_BAR_BAZ_bar-baz"));
|
|
let _b = include_bytes!(env!("CARGO_CDYLIB_FILE_BAR_BAZ"));
|
|
let _b = include_bytes!(env!("CARGO_CDYLIB_FILE_BAR_BAZ_bar-baz"));
|
|
}
|
|
"#,
|
|
)
|
|
.file(
|
|
"bar/Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "bar-baz"
|
|
version = "0.5.0"
|
|
authors = []
|
|
|
|
[lib]
|
|
crate-type = ["rlib", "staticlib", "cdylib"]
|
|
|
|
[[bin]]
|
|
name = "bar"
|
|
|
|
[[bin]]
|
|
name = "baz-suffix"
|
|
"#,
|
|
)
|
|
.file("bar/src/main.rs", "fn main() {}")
|
|
.file("bar/src/lib.rs", "pub fn exists() {}")
|
|
.build();
|
|
p.cargo("build -Z bindeps")
|
|
.masquerade_as_nightly_cargo(&["bindeps"])
|
|
.with_stderr(
|
|
"\
|
|
[COMPILING] bar-baz v0.5.0 ([CWD]/bar)
|
|
[COMPILING] foo [..]
|
|
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]",
|
|
)
|
|
.run();
|
|
|
|
assert!(
|
|
!p.bin("bar").is_file(),
|
|
"artifacts are located in their own directory, exclusively, and won't be lifted up"
|
|
);
|
|
assert_artifact_executable_output(&p, "debug", "bar", "baz_suffix");
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn allow_artifact_and_no_artifact_dep_to_same_package_within_different_dep_categories() {
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "0.0.0"
|
|
authors = []
|
|
resolver = "2"
|
|
|
|
[dependencies]
|
|
bar = { path = "bar/", artifact = "bin" }
|
|
|
|
[dev-dependencies]
|
|
bar = { path = "bar/", package = "bar" }
|
|
"#,
|
|
)
|
|
.file(
|
|
"src/lib.rs",
|
|
r#"
|
|
#[cfg(test)] extern crate bar;
|
|
pub fn foo() {
|
|
env!("CARGO_BIN_DIR_BAR");
|
|
let _b = include_bytes!(env!("CARGO_BIN_FILE_BAR"));
|
|
}"#,
|
|
)
|
|
.file("bar/Cargo.toml", &basic_bin_manifest("bar"))
|
|
.file("bar/src/main.rs", "fn main() {}")
|
|
.file("bar/src/lib.rs", "")
|
|
.build();
|
|
p.cargo("test -Z bindeps")
|
|
.masquerade_as_nightly_cargo(&["bindeps"])
|
|
.with_stderr_contains("[COMPILING] bar v0.5.0 ([CWD]/bar)")
|
|
.with_stderr_contains("[FINISHED] test [unoptimized + debuginfo] target(s) in [..]")
|
|
.run();
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn normal_build_deps_are_picked_up_in_presence_of_an_artifact_build_dep_to_the_same_package() {
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "0.0.0"
|
|
authors = []
|
|
resolver = "2"
|
|
|
|
[dependencies]
|
|
bar = { path = "bar", artifact = "bin:bar" }
|
|
|
|
[build-dependencies]
|
|
bar = { path = "bar" }
|
|
"#,
|
|
)
|
|
.file("build.rs", "fn main() { bar::f(); }")
|
|
.file(
|
|
"src/lib.rs",
|
|
r#"
|
|
pub fn foo() {
|
|
env!("CARGO_BIN_DIR_BAR");
|
|
let _b = include_bytes!(env!("CARGO_BIN_FILE_BAR"));
|
|
}"#,
|
|
)
|
|
.file("bar/Cargo.toml", &basic_bin_manifest("bar"))
|
|
.file("bar/src/main.rs", "fn main() {}")
|
|
.file("bar/src/lib.rs", "pub fn f() {}")
|
|
.build();
|
|
p.cargo("check -Z bindeps")
|
|
.masquerade_as_nightly_cargo(&["bindeps"])
|
|
.run();
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn disallow_using_example_binaries_as_artifacts() {
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "0.0.0"
|
|
authors = []
|
|
resolver = "2"
|
|
|
|
[dependencies]
|
|
bar = { path = "bar/", artifact = "bin:one-example" }
|
|
"#,
|
|
)
|
|
.file("src/lib.rs", "")
|
|
.file("bar/Cargo.toml", &basic_bin_manifest("bar"))
|
|
.file("bar/src/main.rs", "fn main() {}")
|
|
.file("bar/examples/one-example.rs", "fn main() {}")
|
|
.build();
|
|
p.cargo("build -Z bindeps")
|
|
.masquerade_as_nightly_cargo(&["bindeps"])
|
|
.with_status(101)
|
|
.with_stderr(r#"[ERROR] dependency `bar` in package `foo` requires a `bin:one-example` artifact to be present."#)
|
|
.run();
|
|
}
|
|
|
|
/// From RFC 3028
|
|
///
|
|
/// > You may also specify separate dependencies with different artifact values, as well as
|
|
/// dependencies on the same crate without artifact specified; for instance, you may have a
|
|
/// build dependency on the binary of a crate and a normal dependency on the Rust library of the same crate.
|
|
#[cargo_test]
|
|
fn allow_artifact_and_non_artifact_dependency_to_same_crate() {
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "0.0.0"
|
|
authors = []
|
|
resolver = "2"
|
|
|
|
[build-dependencies]
|
|
bar = { path = "bar/", artifact = "bin" }
|
|
|
|
[dependencies]
|
|
bar = { path = "bar/" }
|
|
"#,
|
|
)
|
|
.file("src/lib.rs", r#"
|
|
pub fn foo() {
|
|
bar::doit();
|
|
assert!(option_env!("CARGO_BIN_FILE_BAR").is_none());
|
|
}"#)
|
|
.file(
|
|
"build.rs",
|
|
r#"
|
|
fn main() {
|
|
assert!(option_env!("CARGO_BIN_FILE_BAR").is_none(), "no environment variables at build time");
|
|
std::process::Command::new(std::env::var("CARGO_BIN_FILE_BAR").expect("BAR present")).status().unwrap();
|
|
}"#,
|
|
)
|
|
.file("bar/Cargo.toml", &basic_bin_manifest("bar"))
|
|
.file("bar/src/main.rs", "fn main() {}")
|
|
.file("bar/src/lib.rs", "pub fn doit() {}")
|
|
.build();
|
|
|
|
p.cargo("check -Z bindeps")
|
|
.masquerade_as_nightly_cargo(&["bindeps"])
|
|
.with_stderr_contains("[COMPILING] bar [..]")
|
|
.with_stderr_contains("[COMPILING] foo [..]")
|
|
.run();
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn build_script_deps_adopt_specified_target_unconditionally() {
|
|
if cross_compile::disabled() {
|
|
return;
|
|
}
|
|
|
|
let target = cross_compile::alternate();
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
&format!(
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "0.0.0"
|
|
authors = []
|
|
resolver = "2"
|
|
|
|
[build-dependencies.bar]
|
|
path = "bar/"
|
|
artifact = "bin"
|
|
target = "{}"
|
|
"#,
|
|
target
|
|
),
|
|
)
|
|
.file("src/lib.rs", "")
|
|
.file("build.rs", r#"
|
|
fn main() {
|
|
let bar: std::path::PathBuf = std::env::var("CARGO_BIN_FILE_BAR").expect("CARGO_BIN_FILE_BAR").into();
|
|
assert!(&bar.is_file());
|
|
}"#)
|
|
.file("bar/Cargo.toml", &basic_bin_manifest("bar"))
|
|
.file("bar/src/main.rs", "fn main() {}")
|
|
.file("bar/src/lib.rs", "pub fn doit() {}")
|
|
.build();
|
|
|
|
p.cargo("check -v -Z bindeps")
|
|
.masquerade_as_nightly_cargo(&["bindeps"])
|
|
.with_stderr_does_not_contain(format!(
|
|
"[RUNNING] `rustc --crate-name build_script_build build.rs [..]--target {} [..]",
|
|
target
|
|
))
|
|
.with_stderr_contains("[RUNNING] `rustc --crate-name build_script_build build.rs [..]")
|
|
.with_stderr_contains(format!(
|
|
"[RUNNING] `rustc --crate-name bar bar/src/lib.rs [..]--target {} [..]",
|
|
target
|
|
))
|
|
.with_stderr_contains(format!(
|
|
"[RUNNING] `rustc --crate-name bar bar/src/main.rs [..]--target {} [..]",
|
|
target
|
|
))
|
|
.with_stderr_does_not_contain(format!(
|
|
"[RUNNING] `rustc --crate-name foo [..]--target {} [..]",
|
|
target
|
|
))
|
|
.with_stderr_contains("[RUNNING] `rustc --crate-name foo [..]")
|
|
.run();
|
|
}
|
|
|
|
/// inverse RFC-3176
|
|
#[cargo_test]
|
|
fn build_script_deps_adopt_do_not_allow_multiple_targets_under_different_name_and_same_version() {
|
|
if cross_compile::disabled() {
|
|
return;
|
|
}
|
|
|
|
let alternate = cross_compile::alternate();
|
|
let native = cross_compile::native();
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
&format!(
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "0.0.0"
|
|
authors = []
|
|
resolver = "2"
|
|
|
|
[build-dependencies.bar]
|
|
path = "bar/"
|
|
artifact = "bin"
|
|
target = "{}"
|
|
|
|
[build-dependencies.bar-native]
|
|
package = "bar"
|
|
path = "bar/"
|
|
artifact = "bin"
|
|
target = "{}"
|
|
"#,
|
|
alternate,
|
|
native
|
|
),
|
|
)
|
|
.file("src/lib.rs", "")
|
|
.file("build.rs", r#"
|
|
fn main() {
|
|
let bar: std::path::PathBuf = std::env::var("CARGO_BIN_FILE_BAR").expect("CARGO_BIN_FILE_BAR").into();
|
|
assert!(&bar.is_file());
|
|
let bar_native: std::path::PathBuf = std::env::var("CARGO_BIN_FILE_BAR_NATIVE_bar").expect("CARGO_BIN_FILE_BAR_NATIVE_bar").into();
|
|
assert!(&bar_native.is_file());
|
|
assert_ne!(bar_native, bar, "should build different binaries due to different targets");
|
|
}"#)
|
|
.file("bar/Cargo.toml", &basic_bin_manifest("bar"))
|
|
.file("bar/src/main.rs", "fn main() {}")
|
|
.build();
|
|
|
|
p.cargo("check -v -Z bindeps")
|
|
.masquerade_as_nightly_cargo(&["bindeps"])
|
|
.with_status(101)
|
|
.with_stderr(format!(
|
|
"error: the crate `foo v0.0.0 ([CWD])` depends on crate `bar v0.5.0 ([CWD]/bar)` multiple times with different names",
|
|
))
|
|
.run();
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn non_build_script_deps_adopt_specified_target_unconditionally() {
|
|
if cross_compile::disabled() {
|
|
return;
|
|
}
|
|
|
|
let target = cross_compile::alternate();
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
&format!(
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "0.0.0"
|
|
authors = []
|
|
resolver = "2"
|
|
|
|
[dependencies.bar]
|
|
path = "bar/"
|
|
artifact = "bin"
|
|
target = "{}"
|
|
"#,
|
|
target
|
|
),
|
|
)
|
|
.file(
|
|
"src/lib.rs",
|
|
r#"pub fn foo() { let _b = include_bytes!(env!("CARGO_BIN_FILE_BAR")); }"#,
|
|
)
|
|
.file("bar/Cargo.toml", &basic_bin_manifest("bar"))
|
|
.file("bar/src/main.rs", "fn main() {}")
|
|
.file("bar/src/lib.rs", "pub fn doit() {}")
|
|
.build();
|
|
|
|
p.cargo("check -v -Z bindeps")
|
|
.masquerade_as_nightly_cargo(&["bindeps"])
|
|
.with_stderr_contains(format!(
|
|
"[RUNNING] `rustc --crate-name bar bar/src/lib.rs [..]--target {} [..]",
|
|
target
|
|
))
|
|
.with_stderr_contains(format!(
|
|
"[RUNNING] `rustc --crate-name bar bar/src/main.rs [..]--target {} [..]",
|
|
target
|
|
))
|
|
.with_stderr_does_not_contain(format!(
|
|
"[RUNNING] `rustc --crate-name foo [..]--target {} [..]",
|
|
target
|
|
))
|
|
.with_stderr_contains("[RUNNING] `rustc --crate-name foo [..]")
|
|
.run();
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn no_cross_doctests_works_with_artifacts() {
|
|
if cross_compile::disabled() {
|
|
return;
|
|
}
|
|
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "0.0.1"
|
|
authors = []
|
|
resolver = "2"
|
|
|
|
[dependencies]
|
|
bar = { path = "bar/", artifact = "bin", lib = true }
|
|
"#,
|
|
)
|
|
.file(
|
|
"src/lib.rs",
|
|
r#"
|
|
//! ```
|
|
//! env!("CARGO_BIN_DIR_BAR");
|
|
//! let _b = include_bytes!(env!("CARGO_BIN_FILE_BAR"));
|
|
//! ```
|
|
pub fn foo() {
|
|
env!("CARGO_BIN_DIR_BAR");
|
|
let _b = include_bytes!(env!("CARGO_BIN_FILE_BAR"));
|
|
}
|
|
"#,
|
|
)
|
|
.file("bar/Cargo.toml", &basic_bin_manifest("bar"))
|
|
.file("bar/src/lib.rs", r#"pub extern "C" fn c() {}"#)
|
|
.file("bar/src/main.rs", "fn main() {}")
|
|
.build();
|
|
|
|
let target = rustc_host();
|
|
p.cargo("test -Z bindeps --target")
|
|
.arg(&target)
|
|
.masquerade_as_nightly_cargo(&["bindeps"])
|
|
.with_stderr(&format!(
|
|
"\
|
|
[COMPILING] bar v0.5.0 ([CWD]/bar)
|
|
[COMPILING] foo v0.0.1 ([CWD])
|
|
[FINISHED] test [unoptimized + debuginfo] target(s) in [..]
|
|
[RUNNING] [..] (target/{triple}/debug/deps/foo-[..][EXE])
|
|
[DOCTEST] foo
|
|
",
|
|
triple = target
|
|
))
|
|
.run();
|
|
|
|
println!("c");
|
|
let target = cross_compile::alternate();
|
|
|
|
// This will build the library, but does not build or run doc tests.
|
|
// This should probably be a warning or error.
|
|
p.cargo("test -Z bindeps -v --doc --target")
|
|
.arg(&target)
|
|
.masquerade_as_nightly_cargo(&["bindeps"])
|
|
.with_stderr_contains(format!(
|
|
"[COMPILING] bar v0.5.0 ([CWD]/bar)
|
|
[RUNNING] `rustc --crate-name bar bar/src/lib.rs [..]--target {triple} [..]
|
|
[RUNNING] `rustc --crate-name bar bar/src/main.rs [..]--target {triple} [..]
|
|
[COMPILING] foo v0.0.1 ([CWD])
|
|
[RUNNING] `rustc --crate-name foo [..]
|
|
[FINISHED] test [unoptimized + debuginfo] target(s) in [..]",
|
|
triple = target
|
|
))
|
|
.run();
|
|
|
|
if !cross_compile::can_run_on_host() {
|
|
return;
|
|
}
|
|
|
|
// This tests the library, but does not run the doc tests.
|
|
p.cargo("test -Z bindeps -v --target")
|
|
.arg(&target)
|
|
.masquerade_as_nightly_cargo(&["bindeps"])
|
|
.with_stderr_contains(&format!(
|
|
"[FRESH] bar v0.5.0 ([CWD]/bar)
|
|
[COMPILING] foo v0.0.1 ([CWD])
|
|
[RUNNING] `rustc --crate-name foo [..]--test[..]
|
|
[FINISHED] test [unoptimized + debuginfo] target(s) in [..]
|
|
[RUNNING] `[CWD]/target/{triple}/debug/deps/foo-[..][EXE]`",
|
|
triple = target
|
|
))
|
|
.run();
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn build_script_deps_adopts_target_platform_if_target_equals_target() {
|
|
if cross_compile::disabled() {
|
|
return;
|
|
}
|
|
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "0.0.0"
|
|
authors = []
|
|
resolver = "2"
|
|
|
|
[build-dependencies]
|
|
bar = { path = "bar/", artifact = "bin", target = "target" }
|
|
"#,
|
|
)
|
|
.file("src/lib.rs", "")
|
|
.file("build.rs", r#"
|
|
fn main() {
|
|
let bar: std::path::PathBuf = std::env::var("CARGO_BIN_FILE_BAR").expect("CARGO_BIN_FILE_BAR").into();
|
|
assert!(&bar.is_file());
|
|
}"#)
|
|
.file("bar/Cargo.toml", &basic_bin_manifest("bar"))
|
|
.file("bar/src/main.rs", "fn main() {}")
|
|
.file("bar/src/lib.rs", "pub fn doit() {}")
|
|
.build();
|
|
|
|
let alternate_target = cross_compile::alternate();
|
|
p.cargo("check -v -Z bindeps --target")
|
|
.arg(alternate_target)
|
|
.masquerade_as_nightly_cargo(&["bindeps"])
|
|
.with_stderr_does_not_contain(format!(
|
|
"[RUNNING] `rustc --crate-name build_script_build build.rs [..]--target {} [..]",
|
|
alternate_target
|
|
))
|
|
.with_stderr_contains("[RUNNING] `rustc --crate-name build_script_build build.rs [..]")
|
|
.with_stderr_contains(format!(
|
|
"[RUNNING] `rustc --crate-name bar bar/src/lib.rs [..]--target {} [..]",
|
|
alternate_target
|
|
))
|
|
.with_stderr_contains(format!(
|
|
"[RUNNING] `rustc --crate-name bar bar/src/main.rs [..]--target {} [..]",
|
|
alternate_target
|
|
))
|
|
.with_stderr_contains(format!(
|
|
"[RUNNING] `rustc --crate-name foo [..]--target {} [..]",
|
|
alternate_target
|
|
))
|
|
.run();
|
|
}
|
|
|
|
#[cargo_test]
|
|
// TODO(ST): rename bar (dependency) to something else and un-ignore this with RFC-3176
|
|
#[cfg_attr(target_env = "msvc", ignore = "msvc not working")]
|
|
fn profile_override_basic() {
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "0.0.1"
|
|
authors = []
|
|
|
|
[build-dependencies]
|
|
bar = { path = "bar", artifact = "bin" }
|
|
|
|
[dependencies]
|
|
bar = { path = "bar", artifact = "bin" }
|
|
|
|
[profile.dev.build-override]
|
|
opt-level = 1
|
|
|
|
[profile.dev]
|
|
opt-level = 3
|
|
"#,
|
|
)
|
|
.file("build.rs", "fn main() {}")
|
|
.file("src/lib.rs", "")
|
|
.file("bar/Cargo.toml", &basic_bin_manifest("bar"))
|
|
.file("bar/src/main.rs", "fn main() {}")
|
|
.file("bar/src/lib.rs", "pub fn bar() {}")
|
|
.build();
|
|
|
|
p.cargo("build -v -Z bindeps")
|
|
.masquerade_as_nightly_cargo(&["bindeps"])
|
|
.with_stderr_contains(
|
|
"[RUNNING] `rustc --crate-name build_script_build [..] -C opt-level=1 [..]`",
|
|
)
|
|
.with_stderr_contains(
|
|
"[RUNNING] `rustc --crate-name bar bar/src/main.rs [..] -C opt-level=3 [..]`",
|
|
)
|
|
.with_stderr_contains(
|
|
"[RUNNING] `rustc --crate-name bar bar/src/main.rs [..] -C opt-level=1 [..]`",
|
|
)
|
|
.with_stderr_contains(
|
|
"[RUNNING] `rustc --crate-name bar bar/src/lib.rs [..] -C opt-level=1 [..]`",
|
|
)
|
|
.with_stderr_contains(
|
|
"[RUNNING] `rustc --crate-name bar bar/src/lib.rs [..] -C opt-level=3 [..]`",
|
|
)
|
|
.with_stderr_contains("[RUNNING] `rustc --crate-name foo [..] -C opt-level=3 [..]`")
|
|
.run();
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn dependencies_of_dependencies_work_in_artifacts() {
|
|
Package::new("baz", "1.0.0")
|
|
.file("src/lib.rs", "pub fn baz() {}")
|
|
.publish();
|
|
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "0.0.0"
|
|
authors = []
|
|
resolver = "2"
|
|
|
|
[build-dependencies]
|
|
bar = { path = "bar/", artifact = "bin" }
|
|
"#,
|
|
)
|
|
.file("src/lib.rs", "")
|
|
.file(
|
|
"build.rs",
|
|
r#"
|
|
fn main() {
|
|
std::process::Command::new(std::env::var("CARGO_BIN_FILE_BAR").expect("BAR present")).status().unwrap();
|
|
}
|
|
"#,
|
|
)
|
|
.file(
|
|
"bar/Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "bar"
|
|
version = "0.5.0"
|
|
authors = []
|
|
|
|
[dependencies]
|
|
baz = "1.0.0"
|
|
"#,
|
|
)
|
|
.file("bar/src/lib.rs", r#"pub fn bar() {baz::baz()}"#)
|
|
.file("bar/src/main.rs", r#"fn main() {bar::bar()}"#)
|
|
.build();
|
|
p.cargo("build -Z bindeps")
|
|
.masquerade_as_nightly_cargo(&["bindeps"])
|
|
.run();
|
|
|
|
// cargo tree sees artifacts as the dependency kind they are in and doesn't do anything special with it.
|
|
p.cargo("tree -Z bindeps")
|
|
.masquerade_as_nightly_cargo(&["bindeps"])
|
|
.with_stdout(
|
|
"\
|
|
foo v0.0.0 ([CWD])
|
|
[build-dependencies]
|
|
└── bar v0.5.0 ([CWD]/bar)
|
|
└── baz v1.0.0
|
|
",
|
|
)
|
|
.run();
|
|
}
|
|
#[cargo_test]
|
|
fn targets_are_picked_up_from_non_workspace_artifact_deps() {
|
|
if cross_compile::disabled() {
|
|
return;
|
|
}
|
|
let target = cross_compile::alternate();
|
|
Package::new("artifact", "1.0.0")
|
|
.file("src/main.rs", r#"fn main() {}"#)
|
|
.file("src/lib.rs", r#"pub fn lib() {}"#)
|
|
.publish();
|
|
|
|
let mut dep = registry::Dependency::new("artifact", "1.0.0");
|
|
Package::new("uses-artifact", "1.0.0")
|
|
.schema_version(3)
|
|
.file(
|
|
"src/lib.rs",
|
|
r#"pub fn uses_artifact() { let _b = include_bytes!(env!("CARGO_BIN_FILE_ARTIFACT")); }"#,
|
|
)
|
|
.add_dep(dep.artifact("bin", Some(target.to_string())))
|
|
.publish();
|
|
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "0.0.0"
|
|
authors = []
|
|
|
|
[dependencies]
|
|
uses-artifact = { version = "1.0.0" }
|
|
"#,
|
|
)
|
|
.file(
|
|
"src/lib.rs",
|
|
r#"pub fn foo() { uses_artifact::uses_artifact(); }"#,
|
|
)
|
|
.build();
|
|
|
|
p.cargo("build -Z bindeps")
|
|
.masquerade_as_nightly_cargo(&["bindeps"])
|
|
.run();
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn index_version_filtering() {
|
|
if cross_compile::disabled() {
|
|
return;
|
|
}
|
|
let target = cross_compile::alternate();
|
|
|
|
Package::new("artifact", "1.0.0")
|
|
.file("src/main.rs", r#"fn main() {}"#)
|
|
.file("src/lib.rs", r#"pub fn lib() {}"#)
|
|
.publish();
|
|
|
|
let mut dep = registry::Dependency::new("artifact", "1.0.0");
|
|
|
|
Package::new("bar", "1.0.0").publish();
|
|
Package::new("bar", "1.0.1")
|
|
.schema_version(3)
|
|
.add_dep(dep.artifact("bin", Some(target.to_string())))
|
|
.publish();
|
|
|
|
// Verify that without `-Zbindeps` that it does not use 1.0.1.
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "0.1.0"
|
|
|
|
[dependencies]
|
|
bar = "1.0"
|
|
"#,
|
|
)
|
|
.file("src/lib.rs", "")
|
|
.build();
|
|
|
|
p.cargo("tree")
|
|
.with_stdout("foo v0.1.0 [..]\n└── bar v1.0.0")
|
|
.run();
|
|
|
|
// And with -Zbindeps it can use 1.0.1.
|
|
p.cargo("update -Zbindeps")
|
|
.masquerade_as_nightly_cargo(&["bindeps"])
|
|
.with_stderr(
|
|
"\
|
|
[UPDATING] [..]
|
|
[ADDING] artifact v1.0.0
|
|
[UPDATING] bar v1.0.0 -> v1.0.1",
|
|
)
|
|
.run();
|
|
|
|
// And without -Zbindeps, now that 1.0.1 is in Cargo.lock, it should fail.
|
|
p.cargo("check")
|
|
.with_status(101)
|
|
.with_stderr(
|
|
"\
|
|
[UPDATING] [..]
|
|
error: failed to select a version for the requirement `bar = \"^1.0\"` (locked to 1.0.1)
|
|
candidate versions found which didn't match: 1.0.0
|
|
location searched: [..]
|
|
required by package `foo v0.1.0 [..]`
|
|
perhaps a crate was updated and forgotten to be re-vendored?",
|
|
)
|
|
.run();
|
|
}
|
|
|
|
// FIXME: `download_accessible` should work properly for artifact dependencies
|
|
#[cargo_test]
|
|
#[ignore = "broken, needs download_accessible fix"]
|
|
fn proc_macro_in_artifact_dep() {
|
|
// Forcing FeatureResolver to check a proc-macro for a dependency behind a
|
|
// target dependency.
|
|
if cross_compile::disabled() {
|
|
return;
|
|
}
|
|
Package::new("pm", "1.0.0")
|
|
.file("src/lib.rs", "")
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "pm"
|
|
version = "1.0.0"
|
|
|
|
[lib]
|
|
proc-macro = true
|
|
|
|
"#,
|
|
)
|
|
.publish();
|
|
let alternate = cross_compile::alternate();
|
|
Package::new("bin-uses-pm", "1.0.0")
|
|
.target_dep("pm", "1.0", alternate)
|
|
.file("src/main.rs", "fn main() {}")
|
|
.publish();
|
|
// Simulate a network error downloading the proc-macro.
|
|
std::fs::remove_file(cargo_test_support::paths::root().join("dl/pm/1.0.0/download")).unwrap();
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
&format!(
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "0.1.0"
|
|
edition = "2021"
|
|
|
|
[dependencies]
|
|
bin-uses-pm = {{ version = "1.0", artifact = "bin", target = "{alternate}"}}
|
|
"#
|
|
),
|
|
)
|
|
.file("src/lib.rs", "")
|
|
.build();
|
|
|
|
p.cargo("check -Z bindeps")
|
|
.masquerade_as_nightly_cargo(&["bindeps"])
|
|
.with_stderr("")
|
|
.run();
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn allow_dep_renames_with_multiple_versions() {
|
|
Package::new("bar", "1.0.0")
|
|
.file("src/main.rs", r#"fn main() {println!("1.0.0")}"#)
|
|
.publish();
|
|
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "0.0.0"
|
|
authors = []
|
|
resolver = "2"
|
|
|
|
[build-dependencies]
|
|
bar = { path = "bar/", artifact = "bin" }
|
|
bar_stable = { package = "bar", version = "1.0.0", artifact = "bin" }
|
|
"#,
|
|
)
|
|
.file("src/lib.rs", "")
|
|
.file(
|
|
"build.rs",
|
|
r#"
|
|
fn main() {
|
|
std::process::Command::new(std::env::var("CARGO_BIN_FILE_BAR").expect("BAR present")).status().unwrap();
|
|
std::process::Command::new(std::env::var("CARGO_BIN_FILE_BAR_STABLE_bar").expect("BAR STABLE present")).status().unwrap();
|
|
}
|
|
"#,
|
|
)
|
|
.file("bar/Cargo.toml", &basic_bin_manifest("bar"))
|
|
.file("bar/src/main.rs", r#"fn main() {println!("0.5.0")}"#)
|
|
.build();
|
|
p.cargo("check -Z bindeps")
|
|
.masquerade_as_nightly_cargo(&["bindeps"])
|
|
.with_stderr_contains("[COMPILING] bar [..]")
|
|
.with_stderr_contains("[COMPILING] foo [..]")
|
|
.run();
|
|
let build_script_output = build_script_output_string(&p, "foo");
|
|
match_exact(
|
|
"0.5.0\n1.0.0",
|
|
&build_script_output,
|
|
"build script output",
|
|
"",
|
|
None,
|
|
)
|
|
.unwrap();
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn allow_artifact_and_non_artifact_dependency_to_same_crate_if_these_are_not_the_same_dep_kind() {
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "0.0.0"
|
|
authors = []
|
|
resolver = "2"
|
|
|
|
[build-dependencies]
|
|
bar = { path = "bar/", artifact = "bin", lib = false }
|
|
|
|
[dependencies]
|
|
bar = { path = "bar/" }
|
|
"#,
|
|
)
|
|
.file("src/lib.rs", r#"
|
|
pub fn foo() {
|
|
bar::doit();
|
|
assert!(option_env!("CARGO_BIN_FILE_BAR").is_none());
|
|
}"#)
|
|
.file(
|
|
"build.rs",
|
|
r#"fn main() {
|
|
println!("{}", std::env::var("CARGO_BIN_FILE_BAR").expect("CARGO_BIN_FILE_BAR"));
|
|
println!("{}", std::env::var("CARGO_BIN_FILE_BAR_bar").expect("CARGO_BIN_FILE_BAR_bar"));
|
|
}"#,
|
|
)
|
|
.file("bar/Cargo.toml", &basic_manifest("bar", "0.0.1"))
|
|
.file("bar/src/lib.rs", "pub fn doit() {}")
|
|
.file("bar/src/main.rs", "fn main() {}")
|
|
.build();
|
|
p.cargo("build -Z bindeps")
|
|
.masquerade_as_nightly_cargo(&["bindeps"])
|
|
.with_stderr(
|
|
"\
|
|
[COMPILING] bar [..]
|
|
[COMPILING] foo [..]
|
|
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
|
|
",
|
|
)
|
|
.run();
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn prevent_no_lib_warning_with_artifact_dependencies() {
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "0.0.0"
|
|
authors = []
|
|
resolver = "2"
|
|
|
|
[dependencies]
|
|
bar = { path = "bar/", artifact = "bin" }
|
|
"#,
|
|
)
|
|
.file(
|
|
"src/lib.rs",
|
|
r#"pub fn foo() { let _b = include_bytes!(env!("CARGO_BIN_FILE_BAR")); }"#,
|
|
)
|
|
.file("bar/Cargo.toml", &basic_bin_manifest("bar"))
|
|
.file("bar/src/main.rs", "fn main() {}")
|
|
.build();
|
|
p.cargo("check -Z bindeps")
|
|
.masquerade_as_nightly_cargo(&["bindeps"])
|
|
.with_stderr(
|
|
"\
|
|
[COMPILING] bar v0.5.0 ([CWD]/bar)\n\
|
|
[CHECKING] foo v0.0.0 ([CWD])\n\
|
|
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]",
|
|
)
|
|
.run();
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn show_no_lib_warning_with_artifact_dependencies_that_have_no_lib_but_lib_true() {
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "0.0.0"
|
|
authors = []
|
|
resolver = "2"
|
|
|
|
[build-dependencies]
|
|
bar = { path = "bar/", artifact = "bin" }
|
|
|
|
[dependencies]
|
|
bar = { path = "bar/", artifact = "bin", lib = true }
|
|
"#,
|
|
)
|
|
.file("src/lib.rs", "")
|
|
.file("src/build.rs", "fn main() {}")
|
|
.file("bar/Cargo.toml", &basic_bin_manifest("bar"))
|
|
.file("bar/src/main.rs", "fn main() {}")
|
|
.build();
|
|
p.cargo("check -Z bindeps")
|
|
.masquerade_as_nightly_cargo(&["bindeps"])
|
|
.with_stderr_contains("[WARNING] foo v0.0.0 ([CWD]) ignoring invalid dependency `bar` which is missing a lib target")
|
|
.with_stderr_contains("[COMPILING] bar v0.5.0 ([CWD]/bar)")
|
|
.with_stderr_contains("[CHECKING] foo [..]")
|
|
.with_stderr_contains("[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]")
|
|
.run();
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn resolver_2_build_dep_without_lib() {
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "0.0.0"
|
|
authors = []
|
|
edition = "2021"
|
|
|
|
[build-dependencies]
|
|
bar = { path = "bar/", artifact = "bin" }
|
|
"#,
|
|
)
|
|
.file("src/lib.rs", "")
|
|
.file("build.rs", r#"
|
|
fn main() {
|
|
let bar: std::path::PathBuf = std::env::var("CARGO_BIN_FILE_BAR").expect("CARGO_BIN_FILE_BAR").into();
|
|
assert!(&bar.is_file());
|
|
}"#)
|
|
.file("bar/Cargo.toml", &basic_bin_manifest("bar"))
|
|
.file("bar/src/main.rs", "fn main() {}")
|
|
.build();
|
|
p.cargo("check -Z bindeps")
|
|
.masquerade_as_nightly_cargo(&["bindeps"])
|
|
.run();
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn check_missing_crate_type_in_package_fails() {
|
|
for crate_type in &["cdylib", "staticlib", "bin"] {
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
&format!(
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "0.0.0"
|
|
authors = []
|
|
|
|
[dependencies]
|
|
bar = {{ path = "bar/", artifact = "{}" }}
|
|
"#,
|
|
crate_type
|
|
),
|
|
)
|
|
.file("src/lib.rs", "")
|
|
.file("bar/Cargo.toml", &basic_manifest("bar", "0.0.1")) //no bin, just rlib
|
|
.file("bar/src/lib.rs", "")
|
|
.build();
|
|
p.cargo("check -Z bindeps")
|
|
.masquerade_as_nightly_cargo(&["bindeps"])
|
|
.with_status(101)
|
|
.with_stderr(
|
|
"[ERROR] dependency `bar` in package `foo` requires a `[..]` artifact to be present.",
|
|
)
|
|
.run();
|
|
}
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn check_target_equals_target_in_non_build_dependency_errors() {
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "0.0.0"
|
|
authors = []
|
|
resolver = "2"
|
|
|
|
[dependencies]
|
|
bar = { path = "bar/", artifact = "bin", target = "target" }
|
|
"#,
|
|
)
|
|
.file("src/lib.rs", "")
|
|
.file("bar/Cargo.toml", &basic_manifest("bar", "0.0.1"))
|
|
.file("bar/src/main.rs", "fn main() {}")
|
|
.build();
|
|
p.cargo("check -Z bindeps")
|
|
.masquerade_as_nightly_cargo(&["bindeps"])
|
|
.with_status(101)
|
|
.with_stderr_contains(
|
|
" `target = \"target\"` in normal- or dev-dependencies has no effect (bar)",
|
|
)
|
|
.run();
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn env_vars_and_build_products_for_various_build_targets() {
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "0.0.0"
|
|
authors = []
|
|
resolver = "2"
|
|
|
|
[lib]
|
|
doctest = true
|
|
|
|
[build-dependencies]
|
|
bar = { path = "bar/", artifact = ["cdylib", "staticlib"] }
|
|
|
|
[dependencies]
|
|
bar = { path = "bar/", artifact = "bin", lib = true }
|
|
|
|
[dev-dependencies]
|
|
bar = { path = "bar/", artifact = "bin:baz" }
|
|
"#,
|
|
)
|
|
.file("build.rs", r#"
|
|
fn main() {
|
|
let file: std::path::PathBuf = std::env::var("CARGO_CDYLIB_FILE_BAR").expect("CARGO_CDYLIB_FILE_BAR").into();
|
|
assert!(&file.is_file());
|
|
|
|
let file: std::path::PathBuf = std::env::var("CARGO_STATICLIB_FILE_BAR").expect("CARGO_STATICLIB_FILE_BAR").into();
|
|
assert!(&file.is_file());
|
|
|
|
assert!(std::env::var("CARGO_BIN_FILE_BAR").is_err());
|
|
assert!(std::env::var("CARGO_BIN_FILE_BAR_baz").is_err());
|
|
}
|
|
"#)
|
|
.file(
|
|
"src/lib.rs",
|
|
r#"
|
|
//! ```
|
|
//! bar::c();
|
|
//! env!("CARGO_BIN_DIR_BAR");
|
|
//! let _b = include_bytes!(env!("CARGO_BIN_FILE_BAR"));
|
|
//! let _b = include_bytes!(env!("CARGO_BIN_FILE_BAR_bar"));
|
|
//! let _b = include_bytes!(env!("CARGO_BIN_FILE_BAR_baz"));
|
|
//! assert!(option_env!("CARGO_STATICLIB_FILE_BAR").is_none());
|
|
//! assert!(option_env!("CARGO_CDYLIB_FILE_BAR").is_none());
|
|
//! ```
|
|
pub fn foo() {
|
|
bar::c();
|
|
env!("CARGO_BIN_DIR_BAR");
|
|
let _b = include_bytes!(env!("CARGO_BIN_FILE_BAR"));
|
|
let _b = include_bytes!(env!("CARGO_BIN_FILE_BAR_bar"));
|
|
let _b = include_bytes!(env!("CARGO_BIN_FILE_BAR_baz"));
|
|
assert!(option_env!("CARGO_STATICLIB_FILE_BAR").is_none());
|
|
assert!(option_env!("CARGO_CDYLIB_FILE_BAR").is_none());
|
|
}
|
|
|
|
#[cfg(test)]
|
|
#[test]
|
|
fn env_unit() {
|
|
env!("CARGO_BIN_DIR_BAR");
|
|
let _b = include_bytes!(env!("CARGO_BIN_FILE_BAR"));
|
|
let _b = include_bytes!(env!("CARGO_BIN_FILE_BAR_bar"));
|
|
let _b = include_bytes!(env!("CARGO_BIN_FILE_BAR_baz"));
|
|
assert!(option_env!("CARGO_STATICLIB_FILE_BAR").is_none());
|
|
assert!(option_env!("CARGO_CDYLIB_FILE_BAR").is_none());
|
|
}
|
|
"#,
|
|
)
|
|
.file(
|
|
"tests/main.rs",
|
|
r#"
|
|
#[test]
|
|
fn env_integration() {
|
|
env!("CARGO_BIN_DIR_BAR");
|
|
let _b = include_bytes!(env!("CARGO_BIN_FILE_BAR"));
|
|
let _b = include_bytes!(env!("CARGO_BIN_FILE_BAR_bar"));
|
|
let _b = include_bytes!(env!("CARGO_BIN_FILE_BAR_baz"));
|
|
}"#,
|
|
)
|
|
.file("build.rs", "fn main() {}")
|
|
.file(
|
|
"bar/Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "bar"
|
|
version = "0.5.0"
|
|
authors = []
|
|
|
|
[lib]
|
|
crate-type = ["staticlib", "cdylib", "rlib"]
|
|
|
|
[[bin]]
|
|
name = "bar"
|
|
|
|
[[bin]]
|
|
name = "baz"
|
|
"#,
|
|
)
|
|
.file("bar/src/lib.rs", r#"pub extern "C" fn c() {}"#)
|
|
.file("bar/src/main.rs", "fn main() {}")
|
|
.build();
|
|
p.cargo("test -Z bindeps")
|
|
.masquerade_as_nightly_cargo(&["bindeps"])
|
|
.with_stderr(
|
|
"\
|
|
[COMPILING] bar [..]
|
|
[COMPILING] foo [..]
|
|
[FINISHED] test [unoptimized + debuginfo] target(s) in [..]
|
|
[RUNNING] unittests [..]
|
|
[RUNNING] tests/main.rs [..]
|
|
[DOCTEST] foo
|
|
",
|
|
)
|
|
.run();
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn publish_artifact_dep() {
|
|
let registry = RegistryBuilder::new().http_api().http_index().build();
|
|
|
|
Package::new("bar", "1.0.0").publish();
|
|
Package::new("baz", "1.0.0").publish();
|
|
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "0.1.0"
|
|
authors = []
|
|
license = "MIT"
|
|
description = "foo"
|
|
documentation = "foo"
|
|
homepage = "foo"
|
|
repository = "foo"
|
|
resolver = "2"
|
|
|
|
[dependencies]
|
|
bar = { version = "1.0", artifact = "bin", lib = true }
|
|
|
|
[build-dependencies]
|
|
baz = { version = "1.0", artifact = ["bin:a", "cdylib", "staticlib"], target = "target" }
|
|
"#,
|
|
)
|
|
.file("src/lib.rs", "")
|
|
.build();
|
|
|
|
p.cargo("publish -Z bindeps --no-verify")
|
|
.replace_crates_io(registry.index_url())
|
|
.masquerade_as_nightly_cargo(&["bindeps"])
|
|
.with_stderr(
|
|
"\
|
|
[UPDATING] [..]
|
|
[PACKAGING] foo v0.1.0 [..]
|
|
[PACKAGED] [..]
|
|
[UPLOADING] foo v0.1.0 [..]
|
|
[UPLOADED] foo v0.1.0 [..]
|
|
[NOTE] waiting [..]
|
|
You may press ctrl-c [..]
|
|
[PUBLISHED] foo v0.1.0 [..]
|
|
",
|
|
)
|
|
.run();
|
|
|
|
publish::validate_upload_with_contents(
|
|
r#"
|
|
{
|
|
"authors": [],
|
|
"badges": {},
|
|
"categories": [],
|
|
"deps": [{
|
|
"artifact": ["bin"],
|
|
"default_features": true,
|
|
"features": [],
|
|
"kind": "normal",
|
|
"lib": true,
|
|
"name": "bar",
|
|
"optional": false,
|
|
"target": null,
|
|
"version_req": "^1.0"
|
|
},
|
|
{
|
|
"artifact": [
|
|
"bin:a",
|
|
"cdylib",
|
|
"staticlib"
|
|
],
|
|
"bindep_target": "target",
|
|
"default_features": true,
|
|
"features": [],
|
|
"kind": "build",
|
|
"name": "baz",
|
|
"optional": false,
|
|
"target": null,
|
|
"version_req": "^1.0"
|
|
}
|
|
],
|
|
"description": "foo",
|
|
"documentation": "foo",
|
|
"features": {},
|
|
"homepage": "foo",
|
|
"keywords": [],
|
|
"license": "MIT",
|
|
"license_file": null,
|
|
"links": null,
|
|
"name": "foo",
|
|
"readme": null,
|
|
"readme_file": null,
|
|
"repository": "foo",
|
|
"rust_version": null,
|
|
"vers": "0.1.0"
|
|
}
|
|
"#,
|
|
"foo-0.1.0.crate",
|
|
&["Cargo.toml", "Cargo.toml.orig", "src/lib.rs"],
|
|
&[(
|
|
"Cargo.toml",
|
|
&format!(
|
|
r#"{}
|
|
[package]
|
|
name = "foo"
|
|
version = "0.1.0"
|
|
authors = []
|
|
description = "foo"
|
|
homepage = "foo"
|
|
documentation = "foo"
|
|
license = "MIT"
|
|
repository = "foo"
|
|
resolver = "2"
|
|
|
|
[dependencies.bar]
|
|
version = "1.0"
|
|
artifact = ["bin"]
|
|
lib = true
|
|
|
|
[build-dependencies.baz]
|
|
version = "1.0"
|
|
artifact = [
|
|
"bin:a",
|
|
"cdylib",
|
|
"staticlib",
|
|
]
|
|
target = "target""#,
|
|
cargo::core::package::MANIFEST_PREAMBLE
|
|
),
|
|
)],
|
|
);
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn doc_lib_true() {
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "0.0.1"
|
|
authors = []
|
|
resolver = "2"
|
|
|
|
[dependencies.bar]
|
|
path = "bar"
|
|
artifact = "bin"
|
|
lib = true
|
|
"#,
|
|
)
|
|
.file("src/lib.rs", "extern crate bar; pub fn foo() {}")
|
|
.file("bar/Cargo.toml", &basic_manifest("bar", "0.0.1"))
|
|
.file("bar/src/lib.rs", "pub fn bar() {}")
|
|
.file("bar/src/main.rs", "fn main() {}")
|
|
.build();
|
|
|
|
p.cargo("doc -Z bindeps")
|
|
.masquerade_as_nightly_cargo(&["bindeps"])
|
|
.with_stderr(
|
|
"\
|
|
[COMPILING] bar v0.0.1 ([CWD]/bar)
|
|
[DOCUMENTING] bar v0.0.1 ([CWD]/bar)
|
|
[DOCUMENTING] foo v0.0.1 ([CWD])
|
|
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
|
|
[GENERATED] [CWD]/target/doc/foo/index.html
|
|
",
|
|
)
|
|
.run();
|
|
|
|
assert!(p.root().join("target/doc").is_dir());
|
|
assert!(p.root().join("target/doc/foo/index.html").is_file());
|
|
assert!(p.root().join("target/doc/bar/index.html").is_file());
|
|
|
|
// Verify that it emits rmeta for the bin and lib dependency.
|
|
assert_eq!(p.glob("target/debug/artifact/*.rlib").count(), 0);
|
|
assert_eq!(p.glob("target/debug/deps/libbar-*.rmeta").count(), 2);
|
|
|
|
p.cargo("doc -Z bindeps")
|
|
.masquerade_as_nightly_cargo(&["bindeps"])
|
|
.with_stderr(
|
|
"\
|
|
[FINISHED] [..]
|
|
[GENERATED] [CWD]/target/doc/foo/index.html",
|
|
)
|
|
.run();
|
|
|
|
assert!(p.root().join("target/doc").is_dir());
|
|
assert!(p.root().join("target/doc/foo/index.html").is_file());
|
|
assert!(p.root().join("target/doc/bar/index.html").is_file());
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn rustdoc_works_on_libs_with_artifacts_and_lib_false() {
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "0.0.1"
|
|
authors = []
|
|
resolver = "2"
|
|
|
|
[dependencies.bar]
|
|
path = "bar"
|
|
artifact = ["bin", "staticlib", "cdylib"]
|
|
"#,
|
|
)
|
|
.file(
|
|
"src/lib.rs",
|
|
r#"
|
|
pub fn foo() {
|
|
env!("CARGO_BIN_DIR_BAR");
|
|
let _b = include_bytes!(env!("CARGO_BIN_FILE_BAR"));
|
|
let _b = include_bytes!(env!("CARGO_CDYLIB_FILE_BAR"));
|
|
let _b = include_bytes!(env!("CARGO_CDYLIB_FILE_BAR_bar"));
|
|
let _b = include_bytes!(env!("CARGO_STATICLIB_FILE_BAR"));
|
|
let _b = include_bytes!(env!("CARGO_STATICLIB_FILE_BAR_bar"));
|
|
}"#,
|
|
)
|
|
.file(
|
|
"bar/Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "bar"
|
|
version = "0.5.0"
|
|
authors = []
|
|
|
|
[lib]
|
|
crate-type = ["staticlib", "cdylib"]
|
|
"#,
|
|
)
|
|
.file("bar/src/lib.rs", "pub fn bar() {}")
|
|
.file("bar/src/main.rs", "fn main() {}")
|
|
.build();
|
|
|
|
p.cargo("doc -Z bindeps")
|
|
.masquerade_as_nightly_cargo(&["bindeps"])
|
|
.with_stderr(
|
|
"\
|
|
[COMPILING] bar v0.5.0 ([CWD]/bar)
|
|
[DOCUMENTING] foo v0.0.1 ([CWD])
|
|
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
|
|
[GENERATED] [CWD]/target/doc/foo/index.html
|
|
",
|
|
)
|
|
.run();
|
|
|
|
assert!(p.root().join("target/doc").is_dir());
|
|
assert!(p.root().join("target/doc/foo/index.html").is_file());
|
|
assert!(
|
|
!p.root().join("target/doc/bar/index.html").is_file(),
|
|
"bar is not a lib dependency and thus remains undocumented"
|
|
);
|
|
}
|
|
|
|
fn assert_artifact_executable_output(
|
|
p: &Project,
|
|
target_name: &str,
|
|
dep_name: &str,
|
|
bin_name: &str,
|
|
) {
|
|
if cfg!(target_env = "msvc") {
|
|
assert_eq!(
|
|
p.glob(format!(
|
|
"target/{}/deps/artifact/{}-*/bin/{}{}",
|
|
target_name,
|
|
dep_name,
|
|
bin_name,
|
|
std::env::consts::EXE_SUFFIX
|
|
))
|
|
.count(),
|
|
1,
|
|
"artifacts are placed into their own output directory to not possibly clash"
|
|
);
|
|
} else {
|
|
assert_eq!(
|
|
p.glob(format!(
|
|
"target/{}/deps/artifact/{}-*/bin/{}-*{}",
|
|
target_name,
|
|
dep_name,
|
|
bin_name,
|
|
std::env::consts::EXE_SUFFIX
|
|
))
|
|
.filter_map(Result::ok)
|
|
.filter(|f| f.extension().map_or(true, |ext| ext != "o" && ext != "d"))
|
|
.count(),
|
|
1,
|
|
"artifacts are placed into their own output directory to not possibly clash"
|
|
);
|
|
}
|
|
}
|
|
|
|
fn build_script_output_string(p: &Project, package_name: &str) -> String {
|
|
let paths = p
|
|
.glob(format!("target/debug/build/{}-*/output", package_name))
|
|
.collect::<Result<Vec<_>, _>>()
|
|
.unwrap();
|
|
assert_eq!(paths.len(), 1);
|
|
std::fs::read_to_string(&paths[0]).unwrap()
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn build_script_features_for_shared_dependency() {
|
|
// When a build script is built and run, its features should match. Here:
|
|
//
|
|
// foo
|
|
// -> artifact on d1 with target
|
|
// -> common with features f1
|
|
//
|
|
// d1
|
|
// -> common with features f2
|
|
//
|
|
// common has features f1 and f2, with a build script.
|
|
//
|
|
// When common is built as a dependency of d1, it should have features
|
|
// `f2` (for the library and the build script).
|
|
//
|
|
// When common is built as a dependency of foo, it should have features
|
|
// `f1` (for the library and the build script).
|
|
if cross_compile::disabled() {
|
|
return;
|
|
}
|
|
let target = cross_compile::alternate();
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
&r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "0.0.1"
|
|
resolver = "2"
|
|
|
|
[dependencies]
|
|
d1 = { path = "d1", artifact = "bin", target = "$TARGET" }
|
|
common = { path = "common", features = ["f1"] }
|
|
"#
|
|
.replace("$TARGET", target),
|
|
)
|
|
.file(
|
|
"src/main.rs",
|
|
r#"
|
|
fn main() {
|
|
let _b = include_bytes!(env!("CARGO_BIN_FILE_D1"));
|
|
common::f1();
|
|
}
|
|
"#,
|
|
)
|
|
.file(
|
|
"d1/Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "d1"
|
|
version = "0.0.1"
|
|
|
|
[dependencies]
|
|
common = { path = "../common", features = ["f2"] }
|
|
"#,
|
|
)
|
|
.file(
|
|
"d1/src/main.rs",
|
|
r#"fn main() {
|
|
common::f2();
|
|
}"#,
|
|
)
|
|
.file(
|
|
"common/Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "common"
|
|
version = "0.0.1"
|
|
|
|
[features]
|
|
f1 = []
|
|
f2 = []
|
|
"#,
|
|
)
|
|
.file(
|
|
"common/src/lib.rs",
|
|
r#"
|
|
#[cfg(feature = "f1")]
|
|
pub fn f1() {}
|
|
|
|
#[cfg(feature = "f2")]
|
|
pub fn f2() {}
|
|
"#,
|
|
)
|
|
.file(
|
|
"common/build.rs",
|
|
&r#"
|
|
use std::env::var_os;
|
|
fn main() {
|
|
assert_eq!(var_os("CARGO_FEATURE_F1").is_some(), cfg!(feature="f1"));
|
|
assert_eq!(var_os("CARGO_FEATURE_F2").is_some(), cfg!(feature="f2"));
|
|
if std::env::var("TARGET").unwrap() == "$TARGET" {
|
|
assert!(var_os("CARGO_FEATURE_F1").is_none());
|
|
assert!(var_os("CARGO_FEATURE_F2").is_some());
|
|
} else {
|
|
assert!(var_os("CARGO_FEATURE_F1").is_some());
|
|
assert!(var_os("CARGO_FEATURE_F2").is_none());
|
|
}
|
|
}
|
|
"#
|
|
.replace("$TARGET", target),
|
|
)
|
|
.build();
|
|
|
|
p.cargo("build -Z bindeps -v")
|
|
.masquerade_as_nightly_cargo(&["bindeps"])
|
|
.run();
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn calc_bin_artifact_fingerprint() {
|
|
// See rust-lang/cargo#10527
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "0.1.0"
|
|
resolver = "2"
|
|
|
|
[dependencies]
|
|
bar = { path = "bar/", artifact = "bin" }
|
|
"#,
|
|
)
|
|
.file(
|
|
"src/main.rs",
|
|
r#"
|
|
fn main() {
|
|
let _b = include_bytes!(env!("CARGO_BIN_FILE_BAR"));
|
|
}
|
|
"#,
|
|
)
|
|
.file("bar/Cargo.toml", &basic_bin_manifest("bar"))
|
|
.file("bar/src/main.rs", r#"fn main() { println!("foo") }"#)
|
|
.build();
|
|
p.cargo("check -Z bindeps")
|
|
.masquerade_as_nightly_cargo(&["bindeps"])
|
|
.with_stderr(
|
|
"\
|
|
[COMPILING] bar v0.5.0 ([CWD]/bar)
|
|
[CHECKING] foo v0.1.0 ([CWD])
|
|
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
|
|
",
|
|
)
|
|
.run();
|
|
|
|
p.change_file("bar/src/main.rs", r#"fn main() { println!("bar") }"#);
|
|
// Change in artifact bin dep `bar` propagates to `foo`, triggering recompile.
|
|
p.cargo("check -v -Z bindeps")
|
|
.masquerade_as_nightly_cargo(&["bindeps"])
|
|
.with_stderr(
|
|
"\
|
|
[DIRTY] bar v0.5.0 ([CWD]/bar): the file `bar/src/main.rs` has changed ([..])
|
|
[COMPILING] bar v0.5.0 ([CWD]/bar)
|
|
[RUNNING] `rustc --crate-name bar [..]`
|
|
[DIRTY] foo v0.1.0 ([CWD]): the dependency bar was rebuilt
|
|
[CHECKING] foo v0.1.0 ([CWD])
|
|
[RUNNING] `rustc --crate-name foo [..]`
|
|
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
|
|
",
|
|
)
|
|
.run();
|
|
|
|
// All units are fresh. No recompile.
|
|
p.cargo("check -v -Z bindeps")
|
|
.masquerade_as_nightly_cargo(&["bindeps"])
|
|
.with_stderr(
|
|
"\
|
|
[FRESH] bar v0.5.0 ([CWD]/bar)
|
|
[FRESH] foo v0.1.0 ([CWD])
|
|
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
|
|
",
|
|
)
|
|
.run();
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn with_target_and_optional() {
|
|
// See rust-lang/cargo#10526
|
|
if cross_compile::disabled() {
|
|
return;
|
|
}
|
|
let target = cross_compile::alternate();
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
&r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "0.0.1"
|
|
edition = "2021"
|
|
[dependencies]
|
|
d1 = { path = "d1", artifact = "bin", optional = true, target = "$TARGET" }
|
|
"#
|
|
.replace("$TARGET", target),
|
|
)
|
|
.file(
|
|
"src/main.rs",
|
|
r#"
|
|
fn main() {
|
|
let _b = include_bytes!(env!("CARGO_BIN_FILE_D1"));
|
|
}
|
|
"#,
|
|
)
|
|
.file(
|
|
"d1/Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "d1"
|
|
version = "0.0.1"
|
|
edition = "2021"
|
|
"#,
|
|
)
|
|
.file("d1/src/main.rs", "fn main() {}")
|
|
.build();
|
|
|
|
p.cargo("check -Z bindeps -F d1 -v")
|
|
.masquerade_as_nightly_cargo(&["bindeps"])
|
|
.with_stderr(
|
|
"\
|
|
[COMPILING] d1 v0.0.1 [..]
|
|
[RUNNING] `rustc --crate-name d1 [..]--crate-type bin[..]
|
|
[CHECKING] foo v0.0.1 [..]
|
|
[RUNNING] `rustc --crate-name foo [..]--cfg[..]d1[..]
|
|
[FINISHED] dev [..]
|
|
",
|
|
)
|
|
.run();
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn with_assumed_host_target_and_optional_build_dep() {
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "0.0.1"
|
|
edition = "2021"
|
|
[build-dependencies]
|
|
d1 = { path = "d1", artifact = "bin", optional = true, target = "target" }
|
|
"#,
|
|
)
|
|
.file("src/main.rs", "fn main() {}")
|
|
.file(
|
|
"build.rs",
|
|
r#"
|
|
fn main() {
|
|
std::env::var("CARGO_BIN_FILE_D1").unwrap();
|
|
}
|
|
"#,
|
|
)
|
|
.file(
|
|
"d1/Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "d1"
|
|
version = "0.0.1"
|
|
edition = "2021"
|
|
"#,
|
|
)
|
|
.file("d1/src/main.rs", "fn main() {}")
|
|
.build();
|
|
|
|
p.cargo("check -Z bindeps -F d1 -v")
|
|
.masquerade_as_nightly_cargo(&["bindeps"])
|
|
.with_stderr_unordered(
|
|
"\
|
|
[COMPILING] foo v0.0.1 ([CWD])
|
|
[COMPILING] d1 v0.0.1 ([CWD]/d1)
|
|
[RUNNING] `rustc --crate-name build_script_build [..]--crate-type bin[..]
|
|
[RUNNING] `rustc --crate-name d1 [..]--crate-type bin[..]
|
|
[RUNNING] `[CWD]/target/debug/build/foo-[..]/build-script-build`
|
|
[RUNNING] `rustc --crate-name foo [..]--cfg[..]d1[..]
|
|
[FINISHED] dev [..]
|
|
",
|
|
)
|
|
.run();
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn decouple_same_target_transitive_dep_from_artifact_dep() {
|
|
// See https://github.com/rust-lang/cargo/issues/11463
|
|
let target = rustc_host();
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
&format!(
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "0.1.0"
|
|
edition = "2021"
|
|
|
|
[dependencies]
|
|
a = {{ path = "a" }}
|
|
bar = {{ path = "bar", artifact = "bin", target = "{target}" }}
|
|
"#
|
|
),
|
|
)
|
|
.file(
|
|
"src/main.rs",
|
|
r#"
|
|
fn main() {}
|
|
"#,
|
|
)
|
|
.file(
|
|
"bar/Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "bar"
|
|
version = "0.1.0"
|
|
|
|
[dependencies]
|
|
a = { path = "../a", features = ["feature"] }
|
|
"#,
|
|
)
|
|
.file(
|
|
"bar/src/main.rs",
|
|
r#"
|
|
fn main() {}
|
|
"#,
|
|
)
|
|
.file(
|
|
"a/Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "a"
|
|
version = "0.1.0"
|
|
edition = "2021"
|
|
|
|
[dependencies]
|
|
b = { path = "../b" }
|
|
c = { path = "../c" }
|
|
|
|
[features]
|
|
feature = ["c/feature"]
|
|
"#,
|
|
)
|
|
.file(
|
|
"a/src/lib.rs",
|
|
r#"
|
|
use b::Trait as _;
|
|
|
|
pub fn use_b_trait(x: &impl c::Trait) {
|
|
x.b();
|
|
}
|
|
"#,
|
|
)
|
|
.file(
|
|
"b/Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "b"
|
|
version = "0.1.0"
|
|
|
|
[dependencies]
|
|
c = { path = "../c" }
|
|
"#,
|
|
)
|
|
.file(
|
|
"b/src/lib.rs",
|
|
r#"
|
|
pub trait Trait {
|
|
fn b(&self) {}
|
|
}
|
|
|
|
impl<T: c::Trait> Trait for T {}
|
|
"#,
|
|
)
|
|
.file(
|
|
"c/Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "c"
|
|
version = "0.1.0"
|
|
|
|
[features]
|
|
feature = []
|
|
"#,
|
|
)
|
|
.file(
|
|
"c/src/lib.rs",
|
|
r#"
|
|
pub trait Trait {}
|
|
"#,
|
|
)
|
|
.build();
|
|
p.cargo("build -Z bindeps")
|
|
.masquerade_as_nightly_cargo(&["bindeps"])
|
|
.with_stderr(
|
|
"\
|
|
[COMPILING] c v0.1.0 ([CWD]/c)
|
|
[COMPILING] b v0.1.0 ([CWD]/b)
|
|
[COMPILING] a v0.1.0 ([CWD]/a)
|
|
[COMPILING] bar v0.1.0 ([CWD]/bar)
|
|
[COMPILING] foo v0.1.0 ([CWD])
|
|
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
|
|
",
|
|
)
|
|
.run();
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn decouple_same_target_transitive_dep_from_artifact_dep_lib() {
|
|
// See https://github.com/rust-lang/cargo/issues/10837
|
|
let target = rustc_host();
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
&format!(
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "0.1.0"
|
|
edition = "2021"
|
|
|
|
[dependencies]
|
|
a = {{ path = "a" }}
|
|
b = {{ path = "b", features = ["feature"] }}
|
|
bar = {{ path = "bar", artifact = "bin", lib = true, target = "{target}" }}
|
|
"#
|
|
),
|
|
)
|
|
.file("src/lib.rs", "")
|
|
.file(
|
|
"bar/Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "bar"
|
|
version = "0.1.0"
|
|
edition = "2021"
|
|
|
|
[dependencies]
|
|
a = { path = "../a", features = ["b"] }
|
|
b = { path = "../b" }
|
|
"#,
|
|
)
|
|
.file("bar/src/lib.rs", "")
|
|
.file(
|
|
"bar/src/main.rs",
|
|
r#"
|
|
use b::Trait;
|
|
|
|
fn main() {
|
|
a::A.b()
|
|
}
|
|
"#,
|
|
)
|
|
.file(
|
|
"a/Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "a"
|
|
version = "0.1.0"
|
|
|
|
[dependencies]
|
|
b = { path = "../b", optional = true }
|
|
"#,
|
|
)
|
|
.file(
|
|
"a/src/lib.rs",
|
|
r#"
|
|
pub struct A;
|
|
|
|
#[cfg(feature = "b")]
|
|
impl b::Trait for A {}
|
|
"#,
|
|
)
|
|
.file(
|
|
"b/Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "b"
|
|
version = "0.1.0"
|
|
|
|
[features]
|
|
feature = []
|
|
"#,
|
|
)
|
|
.file(
|
|
"b/src/lib.rs",
|
|
r#"
|
|
pub trait Trait {
|
|
fn b(&self) {}
|
|
}
|
|
"#,
|
|
)
|
|
.build();
|
|
p.cargo("build -Z bindeps")
|
|
.masquerade_as_nightly_cargo(&["bindeps"])
|
|
.with_stderr(
|
|
"\
|
|
[COMPILING] b v0.1.0 ([CWD]/b)
|
|
[COMPILING] a v0.1.0 ([CWD]/a)
|
|
[COMPILING] bar v0.1.0 ([CWD]/bar)
|
|
[COMPILING] foo v0.1.0 ([CWD])
|
|
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
|
|
",
|
|
)
|
|
.run();
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn decouple_same_target_transitive_dep_from_artifact_dep_and_proc_macro() {
|
|
let target = rustc_host();
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
&format!(
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "0.1.0"
|
|
edition = "2021"
|
|
|
|
[dependencies]
|
|
c = {{ path = "c" }}
|
|
bar = {{ path = "bar", artifact = "bin", target = "{target}" }}
|
|
"#
|
|
),
|
|
)
|
|
.file("src/lib.rs", "")
|
|
.file(
|
|
"bar/Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "bar"
|
|
version = "0.1.0"
|
|
|
|
[dependencies]
|
|
b = { path = "../b" }
|
|
"#,
|
|
)
|
|
.file("bar/src/main.rs", "fn main() {}")
|
|
.file(
|
|
"b/Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "b"
|
|
version = "0.1.0"
|
|
edition = "2021"
|
|
|
|
[dependencies]
|
|
a = { path = "../a" }
|
|
|
|
[lib]
|
|
proc-macro = true
|
|
"#,
|
|
)
|
|
.file("b/src/lib.rs", "")
|
|
.file(
|
|
"c/Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "c"
|
|
version = "0.1.0"
|
|
edition = "2021"
|
|
|
|
[dependencies]
|
|
d = { path = "../d", features = ["feature"] }
|
|
a = { path = "../a" }
|
|
|
|
[lib]
|
|
proc-macro = true
|
|
"#,
|
|
)
|
|
.file(
|
|
"c/src/lib.rs",
|
|
r#"
|
|
use a::Trait;
|
|
|
|
fn _c() {
|
|
d::D.a()
|
|
}
|
|
"#,
|
|
)
|
|
.file(
|
|
"a/Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "a"
|
|
version = "0.1.0"
|
|
|
|
[dependencies]
|
|
d = { path = "../d" }
|
|
"#,
|
|
)
|
|
.file(
|
|
"a/src/lib.rs",
|
|
r#"
|
|
pub trait Trait {
|
|
fn a(&self) {}
|
|
}
|
|
|
|
impl Trait for d::D {}
|
|
"#,
|
|
)
|
|
.file(
|
|
"d/Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "d"
|
|
version = "0.1.0"
|
|
|
|
[features]
|
|
feature = []
|
|
"#,
|
|
)
|
|
.file("d/src/lib.rs", "pub struct D;")
|
|
.build();
|
|
|
|
p.cargo("build -Z bindeps")
|
|
.masquerade_as_nightly_cargo(&["bindeps"])
|
|
.with_stderr_unordered(
|
|
"\
|
|
[COMPILING] d v0.1.0 ([CWD]/d)
|
|
[COMPILING] a v0.1.0 ([CWD]/a)
|
|
[COMPILING] b v0.1.0 ([CWD]/b)
|
|
[COMPILING] c v0.1.0 ([CWD]/c)
|
|
[COMPILING] bar v0.1.0 ([CWD]/bar)
|
|
[COMPILING] foo v0.1.0 ([CWD])
|
|
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
|
|
",
|
|
)
|
|
.run();
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn same_target_artifact_dep_sharing() {
|
|
let target = rustc_host();
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
&format!(
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "0.1.0"
|
|
|
|
[dependencies]
|
|
a = {{ path = "a" }}
|
|
bar = {{ path = "bar", artifact = "bin", target = "{target}" }}
|
|
"#
|
|
),
|
|
)
|
|
.file("src/lib.rs", "")
|
|
.file(
|
|
"bar/Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "bar"
|
|
version = "0.1.0"
|
|
|
|
[dependencies]
|
|
a = { path = "../a" }
|
|
"#,
|
|
)
|
|
.file(
|
|
"bar/src/main.rs",
|
|
r#"
|
|
fn main() {}
|
|
"#,
|
|
)
|
|
.file(
|
|
"a/Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "a"
|
|
version = "0.1.0"
|
|
"#,
|
|
)
|
|
.file("a/src/lib.rs", "")
|
|
.build();
|
|
p.cargo(&format!("build -Z bindeps --target {target}"))
|
|
.masquerade_as_nightly_cargo(&["bindeps"])
|
|
.with_stderr(
|
|
"\
|
|
[COMPILING] a v0.1.0 ([CWD]/a)
|
|
[COMPILING] bar v0.1.0 ([CWD]/bar)
|
|
[COMPILING] foo v0.1.0 ([CWD])
|
|
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
|
|
",
|
|
)
|
|
.run();
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn check_transitive_artifact_dependency_with_different_target() {
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "0.0.0"
|
|
|
|
[dependencies]
|
|
bar = { path = "bar/" }
|
|
"#,
|
|
)
|
|
.file("src/lib.rs", "")
|
|
.file(
|
|
"bar/Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "bar"
|
|
version = "0.0.0"
|
|
|
|
[dependencies]
|
|
baz = { path = "baz/", artifact = "bin", target = "custom-target" }
|
|
"#,
|
|
)
|
|
.file("bar/src/lib.rs", "")
|
|
.file(
|
|
"bar/baz/Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "baz"
|
|
version = "0.0.0"
|
|
|
|
[dependencies]
|
|
"#,
|
|
)
|
|
.file("bar/baz/src/main.rs", "fn main() {}")
|
|
.build();
|
|
|
|
p.cargo("check -Z bindeps")
|
|
.masquerade_as_nightly_cargo(&["bindeps"])
|
|
.with_stderr_contains(
|
|
"error: failed to determine target information for target `custom-target`.\n \
|
|
Artifact dependency `baz` in package `bar v0.0.0 [..]` requires building for `custom-target`",
|
|
)
|
|
.with_status(101)
|
|
.run();
|
|
}
|