2019-09-10 22:38:01 +00:00
|
|
|
//! Tests for the new feature resolver.
|
|
|
|
|
2020-03-27 21:58:03 +00:00
|
|
|
use cargo_test_support::cross_compile::{self, alternate};
|
2020-03-15 22:59:42 +00:00
|
|
|
use cargo_test_support::paths::CargoPathExt;
|
2020-04-17 18:20:38 +00:00
|
|
|
use cargo_test_support::publish::validate_crate_contents;
|
2019-09-10 22:38:01 +00:00
|
|
|
use cargo_test_support::registry::{Dependency, Package};
|
2020-04-17 18:20:38 +00:00
|
|
|
use cargo_test_support::{basic_manifest, cargo_process, project, rustc_host};
|
|
|
|
use std::fs::File;
|
2019-09-10 22:38:01 +00:00
|
|
|
|
|
|
|
#[cargo_test]
|
|
|
|
fn inactivate_targets() {
|
|
|
|
// Basic test of `itarget`. A shared dependency where an inactive [target]
|
|
|
|
// changes the features.
|
|
|
|
Package::new("common", "1.0.0")
|
|
|
|
.feature("f1", &[])
|
|
|
|
.file(
|
|
|
|
"src/lib.rs",
|
|
|
|
r#"
|
|
|
|
#[cfg(feature = "f1")]
|
|
|
|
compile_error!("f1 should not activate");
|
|
|
|
"#,
|
|
|
|
)
|
|
|
|
.publish();
|
|
|
|
|
|
|
|
Package::new("bar", "1.0.0")
|
|
|
|
.add_dep(
|
|
|
|
Dependency::new("common", "1.0")
|
|
|
|
.target("cfg(whatever)")
|
|
|
|
.enable_features(&["f1"]),
|
|
|
|
)
|
|
|
|
.publish();
|
|
|
|
|
|
|
|
let p = project()
|
|
|
|
.file(
|
|
|
|
"Cargo.toml",
|
|
|
|
r#"
|
|
|
|
[package]
|
|
|
|
name = "foo"
|
|
|
|
version = "0.1.0"
|
|
|
|
|
|
|
|
[dependencies]
|
|
|
|
common = "1.0"
|
|
|
|
bar = "1.0"
|
|
|
|
"#,
|
|
|
|
)
|
|
|
|
.file("src/lib.rs", "")
|
|
|
|
.build();
|
|
|
|
|
|
|
|
p.cargo("check")
|
|
|
|
.with_status(101)
|
|
|
|
.with_stderr_contains("[..]f1 should not activate[..]")
|
|
|
|
.run();
|
|
|
|
|
|
|
|
p.cargo("check -Zfeatures=itarget")
|
|
|
|
.masquerade_as_nightly_cargo()
|
|
|
|
.run();
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cargo_test]
|
|
|
|
fn inactive_target_optional() {
|
|
|
|
// Activating optional [target] dependencies for inactivate target.
|
|
|
|
Package::new("common", "1.0.0")
|
|
|
|
.feature("f1", &[])
|
|
|
|
.feature("f2", &[])
|
|
|
|
.feature("f3", &[])
|
|
|
|
.feature("f4", &[])
|
|
|
|
.file(
|
|
|
|
"src/lib.rs",
|
|
|
|
r#"
|
|
|
|
pub fn f() {
|
|
|
|
if cfg!(feature="f1") { println!("f1"); }
|
|
|
|
if cfg!(feature="f2") { println!("f2"); }
|
|
|
|
if cfg!(feature="f3") { println!("f3"); }
|
|
|
|
if cfg!(feature="f4") { println!("f4"); }
|
|
|
|
}
|
|
|
|
"#,
|
|
|
|
)
|
|
|
|
.publish();
|
|
|
|
|
|
|
|
let p = project()
|
|
|
|
.file(
|
|
|
|
"Cargo.toml",
|
|
|
|
r#"
|
|
|
|
[package]
|
|
|
|
name = "foo"
|
|
|
|
version = "0.1.0"
|
|
|
|
edition = "2018"
|
|
|
|
|
|
|
|
[dependencies]
|
|
|
|
common = "1.0"
|
|
|
|
|
|
|
|
[target.'cfg(whatever)'.dependencies]
|
|
|
|
dep1 = {path='dep1', optional=true}
|
|
|
|
dep2 = {path='dep2', optional=true, features=["f3"]}
|
|
|
|
common = {version="1.0", optional=true, features=["f4"]}
|
|
|
|
|
|
|
|
[features]
|
|
|
|
foo1 = ["dep1/f2"]
|
|
|
|
"#,
|
|
|
|
)
|
|
|
|
.file(
|
|
|
|
"src/main.rs",
|
|
|
|
r#"
|
|
|
|
fn main() {
|
|
|
|
if cfg!(feature="foo1") { println!("foo1"); }
|
|
|
|
if cfg!(feature="dep1") { println!("dep1"); }
|
|
|
|
if cfg!(feature="dep2") { println!("dep2"); }
|
|
|
|
if cfg!(feature="common") { println!("common"); }
|
|
|
|
common::f();
|
|
|
|
}
|
|
|
|
"#,
|
|
|
|
)
|
|
|
|
.file(
|
|
|
|
"dep1/Cargo.toml",
|
|
|
|
r#"
|
|
|
|
[package]
|
|
|
|
name = "dep1"
|
|
|
|
version = "0.1.0"
|
|
|
|
|
|
|
|
[dependencies]
|
|
|
|
common = {version="1.0", features=["f1"]}
|
|
|
|
|
|
|
|
[features]
|
|
|
|
f2 = ["common/f2"]
|
|
|
|
"#,
|
|
|
|
)
|
|
|
|
.file(
|
|
|
|
"dep1/src/lib.rs",
|
|
|
|
r#"compile_error!("dep1 should not build");"#,
|
|
|
|
)
|
|
|
|
.file(
|
|
|
|
"dep2/Cargo.toml",
|
|
|
|
r#"
|
|
|
|
[package]
|
|
|
|
name = "dep2"
|
|
|
|
version = "0.1.0"
|
|
|
|
|
|
|
|
[dependencies]
|
|
|
|
common = "1.0"
|
|
|
|
|
|
|
|
[features]
|
|
|
|
f3 = ["common/f3"]
|
|
|
|
"#,
|
|
|
|
)
|
|
|
|
.file(
|
|
|
|
"dep2/src/lib.rs",
|
|
|
|
r#"compile_error!("dep2 should not build");"#,
|
|
|
|
)
|
|
|
|
.build();
|
|
|
|
|
|
|
|
p.cargo("run --all-features")
|
|
|
|
.with_stdout("foo1\ndep1\ndep2\ncommon\nf1\nf2\nf3\nf4\n")
|
|
|
|
.run();
|
|
|
|
p.cargo("run --features dep1")
|
|
|
|
.with_stdout("dep1\nf1\n")
|
|
|
|
.run();
|
|
|
|
p.cargo("run --features foo1")
|
|
|
|
.with_stdout("foo1\ndep1\nf1\nf2\n")
|
|
|
|
.run();
|
|
|
|
p.cargo("run --features dep2")
|
|
|
|
.with_stdout("dep2\nf3\n")
|
|
|
|
.run();
|
|
|
|
p.cargo("run --features common")
|
|
|
|
.with_stdout("common\nf4\n")
|
|
|
|
.run();
|
|
|
|
|
|
|
|
p.cargo("run -Zfeatures=itarget --all-features")
|
|
|
|
.masquerade_as_nightly_cargo()
|
|
|
|
.with_stdout("foo1\n")
|
|
|
|
.run();
|
|
|
|
p.cargo("run -Zfeatures=itarget --features dep1")
|
|
|
|
.masquerade_as_nightly_cargo()
|
|
|
|
.with_stdout("dep1\n")
|
|
|
|
.run();
|
|
|
|
p.cargo("run -Zfeatures=itarget --features foo1")
|
|
|
|
.masquerade_as_nightly_cargo()
|
|
|
|
.with_stdout("foo1\n")
|
|
|
|
.run();
|
|
|
|
p.cargo("run -Zfeatures=itarget --features dep2")
|
|
|
|
.masquerade_as_nightly_cargo()
|
|
|
|
.with_stdout("dep2\n")
|
|
|
|
.run();
|
|
|
|
p.cargo("run -Zfeatures=itarget --features common")
|
|
|
|
.masquerade_as_nightly_cargo()
|
|
|
|
.with_stdout("common")
|
|
|
|
.run();
|
|
|
|
}
|
|
|
|
|
2020-03-27 21:58:03 +00:00
|
|
|
#[cargo_test]
|
|
|
|
fn itarget_proc_macro() {
|
|
|
|
// itarget inside a proc-macro while cross-compiling
|
|
|
|
if cross_compile::disabled() {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
Package::new("hostdep", "1.0.0").publish();
|
|
|
|
Package::new("pm", "1.0.0")
|
|
|
|
.proc_macro(true)
|
|
|
|
.target_dep("hostdep", "1.0", &rustc_host())
|
|
|
|
.file("src/lib.rs", "extern crate hostdep;")
|
|
|
|
.publish();
|
|
|
|
let p = project()
|
|
|
|
.file(
|
|
|
|
"Cargo.toml",
|
|
|
|
r#"
|
|
|
|
[package]
|
|
|
|
name = "foo"
|
|
|
|
version = "0.1.0"
|
|
|
|
|
|
|
|
[dependencies]
|
|
|
|
pm = "1.0"
|
|
|
|
"#,
|
|
|
|
)
|
|
|
|
.file("src/lib.rs", "")
|
|
|
|
.build();
|
|
|
|
|
|
|
|
p.cargo("check").run();
|
|
|
|
p.cargo("check -Zfeatures=itarget")
|
|
|
|
.masquerade_as_nightly_cargo()
|
|
|
|
.run();
|
|
|
|
p.cargo("check --target").arg(alternate()).run();
|
|
|
|
p.cargo("check -Zfeatures=itarget --target")
|
|
|
|
.arg(alternate())
|
|
|
|
.masquerade_as_nightly_cargo()
|
|
|
|
.run();
|
|
|
|
// For good measure, just make sure things don't break.
|
|
|
|
p.cargo("check -Zfeatures=all --target")
|
|
|
|
.arg(alternate())
|
|
|
|
.masquerade_as_nightly_cargo()
|
|
|
|
.run();
|
|
|
|
}
|
|
|
|
|
2019-09-10 22:38:01 +00:00
|
|
|
#[cargo_test]
|
2020-03-15 22:59:42 +00:00
|
|
|
fn decouple_host_deps() {
|
|
|
|
// Basic test for `host_dep` decouple.
|
2019-09-10 22:38:01 +00:00
|
|
|
Package::new("common", "1.0.0")
|
|
|
|
.feature("f1", &[])
|
|
|
|
.file(
|
|
|
|
"src/lib.rs",
|
|
|
|
r#"
|
|
|
|
#[cfg(feature = "f1")]
|
|
|
|
pub fn foo() {}
|
|
|
|
#[cfg(not(feature = "f1"))]
|
|
|
|
pub fn bar() {}
|
|
|
|
"#,
|
|
|
|
)
|
|
|
|
.publish();
|
|
|
|
|
|
|
|
let p = project()
|
|
|
|
.file(
|
|
|
|
"Cargo.toml",
|
|
|
|
r#"
|
|
|
|
[package]
|
|
|
|
name = "foo"
|
|
|
|
version = "0.1.0"
|
|
|
|
edition = "2018"
|
|
|
|
|
|
|
|
[build-dependencies]
|
|
|
|
common = {version="1.0", features=["f1"]}
|
|
|
|
|
|
|
|
[dependencies]
|
|
|
|
common = "1.0"
|
|
|
|
"#,
|
|
|
|
)
|
|
|
|
.file(
|
|
|
|
"build.rs",
|
|
|
|
r#"
|
|
|
|
use common::foo;
|
|
|
|
fn main() {}
|
|
|
|
"#,
|
|
|
|
)
|
|
|
|
.file("src/lib.rs", "use common::bar;")
|
|
|
|
.build();
|
|
|
|
|
|
|
|
p.cargo("check")
|
|
|
|
.with_status(101)
|
|
|
|
.with_stderr_contains("[..]unresolved import `common::bar`[..]")
|
|
|
|
.run();
|
|
|
|
|
2020-03-15 22:59:42 +00:00
|
|
|
p.cargo("check -Zfeatures=host_dep")
|
2019-09-10 22:38:01 +00:00
|
|
|
.masquerade_as_nightly_cargo()
|
|
|
|
.run();
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cargo_test]
|
2020-03-15 22:59:42 +00:00
|
|
|
fn decouple_host_deps_nested() {
|
|
|
|
// `host_dep` decouple of transitive dependencies.
|
2019-09-10 22:38:01 +00:00
|
|
|
Package::new("common", "1.0.0")
|
|
|
|
.feature("f1", &[])
|
|
|
|
.file(
|
|
|
|
"src/lib.rs",
|
|
|
|
r#"
|
|
|
|
#[cfg(feature = "f1")]
|
|
|
|
pub fn foo() {}
|
|
|
|
#[cfg(not(feature = "f1"))]
|
|
|
|
pub fn bar() {}
|
|
|
|
"#,
|
|
|
|
)
|
|
|
|
.publish();
|
|
|
|
|
|
|
|
let p = project()
|
|
|
|
.file(
|
|
|
|
"Cargo.toml",
|
|
|
|
r#"
|
|
|
|
[package]
|
|
|
|
name = "foo"
|
|
|
|
version = "0.1.0"
|
|
|
|
edition = "2018"
|
|
|
|
|
|
|
|
[build-dependencies]
|
|
|
|
bdep = {path="bdep"}
|
|
|
|
|
|
|
|
[dependencies]
|
|
|
|
common = "1.0"
|
|
|
|
"#,
|
|
|
|
)
|
|
|
|
.file(
|
|
|
|
"build.rs",
|
|
|
|
r#"
|
|
|
|
use bdep::foo;
|
|
|
|
fn main() {}
|
|
|
|
"#,
|
|
|
|
)
|
|
|
|
.file("src/lib.rs", "use common::bar;")
|
|
|
|
.file(
|
|
|
|
"bdep/Cargo.toml",
|
|
|
|
r#"
|
|
|
|
[package]
|
|
|
|
name = "bdep"
|
|
|
|
version = "0.1.0"
|
|
|
|
edition = "2018"
|
|
|
|
|
|
|
|
[dependencies]
|
|
|
|
common = {version="1.0", features=["f1"]}
|
|
|
|
"#,
|
|
|
|
)
|
|
|
|
.file("bdep/src/lib.rs", "pub use common::foo;")
|
|
|
|
.build();
|
|
|
|
|
|
|
|
p.cargo("check")
|
|
|
|
.with_status(101)
|
|
|
|
.with_stderr_contains("[..]unresolved import `common::bar`[..]")
|
|
|
|
.run();
|
|
|
|
|
2020-03-15 22:59:42 +00:00
|
|
|
p.cargo("check -Zfeatures=host_dep")
|
2019-09-10 22:38:01 +00:00
|
|
|
.masquerade_as_nightly_cargo()
|
|
|
|
.run();
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cargo_test]
|
|
|
|
fn decouple_dev_deps() {
|
|
|
|
// Basic test for `dev_dep` decouple.
|
|
|
|
Package::new("common", "1.0.0")
|
|
|
|
.feature("f1", &[])
|
|
|
|
.feature("f2", &[])
|
|
|
|
.file(
|
|
|
|
"src/lib.rs",
|
|
|
|
r#"
|
2020-01-30 19:12:23 +00:00
|
|
|
// const ensures it uses the correct dependency at *build time*
|
|
|
|
// compared to *link time*.
|
|
|
|
#[cfg(all(feature="f1", not(feature="f2")))]
|
|
|
|
pub const X: u32 = 1;
|
|
|
|
|
|
|
|
#[cfg(all(feature="f1", feature="f2"))]
|
|
|
|
pub const X: u32 = 3;
|
|
|
|
|
2019-09-10 22:38:01 +00:00
|
|
|
pub fn foo() -> u32 {
|
|
|
|
let mut res = 0;
|
|
|
|
if cfg!(feature = "f1") {
|
|
|
|
res |= 1;
|
|
|
|
}
|
|
|
|
if cfg!(feature = "f2") {
|
|
|
|
res |= 2;
|
|
|
|
}
|
|
|
|
res
|
|
|
|
}
|
|
|
|
"#,
|
|
|
|
)
|
|
|
|
.publish();
|
|
|
|
|
|
|
|
let p = project()
|
|
|
|
.file(
|
|
|
|
"Cargo.toml",
|
|
|
|
r#"
|
|
|
|
[package]
|
|
|
|
name = "foo"
|
|
|
|
version = "0.1.0"
|
|
|
|
edition = "2018"
|
|
|
|
|
|
|
|
[dependencies]
|
|
|
|
common = {version="1.0", features=["f1"]}
|
|
|
|
|
|
|
|
[dev-dependencies]
|
|
|
|
common = {version="1.0", features=["f2"]}
|
|
|
|
"#,
|
|
|
|
)
|
|
|
|
.file(
|
|
|
|
"src/main.rs",
|
|
|
|
r#"
|
|
|
|
fn main() {
|
2020-01-30 19:12:23 +00:00
|
|
|
let expected: u32 = std::env::args().skip(1).next().unwrap().parse().unwrap();
|
|
|
|
assert_eq!(foo::foo(), expected);
|
|
|
|
assert_eq!(foo::build_time(), expected);
|
|
|
|
assert_eq!(common::foo(), expected);
|
|
|
|
assert_eq!(common::X, expected);
|
2019-09-10 22:38:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_bin() {
|
|
|
|
assert_eq!(foo::foo(), 3);
|
|
|
|
assert_eq!(common::foo(), 3);
|
2020-01-30 19:12:23 +00:00
|
|
|
assert_eq!(common::X, 3);
|
|
|
|
assert_eq!(foo::build_time(), 3);
|
2019-09-10 22:38:01 +00:00
|
|
|
}
|
|
|
|
"#,
|
|
|
|
)
|
|
|
|
.file(
|
|
|
|
"src/lib.rs",
|
|
|
|
r#"
|
|
|
|
pub fn foo() -> u32 {
|
|
|
|
common::foo()
|
|
|
|
}
|
|
|
|
|
2020-01-30 19:12:23 +00:00
|
|
|
pub fn build_time() -> u32 {
|
|
|
|
common::X
|
|
|
|
}
|
|
|
|
|
2019-09-10 22:38:01 +00:00
|
|
|
#[test]
|
|
|
|
fn test_lib() {
|
|
|
|
assert_eq!(foo(), 3);
|
|
|
|
assert_eq!(common::foo(), 3);
|
2020-01-30 19:12:23 +00:00
|
|
|
assert_eq!(common::X, 3);
|
2019-09-10 22:38:01 +00:00
|
|
|
}
|
|
|
|
"#,
|
|
|
|
)
|
|
|
|
.file(
|
|
|
|
"tests/t1.rs",
|
|
|
|
r#"
|
|
|
|
#[test]
|
|
|
|
fn test_t1() {
|
|
|
|
assert_eq!(foo::foo(), 3);
|
|
|
|
assert_eq!(common::foo(), 3);
|
2020-01-30 19:12:23 +00:00
|
|
|
assert_eq!(common::X, 3);
|
|
|
|
assert_eq!(foo::build_time(), 3);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_main() {
|
|
|
|
// Features are unified for main when run with `cargo test`,
|
|
|
|
// even with -Zfeatures=dev_dep.
|
|
|
|
let s = std::process::Command::new("target/debug/foo")
|
|
|
|
.arg("3")
|
|
|
|
.status().unwrap();
|
|
|
|
assert!(s.success());
|
2019-09-10 22:38:01 +00:00
|
|
|
}
|
|
|
|
"#,
|
|
|
|
)
|
|
|
|
.build();
|
|
|
|
|
2020-01-30 19:12:23 +00:00
|
|
|
p.cargo("run 3").run();
|
2019-09-10 22:38:01 +00:00
|
|
|
|
2020-01-30 19:12:23 +00:00
|
|
|
p.cargo("run -Zfeatures=dev_dep 1")
|
2019-09-10 22:38:01 +00:00
|
|
|
.masquerade_as_nightly_cargo()
|
|
|
|
.run();
|
|
|
|
|
|
|
|
p.cargo("test").run();
|
|
|
|
|
|
|
|
p.cargo("test -Zfeatures=dev_dep")
|
|
|
|
.masquerade_as_nightly_cargo()
|
|
|
|
.run();
|
|
|
|
}
|
2020-02-01 19:38:05 +00:00
|
|
|
|
|
|
|
#[cargo_test]
|
|
|
|
fn build_script_runtime_features() {
|
|
|
|
// Check that the CARGO_FEATURE_* environment variable is set correctly.
|
|
|
|
//
|
|
|
|
// This has a common dependency between build/normal/dev-deps, and it
|
|
|
|
// queries which features it was built with in different circumstances.
|
|
|
|
Package::new("common", "1.0.0")
|
|
|
|
.feature("normal", &[])
|
|
|
|
.feature("dev", &[])
|
|
|
|
.feature("build", &[])
|
|
|
|
.file(
|
|
|
|
"build.rs",
|
|
|
|
r#"
|
|
|
|
fn is_set(name: &str) -> bool {
|
|
|
|
std::env::var(name) == Ok("1".to_string())
|
|
|
|
}
|
|
|
|
|
|
|
|
fn main() {
|
|
|
|
let mut res = 0;
|
|
|
|
if is_set("CARGO_FEATURE_NORMAL") {
|
|
|
|
res |= 1;
|
|
|
|
}
|
|
|
|
if is_set("CARGO_FEATURE_DEV") {
|
|
|
|
res |= 2;
|
|
|
|
}
|
|
|
|
if is_set("CARGO_FEATURE_BUILD") {
|
|
|
|
res |= 4;
|
|
|
|
}
|
|
|
|
println!("cargo:rustc-cfg=RunCustomBuild=\"{}\"", res);
|
|
|
|
|
|
|
|
let mut res = 0;
|
|
|
|
if cfg!(feature = "normal") {
|
|
|
|
res |= 1;
|
|
|
|
}
|
|
|
|
if cfg!(feature = "dev") {
|
|
|
|
res |= 2;
|
|
|
|
}
|
|
|
|
if cfg!(feature = "build") {
|
|
|
|
res |= 4;
|
|
|
|
}
|
|
|
|
println!("cargo:rustc-cfg=CustomBuild=\"{}\"", res);
|
|
|
|
}
|
|
|
|
"#,
|
|
|
|
)
|
|
|
|
.file(
|
|
|
|
"src/lib.rs",
|
|
|
|
r#"
|
|
|
|
pub fn foo() -> u32 {
|
|
|
|
let mut res = 0;
|
|
|
|
if cfg!(feature = "normal") {
|
|
|
|
res |= 1;
|
|
|
|
}
|
|
|
|
if cfg!(feature = "dev") {
|
|
|
|
res |= 2;
|
|
|
|
}
|
|
|
|
if cfg!(feature = "build") {
|
|
|
|
res |= 4;
|
|
|
|
}
|
|
|
|
res
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn build_time() -> u32 {
|
|
|
|
#[cfg(RunCustomBuild="1")] return 1;
|
|
|
|
#[cfg(RunCustomBuild="3")] return 3;
|
|
|
|
#[cfg(RunCustomBuild="4")] return 4;
|
|
|
|
#[cfg(RunCustomBuild="5")] return 5;
|
|
|
|
#[cfg(RunCustomBuild="7")] return 7;
|
|
|
|
}
|
|
|
|
"#,
|
|
|
|
)
|
|
|
|
.publish();
|
|
|
|
|
|
|
|
let p = project()
|
|
|
|
.file(
|
|
|
|
"Cargo.toml",
|
|
|
|
r#"
|
|
|
|
[package]
|
|
|
|
name = "foo"
|
|
|
|
version = "0.1.0"
|
|
|
|
edition = "2018"
|
|
|
|
|
|
|
|
[build-dependencies]
|
|
|
|
common = {version="1.0", features=["build"]}
|
|
|
|
|
|
|
|
[dependencies]
|
|
|
|
common = {version="1.0", features=["normal"]}
|
|
|
|
|
|
|
|
[dev-dependencies]
|
|
|
|
common = {version="1.0", features=["dev"]}
|
|
|
|
"#,
|
|
|
|
)
|
|
|
|
.file(
|
|
|
|
"build.rs",
|
|
|
|
r#"
|
|
|
|
fn main() {
|
|
|
|
assert_eq!(common::foo(), common::build_time());
|
|
|
|
println!("cargo:rustc-cfg=from_build=\"{}\"", common::foo());
|
|
|
|
}
|
|
|
|
"#,
|
|
|
|
)
|
|
|
|
.file(
|
|
|
|
"src/lib.rs",
|
|
|
|
r#"
|
|
|
|
pub fn foo() -> u32 {
|
|
|
|
common::foo()
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn build_time() -> u32 {
|
|
|
|
common::build_time()
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_lib() {
|
|
|
|
assert_eq!(common::foo(), common::build_time());
|
|
|
|
assert_eq!(common::foo(),
|
|
|
|
std::env::var("CARGO_FEATURE_EXPECT").unwrap().parse().unwrap());
|
|
|
|
}
|
|
|
|
"#,
|
|
|
|
)
|
|
|
|
.file(
|
|
|
|
"src/main.rs",
|
|
|
|
r#"
|
|
|
|
fn main() {
|
|
|
|
assert_eq!(common::foo(), common::build_time());
|
|
|
|
assert_eq!(common::foo(),
|
|
|
|
std::env::var("CARGO_FEATURE_EXPECT").unwrap().parse().unwrap());
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_bin() {
|
|
|
|
assert_eq!(common::foo(), common::build_time());
|
|
|
|
assert_eq!(common::foo(),
|
|
|
|
std::env::var("CARGO_FEATURE_EXPECT").unwrap().parse().unwrap());
|
|
|
|
}
|
|
|
|
"#,
|
|
|
|
)
|
|
|
|
.file(
|
|
|
|
"tests/t1.rs",
|
|
|
|
r#"
|
|
|
|
#[test]
|
|
|
|
fn test_t1() {
|
|
|
|
assert_eq!(common::foo(), common::build_time());
|
|
|
|
assert_eq!(common::foo(),
|
|
|
|
std::env::var("CARGO_FEATURE_EXPECT").unwrap().parse().unwrap());
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_main() {
|
|
|
|
// Features are unified for main when run with `cargo test`,
|
|
|
|
// even with -Zfeatures=dev_dep.
|
|
|
|
let s = std::process::Command::new("target/debug/foo")
|
|
|
|
.status().unwrap();
|
|
|
|
assert!(s.success());
|
|
|
|
}
|
|
|
|
"#,
|
|
|
|
)
|
|
|
|
.build();
|
|
|
|
|
|
|
|
// Old way, unifies all 3.
|
|
|
|
p.cargo("run").env("CARGO_FEATURE_EXPECT", "7").run();
|
|
|
|
|
|
|
|
// normal + build unify
|
|
|
|
p.cargo("run -Zfeatures=dev_dep")
|
|
|
|
.env("CARGO_FEATURE_EXPECT", "5")
|
|
|
|
.masquerade_as_nightly_cargo()
|
|
|
|
.run();
|
|
|
|
|
|
|
|
// Normal only.
|
2020-03-15 22:59:42 +00:00
|
|
|
p.cargo("run -Zfeatures=dev_dep,host_dep")
|
2020-02-01 19:38:05 +00:00
|
|
|
.env("CARGO_FEATURE_EXPECT", "1")
|
|
|
|
.masquerade_as_nightly_cargo()
|
|
|
|
.run();
|
|
|
|
|
|
|
|
p.cargo("test").env("CARGO_FEATURE_EXPECT", "7").run();
|
|
|
|
|
|
|
|
// dev_deps are still unified with `cargo test`
|
|
|
|
p.cargo("test -Zfeatures=dev_dep")
|
|
|
|
.env("CARGO_FEATURE_EXPECT", "7")
|
|
|
|
.masquerade_as_nightly_cargo()
|
|
|
|
.run();
|
|
|
|
|
|
|
|
// normal + dev unify
|
2020-03-15 22:59:42 +00:00
|
|
|
p.cargo("test -Zfeatures=host_dep")
|
2020-02-01 19:38:05 +00:00
|
|
|
.env("CARGO_FEATURE_EXPECT", "3")
|
|
|
|
.masquerade_as_nightly_cargo()
|
|
|
|
.run();
|
|
|
|
}
|
2020-02-01 22:33:51 +00:00
|
|
|
|
|
|
|
#[cargo_test]
|
|
|
|
fn cyclical_dev_dep() {
|
|
|
|
// Check how a cyclical dev-dependency will work.
|
|
|
|
let p = project()
|
|
|
|
.file(
|
|
|
|
"Cargo.toml",
|
|
|
|
r#"
|
|
|
|
[package]
|
|
|
|
name = "foo"
|
|
|
|
version = "0.1.0"
|
|
|
|
edition = "2018"
|
|
|
|
|
|
|
|
[features]
|
|
|
|
dev = []
|
|
|
|
|
|
|
|
[dev-dependencies]
|
|
|
|
foo = { path = '.', features = ["dev"] }
|
|
|
|
"#,
|
|
|
|
)
|
|
|
|
.file(
|
|
|
|
"src/lib.rs",
|
|
|
|
r#"
|
|
|
|
pub fn assert_dev(enabled: bool) {
|
|
|
|
assert_eq!(enabled, cfg!(feature="dev"));
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_in_lib() {
|
|
|
|
assert_dev(true);
|
|
|
|
}
|
|
|
|
"#,
|
|
|
|
)
|
|
|
|
.file(
|
|
|
|
"src/main.rs",
|
|
|
|
r#"
|
|
|
|
fn main() {
|
|
|
|
let expected: bool = std::env::args().skip(1).next().unwrap().parse().unwrap();
|
|
|
|
foo::assert_dev(expected);
|
|
|
|
}
|
|
|
|
"#,
|
|
|
|
)
|
|
|
|
.file(
|
|
|
|
"tests/t1.rs",
|
|
|
|
r#"
|
|
|
|
#[test]
|
|
|
|
fn integration_links() {
|
|
|
|
foo::assert_dev(true);
|
|
|
|
// The lib linked with main.rs will also be unified.
|
|
|
|
let s = std::process::Command::new("target/debug/foo")
|
|
|
|
.arg("true")
|
|
|
|
.status().unwrap();
|
|
|
|
assert!(s.success());
|
|
|
|
}
|
|
|
|
"#,
|
|
|
|
)
|
|
|
|
.build();
|
|
|
|
|
|
|
|
// Old way unifies features.
|
|
|
|
p.cargo("run true").run();
|
|
|
|
|
|
|
|
// Should decouple main.
|
|
|
|
p.cargo("run -Zfeatures=dev_dep false")
|
|
|
|
.masquerade_as_nightly_cargo()
|
|
|
|
.run();
|
|
|
|
|
|
|
|
// dev feature should always be enabled in tests.
|
|
|
|
p.cargo("test").run();
|
|
|
|
|
|
|
|
// And this should be no different.
|
|
|
|
p.cargo("test -Zfeatures=dev_dep")
|
|
|
|
.masquerade_as_nightly_cargo()
|
|
|
|
.run();
|
|
|
|
}
|
2020-02-01 22:57:28 +00:00
|
|
|
|
|
|
|
#[cargo_test]
|
|
|
|
fn all_feature_opts() {
|
|
|
|
// All feature options at once.
|
|
|
|
Package::new("common", "1.0.0")
|
|
|
|
.feature("normal", &[])
|
|
|
|
.feature("build", &[])
|
|
|
|
.feature("dev", &[])
|
|
|
|
.feature("itarget", &[])
|
|
|
|
.file(
|
|
|
|
"src/lib.rs",
|
|
|
|
r#"
|
|
|
|
pub fn feats() -> u32 {
|
|
|
|
let mut res = 0;
|
|
|
|
if cfg!(feature="normal") { res |= 1; }
|
|
|
|
if cfg!(feature="build") { res |= 2; }
|
|
|
|
if cfg!(feature="dev") { res |= 4; }
|
|
|
|
if cfg!(feature="itarget") { res |= 8; }
|
|
|
|
res
|
|
|
|
}
|
|
|
|
"#,
|
|
|
|
)
|
|
|
|
.publish();
|
|
|
|
|
|
|
|
let p = project()
|
|
|
|
.file(
|
|
|
|
"Cargo.toml",
|
|
|
|
r#"
|
|
|
|
[package]
|
|
|
|
name = "foo"
|
|
|
|
version = "0.1.0"
|
|
|
|
edition = "2018"
|
|
|
|
|
|
|
|
[dependencies]
|
|
|
|
common = {version = "1.0", features=["normal"]}
|
|
|
|
|
|
|
|
[dev-dependencies]
|
|
|
|
common = {version = "1.0", features=["dev"]}
|
|
|
|
|
|
|
|
[build-dependencies]
|
|
|
|
common = {version = "1.0", features=["build"]}
|
|
|
|
|
|
|
|
[target.'cfg(whatever)'.dependencies]
|
|
|
|
common = {version = "1.0", features=["itarget"]}
|
|
|
|
"#,
|
|
|
|
)
|
|
|
|
.file(
|
|
|
|
"src/main.rs",
|
|
|
|
r#"
|
|
|
|
fn main() {
|
|
|
|
expect();
|
|
|
|
}
|
|
|
|
|
|
|
|
fn expect() {
|
|
|
|
let expected: u32 = std::env::var("EXPECTED_FEATS").unwrap().parse().unwrap();
|
|
|
|
assert_eq!(expected, common::feats());
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn from_test() {
|
|
|
|
expect();
|
|
|
|
}
|
|
|
|
"#,
|
|
|
|
)
|
|
|
|
.build();
|
|
|
|
|
|
|
|
p.cargo("run").env("EXPECTED_FEATS", "15").run();
|
|
|
|
|
|
|
|
// Only normal feature.
|
|
|
|
p.cargo("run -Zfeatures=all")
|
|
|
|
.masquerade_as_nightly_cargo()
|
|
|
|
.env("EXPECTED_FEATS", "1")
|
|
|
|
.run();
|
|
|
|
|
|
|
|
p.cargo("test").env("EXPECTED_FEATS", "15").run();
|
|
|
|
|
|
|
|
// only normal+dev
|
|
|
|
p.cargo("test -Zfeatures=all")
|
|
|
|
.masquerade_as_nightly_cargo()
|
|
|
|
.env("EXPECTED_FEATS", "5")
|
|
|
|
.run();
|
|
|
|
}
|
2020-02-02 22:27:16 +00:00
|
|
|
|
|
|
|
#[cargo_test]
|
2020-03-15 22:59:42 +00:00
|
|
|
fn required_features_host_dep() {
|
2020-02-02 22:27:16 +00:00
|
|
|
// Check that required-features handles build-dependencies correctly.
|
|
|
|
let p = project()
|
|
|
|
.file(
|
|
|
|
"Cargo.toml",
|
|
|
|
r#"
|
|
|
|
[package]
|
|
|
|
name = "foo"
|
|
|
|
version = "0.1.0"
|
|
|
|
edition = "2018"
|
|
|
|
|
|
|
|
[[bin]]
|
|
|
|
name = "x"
|
|
|
|
required-features = ["bdep/f1"]
|
|
|
|
|
|
|
|
[build-dependencies]
|
|
|
|
bdep = {path="bdep"}
|
|
|
|
"#,
|
|
|
|
)
|
|
|
|
.file("build.rs", "fn main() {}")
|
|
|
|
.file(
|
|
|
|
"src/bin/x.rs",
|
|
|
|
r#"
|
|
|
|
fn main() {}
|
|
|
|
"#,
|
|
|
|
)
|
|
|
|
.file(
|
|
|
|
"bdep/Cargo.toml",
|
|
|
|
r#"
|
|
|
|
[package]
|
|
|
|
name = "bdep"
|
|
|
|
version = "0.1.0"
|
|
|
|
|
|
|
|
[features]
|
|
|
|
f1 = []
|
|
|
|
"#,
|
|
|
|
)
|
|
|
|
.file("bdep/src/lib.rs", "")
|
|
|
|
.build();
|
|
|
|
|
|
|
|
p.cargo("run")
|
|
|
|
.with_status(101)
|
|
|
|
.with_stderr(
|
|
|
|
"\
|
|
|
|
[ERROR] target `x` in package `foo` requires the features: `bdep/f1`
|
|
|
|
Consider enabling them by passing, e.g., `--features=\"bdep/f1\"`
|
|
|
|
",
|
|
|
|
)
|
|
|
|
.run();
|
|
|
|
|
2020-03-15 22:59:42 +00:00
|
|
|
p.cargo("run --features bdep/f1 -Zfeatures=host_dep")
|
2020-02-02 22:27:16 +00:00
|
|
|
.masquerade_as_nightly_cargo()
|
|
|
|
.run();
|
|
|
|
}
|
2020-02-20 19:42:53 +00:00
|
|
|
|
|
|
|
#[cargo_test]
|
2020-03-15 22:59:42 +00:00
|
|
|
fn disabled_shared_host_dep() {
|
2020-02-20 19:42:53 +00:00
|
|
|
// Check for situation where an optional dep of a shared dep is enabled in
|
|
|
|
// a normal dependency, but disabled in an optional one. The unit tree is:
|
|
|
|
// foo
|
|
|
|
// ├── foo build.rs
|
|
|
|
// | └── common (BUILD dependency, NO FEATURES)
|
|
|
|
// └── common (Normal dependency, default features)
|
|
|
|
// └── somedep
|
|
|
|
Package::new("somedep", "1.0.0")
|
|
|
|
.file(
|
|
|
|
"src/lib.rs",
|
|
|
|
r#"
|
|
|
|
pub fn f() { println!("hello from somedep"); }
|
|
|
|
"#,
|
|
|
|
)
|
|
|
|
.publish();
|
|
|
|
Package::new("common", "1.0.0")
|
|
|
|
.feature("default", &["somedep"])
|
|
|
|
.add_dep(Dependency::new("somedep", "1.0").optional(true))
|
|
|
|
.file(
|
|
|
|
"src/lib.rs",
|
|
|
|
r#"
|
|
|
|
pub fn check_somedep() -> bool {
|
|
|
|
#[cfg(feature="somedep")]
|
|
|
|
{
|
|
|
|
extern crate somedep;
|
|
|
|
somedep::f();
|
|
|
|
true
|
|
|
|
}
|
|
|
|
#[cfg(not(feature="somedep"))]
|
|
|
|
{
|
|
|
|
println!("no somedep");
|
|
|
|
false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
"#,
|
|
|
|
)
|
|
|
|
.publish();
|
|
|
|
|
|
|
|
let p = project()
|
|
|
|
.file(
|
|
|
|
"Cargo.toml",
|
|
|
|
r#"
|
|
|
|
[package]
|
|
|
|
name = "foo"
|
|
|
|
version = "1.0.0"
|
|
|
|
edition = "2018"
|
|
|
|
|
|
|
|
[dependencies]
|
|
|
|
common = "1.0"
|
|
|
|
|
|
|
|
[build-dependencies]
|
|
|
|
common = {version = "1.0", default-features = false}
|
|
|
|
"#,
|
|
|
|
)
|
|
|
|
.file(
|
|
|
|
"src/main.rs",
|
|
|
|
"fn main() { assert!(common::check_somedep()); }",
|
|
|
|
)
|
|
|
|
.file(
|
|
|
|
"build.rs",
|
|
|
|
"fn main() { assert!(!common::check_somedep()); }",
|
|
|
|
)
|
|
|
|
.build();
|
|
|
|
|
2020-03-15 22:59:42 +00:00
|
|
|
p.cargo("run -Zfeatures=host_dep -v")
|
2020-02-20 19:42:53 +00:00
|
|
|
.masquerade_as_nightly_cargo()
|
|
|
|
.with_stdout("hello from somedep")
|
|
|
|
.run();
|
|
|
|
}
|
2020-03-03 19:46:37 +00:00
|
|
|
|
|
|
|
#[cargo_test]
|
|
|
|
fn required_features_inactive_dep() {
|
|
|
|
// required-features with an inactivated dep.
|
|
|
|
let p = project()
|
|
|
|
.file(
|
|
|
|
"Cargo.toml",
|
|
|
|
r#"
|
|
|
|
[package]
|
|
|
|
name = "foo"
|
|
|
|
version = "0.1.0"
|
|
|
|
|
|
|
|
[target.'cfg(whatever)'.dependencies]
|
|
|
|
bar = {path="bar"}
|
|
|
|
|
|
|
|
[[bin]]
|
|
|
|
name = "foo"
|
|
|
|
required-features = ["feat1"]
|
|
|
|
|
|
|
|
[features]
|
|
|
|
feat1 = []
|
|
|
|
"#,
|
|
|
|
)
|
|
|
|
.file("src/main.rs", "fn main() {}")
|
|
|
|
.file("bar/Cargo.toml", &basic_manifest("bar", "0.1.0"))
|
|
|
|
.file("bar/src/lib.rs", "")
|
|
|
|
.build();
|
|
|
|
|
|
|
|
p.cargo("check -Zfeatures=itarget")
|
|
|
|
.masquerade_as_nightly_cargo()
|
|
|
|
.with_stderr("[FINISHED] [..]")
|
|
|
|
.run();
|
|
|
|
|
|
|
|
p.cargo("check -Zfeatures=itarget --features=feat1")
|
|
|
|
.masquerade_as_nightly_cargo()
|
|
|
|
.with_stderr("[CHECKING] foo[..]\n[FINISHED] [..]")
|
|
|
|
.run();
|
|
|
|
}
|
2020-03-15 22:59:42 +00:00
|
|
|
|
|
|
|
#[cargo_test]
|
|
|
|
fn decouple_proc_macro() {
|
|
|
|
// proc macro features are not shared
|
|
|
|
Package::new("common", "1.0.0")
|
|
|
|
.feature("somefeat", &[])
|
|
|
|
.file(
|
|
|
|
"src/lib.rs",
|
|
|
|
r#"
|
|
|
|
pub const fn foo() -> bool { cfg!(feature="somefeat") }
|
|
|
|
#[cfg(feature="somefeat")]
|
|
|
|
pub const FEAT_ONLY_CONST: bool = true;
|
|
|
|
"#,
|
|
|
|
)
|
|
|
|
.publish();
|
|
|
|
Package::new("pm", "1.0.0")
|
|
|
|
.proc_macro(true)
|
|
|
|
.feature_dep("common", "1.0", &["somefeat"])
|
|
|
|
.file(
|
|
|
|
"src/lib.rs",
|
|
|
|
r#"
|
|
|
|
extern crate proc_macro;
|
|
|
|
extern crate common;
|
|
|
|
#[proc_macro]
|
|
|
|
pub fn foo(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
|
|
|
|
assert!(common::foo());
|
|
|
|
"".parse().unwrap()
|
|
|
|
}
|
|
|
|
"#,
|
|
|
|
)
|
|
|
|
.publish();
|
|
|
|
let p = project()
|
|
|
|
.file(
|
|
|
|
"Cargo.toml",
|
|
|
|
r#"
|
|
|
|
[package]
|
|
|
|
name = "foo"
|
|
|
|
version = "1.0.0"
|
|
|
|
edition = "2018"
|
|
|
|
|
|
|
|
[dependencies]
|
|
|
|
pm = "1.0"
|
|
|
|
common = "1.0"
|
|
|
|
"#,
|
|
|
|
)
|
|
|
|
.file(
|
|
|
|
"src/lib.rs",
|
|
|
|
r#"
|
|
|
|
//! Test with docs.
|
|
|
|
//!
|
|
|
|
//! ```rust
|
|
|
|
//! pm::foo!{}
|
|
|
|
//! fn main() {
|
|
|
|
//! let expected = std::env::var_os("TEST_EXPECTS_ENABLED").is_some();
|
|
|
|
//! assert_eq!(expected, common::foo(), "common is wrong");
|
|
|
|
//! }
|
|
|
|
//! ```
|
|
|
|
"#,
|
|
|
|
)
|
|
|
|
.file(
|
|
|
|
"src/main.rs",
|
|
|
|
r#"
|
|
|
|
pm::foo!{}
|
|
|
|
fn main() {
|
|
|
|
println!("it is {}", common::foo());
|
|
|
|
}
|
|
|
|
"#,
|
|
|
|
)
|
|
|
|
.build();
|
|
|
|
|
|
|
|
p.cargo("run")
|
|
|
|
.env("TEST_EXPECTS_ENABLED", "1")
|
|
|
|
.with_stdout("it is true")
|
|
|
|
.run();
|
|
|
|
|
|
|
|
p.cargo("run -Zfeatures=host_dep")
|
|
|
|
.masquerade_as_nightly_cargo()
|
|
|
|
.with_stdout("it is false")
|
|
|
|
.run();
|
|
|
|
|
|
|
|
// Make sure the test is fallible.
|
|
|
|
p.cargo("test --doc")
|
|
|
|
.with_status(101)
|
|
|
|
.with_stdout_contains("[..]common is wrong[..]")
|
|
|
|
.run();
|
|
|
|
|
|
|
|
p.cargo("test --doc").env("TEST_EXPECTS_ENABLED", "1").run();
|
|
|
|
|
|
|
|
p.cargo("test --doc -Zfeatures=host_dep")
|
|
|
|
.masquerade_as_nightly_cargo()
|
|
|
|
.run();
|
|
|
|
|
|
|
|
p.cargo("doc").run();
|
|
|
|
assert!(p
|
|
|
|
.build_dir()
|
|
|
|
.join("doc/common/constant.FEAT_ONLY_CONST.html")
|
|
|
|
.exists());
|
|
|
|
// cargo doc should clean in-between runs, but it doesn't, and leaves stale files.
|
|
|
|
// https://github.com/rust-lang/cargo/issues/6783 (same for removed items)
|
|
|
|
p.build_dir().join("doc").rm_rf();
|
|
|
|
|
|
|
|
p.cargo("doc -Zfeatures=host_dep")
|
|
|
|
.masquerade_as_nightly_cargo()
|
|
|
|
.run();
|
|
|
|
assert!(!p
|
|
|
|
.build_dir()
|
|
|
|
.join("doc/common/constant.FEAT_ONLY_CONST.html")
|
|
|
|
.exists());
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cargo_test]
|
|
|
|
fn proc_macro_ws() {
|
|
|
|
// Checks for bug with proc-macro in a workspace with dependency (shouldn't panic).
|
|
|
|
let p = project()
|
|
|
|
.file(
|
|
|
|
"Cargo.toml",
|
|
|
|
r#"
|
|
|
|
[workspace]
|
|
|
|
members = ["foo", "pm"]
|
|
|
|
"#,
|
|
|
|
)
|
|
|
|
.file(
|
|
|
|
"foo/Cargo.toml",
|
|
|
|
r#"
|
|
|
|
[package]
|
|
|
|
name = "foo"
|
|
|
|
version = "0.1.0"
|
|
|
|
|
|
|
|
[features]
|
|
|
|
feat1 = []
|
|
|
|
"#,
|
|
|
|
)
|
|
|
|
.file("foo/src/lib.rs", "")
|
|
|
|
.file(
|
|
|
|
"pm/Cargo.toml",
|
|
|
|
r#"
|
|
|
|
[package]
|
|
|
|
name = "pm"
|
|
|
|
version = "0.1.0"
|
|
|
|
|
|
|
|
[lib]
|
|
|
|
proc-macro = true
|
|
|
|
|
|
|
|
[dependencies]
|
|
|
|
foo = { path = "../foo", features=["feat1"] }
|
|
|
|
"#,
|
|
|
|
)
|
|
|
|
.file("pm/src/lib.rs", "")
|
|
|
|
.build();
|
|
|
|
|
|
|
|
p.cargo("check -p pm -Zfeatures=host_dep -v")
|
|
|
|
.masquerade_as_nightly_cargo()
|
|
|
|
.with_stderr_contains("[RUNNING] `rustc --crate-name foo [..]--cfg[..]feat1[..]")
|
|
|
|
.run();
|
|
|
|
// This may be surprising that `foo` doesn't get built separately. It is
|
|
|
|
// because pm might have other units (binaries, tests, etc.), and so the
|
|
|
|
// feature resolver must assume that normal deps get unified with it. This
|
|
|
|
// is related to the bigger issue where the features selected in a
|
|
|
|
// workspace depend on which packages are selected.
|
|
|
|
p.cargo("check --workspace -Zfeatures=host_dep -v")
|
|
|
|
.masquerade_as_nightly_cargo()
|
|
|
|
.with_stderr(
|
|
|
|
"\
|
|
|
|
[FRESH] foo v0.1.0 [..]
|
|
|
|
[FRESH] pm v0.1.0 [..]
|
|
|
|
[FINISHED] dev [..]
|
|
|
|
",
|
|
|
|
)
|
|
|
|
.run();
|
|
|
|
// Selecting just foo will build without unification.
|
|
|
|
p.cargo("check -p foo -Zfeatures=host_dep -v")
|
|
|
|
.masquerade_as_nightly_cargo()
|
|
|
|
// Make sure `foo` is built without feat1
|
|
|
|
.with_stderr_line_without(&["[RUNNING] `rustc --crate-name foo"], &["--cfg[..]feat1"])
|
|
|
|
.run();
|
|
|
|
}
|
2020-03-22 17:58:10 +00:00
|
|
|
|
|
|
|
#[cargo_test]
|
|
|
|
fn has_dev_dep_for_test() {
|
|
|
|
// Check for a bug where the decision on whether or not "dev dependencies"
|
|
|
|
// should be used did not consider `check --profile=test`.
|
|
|
|
let p = project()
|
|
|
|
.file(
|
|
|
|
"Cargo.toml",
|
|
|
|
r#"
|
|
|
|
[package]
|
|
|
|
name = "foo"
|
|
|
|
version = "0.1.0"
|
|
|
|
|
|
|
|
[dev-dependencies]
|
|
|
|
dep = { path = 'dep', features = ['f1'] }
|
|
|
|
"#,
|
|
|
|
)
|
|
|
|
.file(
|
|
|
|
"src/lib.rs",
|
|
|
|
r#"
|
|
|
|
#[test]
|
|
|
|
fn t1() {
|
|
|
|
dep::f();
|
|
|
|
}
|
|
|
|
"#,
|
|
|
|
)
|
|
|
|
.file(
|
|
|
|
"dep/Cargo.toml",
|
|
|
|
r#"
|
|
|
|
[package]
|
|
|
|
name = "dep"
|
|
|
|
version = "0.1.0"
|
|
|
|
|
|
|
|
[features]
|
|
|
|
f1 = []
|
|
|
|
"#,
|
|
|
|
)
|
|
|
|
.file(
|
|
|
|
"dep/src/lib.rs",
|
|
|
|
r#"
|
|
|
|
#[cfg(feature = "f1")]
|
|
|
|
pub fn f() {}
|
|
|
|
"#,
|
|
|
|
)
|
|
|
|
.build();
|
|
|
|
|
|
|
|
p.cargo("check -v")
|
|
|
|
.with_stderr(
|
|
|
|
"\
|
|
|
|
[CHECKING] foo v0.1.0 [..]
|
|
|
|
[RUNNING] `rustc --crate-name foo [..]
|
|
|
|
[FINISHED] [..]
|
|
|
|
",
|
|
|
|
)
|
|
|
|
.run();
|
|
|
|
p.cargo("check -v --profile=test -Zfeatures=dev_dep")
|
|
|
|
.masquerade_as_nightly_cargo()
|
|
|
|
.with_stderr(
|
|
|
|
"\
|
|
|
|
[CHECKING] dep v0.1.0 [..]
|
|
|
|
[RUNNING] `rustc --crate-name dep [..]
|
|
|
|
[CHECKING] foo v0.1.0 [..]
|
|
|
|
[RUNNING] `rustc --crate-name foo [..]
|
|
|
|
[FINISHED] [..]
|
|
|
|
",
|
|
|
|
)
|
|
|
|
.run();
|
|
|
|
p.cargo("check -v --profile=test")
|
|
|
|
.with_stderr(
|
|
|
|
"\
|
|
|
|
[FRESH] dep [..]
|
|
|
|
[FRESH] foo [..]
|
|
|
|
[FINISHED] [..]
|
|
|
|
",
|
|
|
|
)
|
|
|
|
.run();
|
|
|
|
}
|
2020-03-27 21:58:03 +00:00
|
|
|
|
|
|
|
#[cargo_test]
|
|
|
|
fn build_dep_activated() {
|
|
|
|
// Build dependencies always match the host for [target.*.build-dependencies].
|
|
|
|
if cross_compile::disabled() {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
Package::new("somedep", "1.0.0")
|
|
|
|
.file("src/lib.rs", "")
|
|
|
|
.publish();
|
|
|
|
Package::new("targetdep", "1.0.0").publish();
|
|
|
|
Package::new("hostdep", "1.0.0")
|
|
|
|
// Check that "for_host" is sticky.
|
|
|
|
.target_dep("somedep", "1.0", &rustc_host())
|
|
|
|
.feature("feat1", &[])
|
|
|
|
.file(
|
|
|
|
"src/lib.rs",
|
|
|
|
r#"
|
|
|
|
extern crate somedep;
|
|
|
|
|
|
|
|
#[cfg(not(feature="feat1"))]
|
|
|
|
compile_error!{"feat1 missing"}
|
|
|
|
"#,
|
|
|
|
)
|
|
|
|
.publish();
|
|
|
|
|
|
|
|
let p = project()
|
|
|
|
.file(
|
|
|
|
"Cargo.toml",
|
|
|
|
&format!(
|
|
|
|
r#"
|
2020-09-27 00:59:58 +00:00
|
|
|
[package]
|
|
|
|
name = "foo"
|
|
|
|
version = "0.1.0"
|
2020-03-27 21:58:03 +00:00
|
|
|
|
2020-09-27 00:59:58 +00:00
|
|
|
# This should never be selected.
|
|
|
|
[target.'{}'.build-dependencies]
|
|
|
|
targetdep = "1.0"
|
2020-03-27 21:58:03 +00:00
|
|
|
|
2020-09-27 00:59:58 +00:00
|
|
|
[target.'{}'.build-dependencies]
|
|
|
|
hostdep = {{version="1.0", features=["feat1"]}}
|
|
|
|
"#,
|
2020-03-27 21:58:03 +00:00
|
|
|
alternate(),
|
|
|
|
rustc_host()
|
|
|
|
),
|
|
|
|
)
|
|
|
|
.file("src/lib.rs", "")
|
|
|
|
.file("build.rs", "fn main() {}")
|
|
|
|
.build();
|
|
|
|
|
|
|
|
p.cargo("check").run();
|
|
|
|
p.cargo("check -Zfeatures=all")
|
|
|
|
.masquerade_as_nightly_cargo()
|
|
|
|
.run();
|
|
|
|
p.cargo("check --target").arg(alternate()).run();
|
|
|
|
p.cargo("check -Zfeatures=all --target")
|
|
|
|
.arg(alternate())
|
|
|
|
.masquerade_as_nightly_cargo()
|
|
|
|
.run();
|
|
|
|
}
|
2020-04-17 18:20:38 +00:00
|
|
|
|
|
|
|
#[cargo_test]
|
|
|
|
fn resolver_gated() {
|
|
|
|
// Check that `resolver` field is feature gated.
|
|
|
|
let p = project()
|
|
|
|
.file(
|
|
|
|
"Cargo.toml",
|
|
|
|
r#"
|
|
|
|
[package]
|
|
|
|
name = "foo"
|
|
|
|
version = "0.1.0"
|
|
|
|
resolver = "2"
|
|
|
|
"#,
|
|
|
|
)
|
|
|
|
.file("src/lib.rs", "")
|
|
|
|
.build();
|
|
|
|
|
|
|
|
p.cargo("build")
|
|
|
|
.masquerade_as_nightly_cargo()
|
|
|
|
.with_status(101)
|
|
|
|
.with_stderr(
|
|
|
|
"\
|
|
|
|
error: failed to parse manifest at `[..]/foo/Cargo.toml`
|
|
|
|
|
|
|
|
Caused by:
|
|
|
|
feature `resolver` is required
|
|
|
|
|
2020-06-25 15:25:52 +00:00
|
|
|
consider adding `cargo-features = [\"resolver\"]` to the manifest
|
2020-04-17 18:20:38 +00:00
|
|
|
",
|
|
|
|
)
|
|
|
|
.run();
|
|
|
|
|
|
|
|
// Test with virtual ws.
|
|
|
|
let p = project()
|
|
|
|
.file(
|
|
|
|
"Cargo.toml",
|
|
|
|
r#"
|
|
|
|
[workspace]
|
|
|
|
members = ["a"]
|
|
|
|
resolver = "2"
|
|
|
|
"#,
|
|
|
|
)
|
|
|
|
.file("a/Cargo.toml", &basic_manifest("a", "0.1.0"))
|
|
|
|
.file("a/src/lib.rs", "")
|
|
|
|
.build();
|
|
|
|
|
|
|
|
p.cargo("build")
|
|
|
|
.masquerade_as_nightly_cargo()
|
|
|
|
.with_status(101)
|
|
|
|
.with_stderr(
|
|
|
|
"\
|
|
|
|
error: failed to parse manifest at `[..]/foo/Cargo.toml`
|
|
|
|
|
|
|
|
Caused by:
|
|
|
|
feature `resolver` is required
|
|
|
|
|
2020-06-25 15:25:52 +00:00
|
|
|
consider adding `cargo-features = [\"resolver\"]` to the manifest
|
2020-04-17 18:20:38 +00:00
|
|
|
",
|
|
|
|
)
|
|
|
|
.run();
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cargo_test]
|
|
|
|
fn resolver_bad_setting() {
|
|
|
|
// Unknown setting in `resolver`
|
|
|
|
let p = project()
|
|
|
|
.file(
|
|
|
|
"Cargo.toml",
|
|
|
|
r#"
|
|
|
|
cargo-features = ["resolver"]
|
|
|
|
[package]
|
|
|
|
name = "foo"
|
|
|
|
version = "0.1.0"
|
|
|
|
resolver = "1"
|
|
|
|
"#,
|
|
|
|
)
|
|
|
|
.file("src/lib.rs", "")
|
|
|
|
.build();
|
|
|
|
|
|
|
|
p.cargo("build")
|
|
|
|
.masquerade_as_nightly_cargo()
|
|
|
|
.with_status(101)
|
|
|
|
.with_stderr(
|
|
|
|
"\
|
|
|
|
error: failed to parse manifest at `[..]/foo/Cargo.toml`
|
|
|
|
|
|
|
|
Caused by:
|
|
|
|
`resolver` setting `1` is not valid, only valid option is \"2\"
|
|
|
|
",
|
|
|
|
)
|
|
|
|
.run();
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cargo_test]
|
|
|
|
fn resolver_not_both() {
|
|
|
|
// Can't specify resolver in both workspace and package.
|
|
|
|
let p = project()
|
|
|
|
.file(
|
|
|
|
"Cargo.toml",
|
|
|
|
r#"
|
|
|
|
cargo-features = ["resolver"]
|
|
|
|
[workspace]
|
|
|
|
resolver = "2"
|
|
|
|
[package]
|
|
|
|
name = "foo"
|
|
|
|
version = "0.1.0"
|
|
|
|
resolver = "2"
|
|
|
|
"#,
|
|
|
|
)
|
|
|
|
.file("src/lib.rs", "")
|
|
|
|
.build();
|
|
|
|
|
|
|
|
p.cargo("build")
|
|
|
|
.masquerade_as_nightly_cargo()
|
|
|
|
.with_status(101)
|
|
|
|
.with_stderr(
|
|
|
|
"\
|
|
|
|
error: failed to parse manifest at `[..]/foo/Cargo.toml`
|
|
|
|
|
|
|
|
Caused by:
|
|
|
|
cannot specify `resolver` field in both `[workspace]` and `[package]`
|
|
|
|
",
|
|
|
|
)
|
|
|
|
.run();
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cargo_test]
|
|
|
|
fn resolver_ws_member() {
|
|
|
|
// Can't specify `resolver` in a ws member.
|
|
|
|
let p = project()
|
|
|
|
.file(
|
|
|
|
"Cargo.toml",
|
|
|
|
r#"
|
|
|
|
[workspace]
|
|
|
|
members = ["a"]
|
|
|
|
"#,
|
|
|
|
)
|
|
|
|
.file(
|
|
|
|
"a/Cargo.toml",
|
|
|
|
r#"
|
|
|
|
cargo-features = ["resolver"]
|
|
|
|
[package]
|
|
|
|
name = "a"
|
|
|
|
version = "0.1.0"
|
|
|
|
resolver = "2"
|
|
|
|
"#,
|
|
|
|
)
|
|
|
|
.file("a/src/lib.rs", "")
|
|
|
|
.build();
|
|
|
|
|
|
|
|
p.cargo("check")
|
|
|
|
.masquerade_as_nightly_cargo()
|
|
|
|
.with_stderr(
|
|
|
|
"\
|
|
|
|
warning: resolver for the non root package will be ignored, specify resolver at the workspace root:
|
|
|
|
package: [..]/foo/a/Cargo.toml
|
|
|
|
workspace: [..]/foo/Cargo.toml
|
|
|
|
[CHECKING] a v0.1.0 [..]
|
|
|
|
[FINISHED] [..]
|
|
|
|
",
|
|
|
|
)
|
|
|
|
.run();
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cargo_test]
|
|
|
|
fn resolver_ws_root_and_member() {
|
|
|
|
// Check when specified in both ws root and member.
|
|
|
|
let p = project()
|
|
|
|
.file(
|
|
|
|
"Cargo.toml",
|
|
|
|
r#"
|
|
|
|
cargo-features = ["resolver"]
|
|
|
|
[workspace]
|
|
|
|
members = ["a"]
|
|
|
|
resolver = "2"
|
|
|
|
"#,
|
|
|
|
)
|
|
|
|
.file(
|
|
|
|
"a/Cargo.toml",
|
|
|
|
r#"
|
|
|
|
cargo-features = ["resolver"]
|
|
|
|
[package]
|
|
|
|
name = "a"
|
|
|
|
version = "0.1.0"
|
|
|
|
resolver = "2"
|
|
|
|
"#,
|
|
|
|
)
|
|
|
|
.file("a/src/lib.rs", "")
|
|
|
|
.build();
|
|
|
|
|
|
|
|
// Ignores if they are the same.
|
|
|
|
p.cargo("check")
|
|
|
|
.masquerade_as_nightly_cargo()
|
|
|
|
.with_stderr(
|
|
|
|
"\
|
|
|
|
[CHECKING] a v0.1.0 [..]
|
|
|
|
[FINISHED] [..]
|
|
|
|
",
|
|
|
|
)
|
|
|
|
.run();
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cargo_test]
|
|
|
|
fn resolver_enables_new_features() {
|
|
|
|
// resolver="2" enables all the things.
|
|
|
|
Package::new("common", "1.0.0")
|
|
|
|
.feature("normal", &[])
|
|
|
|
.feature("build", &[])
|
|
|
|
.feature("dev", &[])
|
|
|
|
.feature("itarget", &[])
|
|
|
|
.file(
|
|
|
|
"src/lib.rs",
|
|
|
|
r#"
|
|
|
|
pub fn feats() -> u32 {
|
|
|
|
let mut res = 0;
|
|
|
|
if cfg!(feature="normal") { res |= 1; }
|
|
|
|
if cfg!(feature="build") { res |= 2; }
|
|
|
|
if cfg!(feature="dev") { res |= 4; }
|
|
|
|
if cfg!(feature="itarget") { res |= 8; }
|
|
|
|
res
|
|
|
|
}
|
|
|
|
"#,
|
|
|
|
)
|
|
|
|
.publish();
|
|
|
|
|
|
|
|
let p = project()
|
|
|
|
.file(
|
|
|
|
"Cargo.toml",
|
|
|
|
r#"
|
|
|
|
cargo-features = ["resolver"]
|
|
|
|
[workspace]
|
|
|
|
members = ["a", "b"]
|
|
|
|
resolver = "2"
|
|
|
|
"#,
|
|
|
|
)
|
|
|
|
.file(
|
|
|
|
"a/Cargo.toml",
|
|
|
|
r#"
|
|
|
|
[package]
|
|
|
|
name = "a"
|
|
|
|
version = "0.1.0"
|
|
|
|
edition = "2018"
|
|
|
|
|
|
|
|
[dependencies]
|
|
|
|
common = {version = "1.0", features=["normal"]}
|
|
|
|
|
|
|
|
[dev-dependencies]
|
|
|
|
common = {version = "1.0", features=["dev"]}
|
|
|
|
|
|
|
|
[build-dependencies]
|
|
|
|
common = {version = "1.0", features=["build"]}
|
|
|
|
|
|
|
|
[target.'cfg(whatever)'.dependencies]
|
|
|
|
common = {version = "1.0", features=["itarget"]}
|
|
|
|
"#,
|
|
|
|
)
|
|
|
|
.file(
|
|
|
|
"a/src/main.rs",
|
|
|
|
r#"
|
|
|
|
fn main() {
|
|
|
|
expect();
|
|
|
|
}
|
|
|
|
|
|
|
|
fn expect() {
|
|
|
|
let expected: u32 = std::env::var("EXPECTED_FEATS").unwrap().parse().unwrap();
|
|
|
|
assert_eq!(expected, common::feats());
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn from_test() {
|
|
|
|
expect();
|
|
|
|
}
|
|
|
|
"#,
|
|
|
|
)
|
|
|
|
.file(
|
|
|
|
"b/Cargo.toml",
|
|
|
|
r#"
|
|
|
|
[package]
|
|
|
|
name = "b"
|
|
|
|
version = "0.1.0"
|
|
|
|
|
|
|
|
[features]
|
|
|
|
ping = []
|
|
|
|
"#,
|
|
|
|
)
|
|
|
|
.file(
|
|
|
|
"b/src/main.rs",
|
|
|
|
r#"
|
|
|
|
fn main() {
|
|
|
|
if cfg!(feature="ping") {
|
|
|
|
println!("pong");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
"#,
|
|
|
|
)
|
|
|
|
.build();
|
|
|
|
|
|
|
|
// Only normal.
|
|
|
|
p.cargo("run --bin a")
|
|
|
|
.masquerade_as_nightly_cargo()
|
|
|
|
.env("EXPECTED_FEATS", "1")
|
2020-04-27 21:16:41 +00:00
|
|
|
.with_stderr(
|
|
|
|
"\
|
|
|
|
[UPDATING] [..]
|
|
|
|
[DOWNLOADING] crates ...
|
|
|
|
[DOWNLOADED] common [..]
|
|
|
|
[COMPILING] common v1.0.0
|
|
|
|
[COMPILING] a v0.1.0 [..]
|
|
|
|
[FINISHED] [..]
|
|
|
|
[RUNNING] `target/debug/a[EXE]`
|
|
|
|
",
|
|
|
|
)
|
2020-04-17 18:20:38 +00:00
|
|
|
.run();
|
|
|
|
|
|
|
|
// only normal+dev
|
|
|
|
p.cargo("test")
|
|
|
|
.cwd("a")
|
|
|
|
.masquerade_as_nightly_cargo()
|
|
|
|
.env("EXPECTED_FEATS", "5")
|
|
|
|
.run();
|
|
|
|
|
|
|
|
// -Zpackage-features is enabled.
|
|
|
|
p.cargo("run -p b --features=ping")
|
|
|
|
.cwd("a")
|
|
|
|
.masquerade_as_nightly_cargo()
|
|
|
|
.with_stdout("pong")
|
|
|
|
.run();
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cargo_test]
|
|
|
|
fn install_resolve_behavior() {
|
|
|
|
// install honors the resolver behavior.
|
|
|
|
Package::new("common", "1.0.0")
|
|
|
|
.feature("f1", &[])
|
|
|
|
.file(
|
|
|
|
"src/lib.rs",
|
|
|
|
r#"
|
|
|
|
#[cfg(feature = "f1")]
|
|
|
|
compile_error!("f1 should not activate");
|
|
|
|
"#,
|
|
|
|
)
|
|
|
|
.publish();
|
|
|
|
|
|
|
|
Package::new("bar", "1.0.0").dep("common", "1.0").publish();
|
|
|
|
|
|
|
|
Package::new("foo", "1.0.0")
|
|
|
|
.file(
|
|
|
|
"Cargo.toml",
|
|
|
|
r#"
|
|
|
|
cargo-features = ["resolver"]
|
|
|
|
|
|
|
|
[package]
|
|
|
|
name = "foo"
|
|
|
|
version = "1.0.0"
|
|
|
|
resolver = "2"
|
|
|
|
|
|
|
|
[target.'cfg(whatever)'.dependencies]
|
|
|
|
common = {version="1.0", features=["f1"]}
|
|
|
|
|
|
|
|
[dependencies]
|
|
|
|
bar = "1.0"
|
|
|
|
|
|
|
|
"#,
|
|
|
|
)
|
|
|
|
.file("src/main.rs", "fn main() {}")
|
|
|
|
.publish();
|
|
|
|
|
|
|
|
cargo_process("install foo")
|
|
|
|
.masquerade_as_nightly_cargo()
|
|
|
|
.run();
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cargo_test]
|
|
|
|
fn package_includes_resolve_behavior() {
|
|
|
|
// `cargo package` will inherit the correct resolve behavior.
|
|
|
|
let p = project()
|
|
|
|
.file(
|
|
|
|
"Cargo.toml",
|
|
|
|
r#"
|
|
|
|
cargo-features = ["resolver"]
|
|
|
|
[workspace]
|
|
|
|
members = ["a"]
|
|
|
|
resolver = "2"
|
|
|
|
"#,
|
|
|
|
)
|
|
|
|
.file(
|
|
|
|
"a/Cargo.toml",
|
|
|
|
r#"
|
|
|
|
[package]
|
|
|
|
name = "a"
|
|
|
|
version = "0.1.0"
|
|
|
|
authors = ["Zzz"]
|
|
|
|
description = "foo"
|
|
|
|
license = "MIT"
|
|
|
|
homepage = "https://example.com/"
|
|
|
|
"#,
|
|
|
|
)
|
|
|
|
.file("a/src/lib.rs", "")
|
|
|
|
.build();
|
|
|
|
|
|
|
|
p.cargo("package")
|
|
|
|
.cwd("a")
|
|
|
|
.masquerade_as_nightly_cargo()
|
|
|
|
.run();
|
|
|
|
|
|
|
|
let rewritten_toml = format!(
|
|
|
|
r#"{}
|
|
|
|
cargo-features = ["resolver"]
|
|
|
|
|
|
|
|
[package]
|
|
|
|
name = "a"
|
|
|
|
version = "0.1.0"
|
|
|
|
authors = ["Zzz"]
|
|
|
|
description = "foo"
|
|
|
|
homepage = "https://example.com/"
|
|
|
|
license = "MIT"
|
|
|
|
resolver = "2"
|
|
|
|
"#,
|
|
|
|
cargo::core::package::MANIFEST_PREAMBLE
|
|
|
|
);
|
|
|
|
|
|
|
|
let f = File::open(&p.root().join("target/package/a-0.1.0.crate")).unwrap();
|
|
|
|
validate_crate_contents(
|
|
|
|
f,
|
|
|
|
"a-0.1.0.crate",
|
|
|
|
&["Cargo.toml", "Cargo.toml.orig", "src/lib.rs"],
|
|
|
|
&[("Cargo.toml", &rewritten_toml)],
|
|
|
|
);
|
|
|
|
}
|
2020-05-22 21:35:07 +00:00
|
|
|
|
|
|
|
#[cargo_test]
|
|
|
|
fn tree_all() {
|
|
|
|
// `cargo tree` with the new feature resolver.
|
|
|
|
Package::new("log", "0.4.8").feature("serde", &[]).publish();
|
|
|
|
let p = project()
|
|
|
|
.file(
|
|
|
|
"Cargo.toml",
|
|
|
|
r#"
|
|
|
|
[package]
|
|
|
|
name = "foo"
|
|
|
|
version = "0.1.0"
|
|
|
|
|
|
|
|
[target.'cfg(whatever)'.dependencies]
|
|
|
|
log = {version="*", features=["serde"]}
|
|
|
|
"#,
|
|
|
|
)
|
|
|
|
.file("src/lib.rs", "")
|
|
|
|
.build();
|
|
|
|
p.cargo("tree --target=all -Zfeatures=all")
|
|
|
|
.masquerade_as_nightly_cargo()
|
|
|
|
.with_stdout(
|
|
|
|
"\
|
|
|
|
foo v0.1.0 ([..]/foo)
|
|
|
|
└── log v0.4.8
|
|
|
|
",
|
|
|
|
)
|
|
|
|
.run();
|
|
|
|
}
|
2020-09-12 20:43:04 +00:00
|
|
|
|
|
|
|
#[cargo_test]
|
|
|
|
fn shared_dep_same_but_dependencies() {
|
|
|
|
// Checks for a bug of nondeterminism. This scenario creates a shared
|
|
|
|
// dependency `dep` which needs to be built twice (once as normal, and
|
|
|
|
// once as a build dep). However, in both cases the flags to `dep` are the
|
|
|
|
// same, the only difference is what it links to. The normal dependency
|
|
|
|
// should link to `subdep` with the feature disabled, and the build
|
|
|
|
// dependency should link to it with it enabled. Crucially, the `--target`
|
|
|
|
// flag should not be specified, otherwise Unit.kind would be different
|
|
|
|
// and avoid the collision, and this bug won't manifest.
|
|
|
|
let p = project()
|
|
|
|
.file(
|
|
|
|
"Cargo.toml",
|
|
|
|
r#"
|
|
|
|
[workspace]
|
|
|
|
members = ["bin1", "bin2"]
|
|
|
|
"#,
|
|
|
|
)
|
|
|
|
.file(
|
|
|
|
"bin1/Cargo.toml",
|
|
|
|
r#"
|
|
|
|
[package]
|
|
|
|
name = "bin1"
|
|
|
|
version = "0.1.0"
|
|
|
|
|
|
|
|
[dependencies]
|
|
|
|
dep = { path = "../dep" }
|
|
|
|
"#,
|
|
|
|
)
|
|
|
|
.file("bin1/src/main.rs", "fn main() { dep::feat_func(); }")
|
|
|
|
.file(
|
|
|
|
"bin2/Cargo.toml",
|
|
|
|
r#"
|
|
|
|
[package]
|
|
|
|
name = "bin2"
|
|
|
|
version = "0.1.0"
|
|
|
|
|
|
|
|
[build-dependencies]
|
|
|
|
dep = { path = "../dep" }
|
|
|
|
subdep = { path = "../subdep", features = ["feat"] }
|
|
|
|
"#,
|
|
|
|
)
|
|
|
|
.file("bin2/build.rs", "fn main() { dep::feat_func(); }")
|
|
|
|
.file("bin2/src/main.rs", "fn main() {}")
|
|
|
|
.file(
|
|
|
|
"dep/Cargo.toml",
|
|
|
|
r#"
|
|
|
|
[package]
|
|
|
|
name = "dep"
|
|
|
|
version = "0.1.0"
|
|
|
|
|
|
|
|
[dependencies]
|
|
|
|
subdep = { path = "../subdep" }
|
|
|
|
"#,
|
|
|
|
)
|
|
|
|
.file(
|
|
|
|
"dep/src/lib.rs",
|
|
|
|
"pub fn feat_func() { subdep::feat_func(); }",
|
|
|
|
)
|
|
|
|
.file(
|
|
|
|
"subdep/Cargo.toml",
|
|
|
|
r#"
|
|
|
|
[package]
|
|
|
|
name = "subdep"
|
|
|
|
version = "0.1.0"
|
|
|
|
|
|
|
|
[features]
|
|
|
|
feat = []
|
|
|
|
"#,
|
|
|
|
)
|
|
|
|
.file(
|
|
|
|
"subdep/src/lib.rs",
|
|
|
|
r#"
|
|
|
|
pub fn feat_func() {
|
|
|
|
#[cfg(feature = "feat")] println!("cargo:warning=feat: enabled");
|
|
|
|
#[cfg(not(feature = "feat"))] println!("cargo:warning=feat: not enabled");
|
|
|
|
}
|
|
|
|
"#,
|
|
|
|
)
|
|
|
|
.build();
|
|
|
|
|
|
|
|
p.cargo("build --bin bin1 --bin bin2 -Zfeatures=all")
|
|
|
|
.masquerade_as_nightly_cargo()
|
|
|
|
// unordered because bin1 and bin2 build at the same time
|
|
|
|
.with_stderr_unordered(
|
|
|
|
"\
|
|
|
|
[COMPILING] subdep [..]
|
|
|
|
[COMPILING] dep [..]
|
|
|
|
[COMPILING] bin2 [..]
|
|
|
|
[COMPILING] bin1 [..]
|
|
|
|
warning: feat: enabled
|
|
|
|
[FINISHED] [..]
|
|
|
|
",
|
|
|
|
)
|
|
|
|
.run();
|
|
|
|
p.process(p.bin("bin1"))
|
|
|
|
.with_stdout("cargo:warning=feat: not enabled")
|
|
|
|
.run();
|
|
|
|
|
|
|
|
// Make sure everything stays cached.
|
|
|
|
p.cargo("build -v --bin bin1 --bin bin2 -Zfeatures=all")
|
|
|
|
.masquerade_as_nightly_cargo()
|
|
|
|
.with_stderr_unordered(
|
|
|
|
"\
|
|
|
|
[FRESH] subdep [..]
|
|
|
|
[FRESH] dep [..]
|
|
|
|
[FRESH] bin1 [..]
|
|
|
|
warning: feat: enabled
|
|
|
|
[FRESH] bin2 [..]
|
|
|
|
[FINISHED] [..]
|
|
|
|
",
|
|
|
|
)
|
|
|
|
.run();
|
|
|
|
}
|
2020-09-28 23:21:55 +00:00
|
|
|
|
|
|
|
#[cargo_test]
|
|
|
|
fn test_proc_macro() {
|
|
|
|
// Running `cargo test` on a proc-macro, with a shared dependency that has
|
|
|
|
// different features.
|
|
|
|
//
|
|
|
|
// There was a bug where `shared` was built twice (once with feature "B"
|
|
|
|
// and once without), and both copies linked into the unit test. This
|
|
|
|
// would cause a type failure when used in an intermediate dependency
|
|
|
|
// (the-macro-support).
|
|
|
|
let p = project()
|
|
|
|
.file(
|
|
|
|
"Cargo.toml",
|
|
|
|
r#"
|
|
|
|
[package]
|
|
|
|
name = "runtime"
|
|
|
|
version = "0.1.0"
|
|
|
|
[dependencies]
|
|
|
|
the-macro = { path = "the-macro", features = ['a'] }
|
|
|
|
[build-dependencies]
|
|
|
|
shared = { path = "shared", features = ['b'] }
|
|
|
|
"#,
|
|
|
|
)
|
|
|
|
.file("src/lib.rs", "")
|
|
|
|
.file(
|
|
|
|
"the-macro/Cargo.toml",
|
|
|
|
r#"
|
|
|
|
[package]
|
|
|
|
name = "the-macro"
|
|
|
|
version = "0.1.0"
|
|
|
|
[lib]
|
|
|
|
proc-macro = true
|
|
|
|
test = false
|
|
|
|
[dependencies]
|
|
|
|
the-macro-support = { path = "../the-macro-support" }
|
|
|
|
shared = { path = "../shared" }
|
|
|
|
[dev-dependencies]
|
|
|
|
runtime = { path = ".." }
|
|
|
|
[features]
|
|
|
|
a = []
|
|
|
|
"#,
|
|
|
|
)
|
|
|
|
.file(
|
|
|
|
"the-macro/src/lib.rs",
|
|
|
|
"
|
|
|
|
fn _test() {
|
|
|
|
the_macro_support::foo(shared::Foo);
|
|
|
|
}
|
|
|
|
",
|
|
|
|
)
|
|
|
|
.file(
|
|
|
|
"the-macro-support/Cargo.toml",
|
|
|
|
r#"
|
|
|
|
[package]
|
|
|
|
name = "the-macro-support"
|
|
|
|
version = "0.1.0"
|
|
|
|
[dependencies]
|
|
|
|
shared = { path = "../shared" }
|
|
|
|
"#,
|
|
|
|
)
|
|
|
|
.file(
|
|
|
|
"the-macro-support/src/lib.rs",
|
|
|
|
"
|
|
|
|
pub fn foo(_: shared::Foo) {}
|
|
|
|
",
|
|
|
|
)
|
|
|
|
.file(
|
|
|
|
"shared/Cargo.toml",
|
|
|
|
r#"
|
|
|
|
[package]
|
|
|
|
name = "shared"
|
|
|
|
version = "0.1.0"
|
|
|
|
[features]
|
|
|
|
b = []
|
|
|
|
"#,
|
|
|
|
)
|
|
|
|
.file("shared/src/lib.rs", "pub struct Foo;")
|
|
|
|
.build();
|
|
|
|
p.cargo("test -Zfeatures=all --manifest-path the-macro/Cargo.toml")
|
|
|
|
.masquerade_as_nightly_cargo()
|
|
|
|
.run();
|
|
|
|
}
|
2020-10-13 22:39:46 +00:00
|
|
|
|
|
|
|
#[cargo_test]
|
|
|
|
fn doc_optional() {
|
|
|
|
// Checks for a bug where `cargo doc` was failing with an inactive target
|
|
|
|
// that enables a shared optional dependency.
|
|
|
|
Package::new("spin", "1.0.0").publish();
|
|
|
|
Package::new("bar", "1.0.0")
|
|
|
|
.add_dep(Dependency::new("spin", "1.0").optional(true))
|
|
|
|
.publish();
|
|
|
|
// The enabler package enables the `spin` feature, which we don't want.
|
|
|
|
Package::new("enabler", "1.0.0")
|
|
|
|
.feature_dep("bar", "1.0", &["spin"])
|
|
|
|
.publish();
|
|
|
|
let p = project()
|
|
|
|
.file(
|
|
|
|
"Cargo.toml",
|
|
|
|
r#"
|
|
|
|
[package]
|
|
|
|
name = "foo"
|
|
|
|
version = "0.1.0"
|
|
|
|
|
|
|
|
[target.'cfg(whatever)'.dependencies]
|
|
|
|
enabler = "1.0"
|
|
|
|
|
|
|
|
[dependencies]
|
|
|
|
bar = "1.0"
|
|
|
|
"#,
|
|
|
|
)
|
|
|
|
.file("src/lib.rs", "")
|
|
|
|
.build();
|
|
|
|
|
|
|
|
p.cargo("doc -Zfeatures=itarget")
|
|
|
|
.masquerade_as_nightly_cargo()
|
|
|
|
.with_stderr_unordered(
|
|
|
|
"\
|
|
|
|
[UPDATING] [..]
|
|
|
|
[DOWNLOADING] crates ...
|
|
|
|
[DOWNLOADED] spin v1.0.0 [..]
|
|
|
|
[DOWNLOADED] bar v1.0.0 [..]
|
|
|
|
[DOWNLOADING] crates ...
|
|
|
|
[DOWNLOADED] enabler v1.0.0 [..]
|
|
|
|
[DOCUMENTING] bar v1.0.0
|
|
|
|
[CHECKING] bar v1.0.0
|
|
|
|
[DOCUMENTING] foo v0.1.0 [..]
|
|
|
|
[FINISHED] [..]
|
|
|
|
",
|
|
|
|
)
|
|
|
|
.run();
|
|
|
|
}
|