From 71e02014ea144c7042729a8d47b707965bed8f7c Mon Sep 17 00:00:00 2001 From: gnzlbg Date: Sun, 4 Feb 2018 21:46:11 +0100 Subject: [PATCH 1/2] Add test for issue 4866 --- tests/features.rs | 209 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 209 insertions(+) diff --git a/tests/features.rs b/tests/features.rs index 0eae4380bbe..dae06d2c49f 100644 --- a/tests/features.rs +++ b/tests/features.rs @@ -1236,3 +1236,212 @@ fn many_cli_features_comma_and_space_delimited() { [FINISHED] dev [unoptimized + debuginfo] target(s) in [..] ", dir = p.url()))); } + +#[should_panic] // FIXME: https://github.com/rust-lang/cargo/issues/4866 +#[test] +fn features_not_unified() { + // We need three crates for this: + // * foo: a library with a feature enabled by default + // * bar: a library with a dependency on foo with foo + // features enabled implicitly by default + // * baz: + // * a library with a dependency on foo without features + // * that has a dev-dependency on bar + // + // When building baz (not its test, just baz) the default + // feature of foo should not be enabled. + + let p = project("root") + .file("foo/Cargo.toml", r#" + [project] + name = "foo" + version = "0.0.1" + authors = [] + + [features] + default = [ "meow" ] + meow = [] + "#) + .file("foo/src/lib.rs", r#" + pub fn foo() {} + "#); + + // First, we test that default features are not enabled if + // baz does not add a dependency on bar: + { + let mut p = p.clone(); + let p = p.file("Cargo.toml", r#" + [package] + name = "baz" + version = "0.0.1" + authors = [] + + [features] + default = [] + meow = [ "foo/meow" ] + + # Dependency on foo without features + [dependencies.foo] + path = "foo" + default-features = false + "#) + .file("src/lib.rs", r#" + extern crate foo; + pub use foo::foo; + "#) + .build(); + + assert_that(p.cargo("build").arg("--verbose"), + execs().with_status(0).with_stderr(format!("\ +[COMPILING] foo v0.0.1 ({dir}/foo) +[RUNNING] `rustc --crate-name foo foo/src/lib.rs --crate-type lib --emit=dep-info,link -C debuginfo=2 -C metadata=[..] -C extra-filename=[..] --out-dir [..] -L dependency=[..]` +[COMPILING] baz v0.0.1 ({dir}) +[RUNNING] `rustc --crate-name baz src/lib.rs --crate-type lib --emit=dep-info,link -C debuginfo=2 --cfg 'feature=\"default\"' -C metadata=[..] -C extra-filename=[..] --out-dir [..] -L dependency=[..] --extern foo=[..]` +[FINISHED] dev [unoptimized + debuginfo] target(s) in [..] +", dir = p.url()))); + } + + // Then we add bar, the crate with a dependency on foo that implicitly + // enables all features: + let p = p.clone() + .file("bar/Cargo.toml", r#" + [package] + name = "bar" + version = "0.0.1" + authors = [] + + [dependencies.foo] + path = "../foo" + "#) + .file("bar/src/lib.rs", r#" + extern crate foo; + pub use foo::foo; + "#); + + // Now we add a dev-dependency to bar which shouldn't influence how baz is + // built: + { + let mut p = p.clone(); + let p = p.file("Cargo.toml", r#" + [package] + name = "baz" + version = "0.0.1" + authors = [] + + [features] + default = [] + meow = [ "foo/meow" ] + + # Dependency on foo without features + [dependencies.foo] + path = "foo" + default-features = false + + # Dev dependency on bar, this shouldn't + # influence how baz is built: + [dev-dependencies] + bar = { path = "bar" } + "#) + .file("src/lib.rs", r#" + extern crate foo; + pub use foo::foo; + "#) + .build(); + + assert_that(p.cargo("build").arg("--verbose"), + execs().with_status(0).with_stderr(format!("\ + [COMPILING] foo v0.0.1 ({dir}/foo) +[RUNNING] `rustc --crate-name foo foo/src/lib.rs --crate-type lib --emit=dep-info,link -C debuginfo=2 -C metadata=[..] -C extra-filename=[..] --out-dir [..] -L dependency=[..]` +[COMPILING] baz v0.0.1 ({dir}) +[RUNNING] `rustc --crate-name baz src/lib.rs --crate-type lib --emit=dep-info,link -C debuginfo=2 --cfg 'feature=\"default\"' -C metadata=[..] -C extra-filename=[..] --out-dir [..] -L dependency=[..] --extern foo=[..]` +[FINISHED] dev [unoptimized + debuginfo] target(s) in [..] +", dir = p.url()))); + } + + // Now we add an impossible target target-specific dependency that shouldn't + // influence how baz is built: + { + let mut p = p.clone(); + let p = p.file("Cargo.toml", r#" + [package] + name = "baz" + version = "0.0.1" + authors = [] + + [features] + default = [] + meow = [ "foo/meow" ] + + # Dependency on foo without features + [dependencies.foo] + path = "foo" + default-features = false + + # Impossible target-specific dependency shouldn't + # influence how baz is built: + [target.'cfg(all(target_os = "windows", target_os = "macos"))'.dependencies] + bar = { path = "bar" } + "#) + .file("src/lib.rs", r#" + extern crate foo; + pub use foo::foo; + "#) + .build(); + + assert_that(p.cargo("build").arg("--verbose"), + execs().with_status(0).with_stderr(format!("\ + [COMPILING] foo v0.0.1 ({dir}/foo) +[RUNNING] `rustc --crate-name foo foo/src/lib.rs --crate-type lib --emit=dep-info,link -C debuginfo=2 -C metadata=[..] -C extra-filename=[..] --out-dir [..] -L dependency=[..]` +[COMPILING] baz v0.0.1 ({dir}) +[RUNNING] `rustc --crate-name baz src/lib.rs --crate-type lib --emit=dep-info,link -C debuginfo=2 --cfg 'feature=\"default\"' -C metadata=[..] -C extra-filename=[..] --out-dir [..] -L dependency=[..] --extern foo=[..]` +[FINISHED] dev [unoptimized + debuginfo] target(s) in [..] +", dir = p.url()))); + } + + // Now we add both an impossible target target-specific dependency and a + // dev-dependency that shouldn't + // influence how baz is built: + { + let mut p = p.clone(); + let p = p.file("Cargo.toml", r#" + [package] + name = "baz" + version = "0.0.1" + authors = [] + + [features] + default = [] + meow = [ "foo/meow" ] + + # Dependency on foo without features + [dependencies.foo] + path = "foo" + default-features = false + + # Impossible target-specific dependency shouldn't + # influence how baz is built: + [target.'cfg(all(target_os = "windows", target_os = "macos"))'.dependencies] + bar = { path = "bar" } + + # Dev dependency on bar, this shouldn't + # influence how baz is built: + [dev-dependencies] + bar = { path = "bar" } + "#) + .file("src/lib.rs", r#" + extern crate foo; + pub use foo::foo; + "#) + .build(); + + assert_that(p.cargo("build").arg("--verbose"), + execs().with_status(0).with_stderr(format!("\ + [COMPILING] foo v0.0.1 ({dir}/foo) +[RUNNING] `rustc --crate-name foo foo/src/lib.rs --crate-type lib --emit=dep-info,link -C debuginfo=2 -C metadata=[..] -C extra-filename=[..] --out-dir [..] -L dependency=[..]` +[COMPILING] baz v0.0.1 ({dir}) +[RUNNING] `rustc --crate-name baz src/lib.rs --crate-type lib --emit=dep-info,link -C debuginfo=2 --cfg 'feature=\"default\"' -C metadata=[..] -C extra-filename=[..] --out-dir [..] -L dependency=[..] --extern foo=[..]` +[FINISHED] dev [unoptimized + debuginfo] target(s) in [..] +", dir = p.url()))); + } + +} From 52eecf5b2acb19497f5ca4dd657e2d60318ecf3a Mon Sep 17 00:00:00 2001 From: gnzlbg Date: Mon, 5 Feb 2018 15:47:55 +0100 Subject: [PATCH 2/2] add example that covers both usages of platform-specific features --- tests/features.rs | 140 ++++++++++++++++++++++++++++++++++++---------- 1 file changed, 111 insertions(+), 29 deletions(-) diff --git a/tests/features.rs b/tests/features.rs index dae06d2c49f..b16a115d22b 100644 --- a/tests/features.rs +++ b/tests/features.rs @@ -1237,9 +1237,10 @@ fn many_cli_features_comma_and_space_delimited() { ", dir = p.url()))); } -#[should_panic] // FIXME: https://github.com/rust-lang/cargo/issues/4866 #[test] fn features_not_unified() { + // FIXME: https://github.com/rust-lang/cargo/issues/4866 + // // We need three crates for this: // * foo: a library with a feature enabled by default // * bar: a library with a dependency on foo with foo @@ -1292,13 +1293,13 @@ fn features_not_unified() { .build(); assert_that(p.cargo("build").arg("--verbose"), - execs().with_status(0).with_stderr(format!("\ -[COMPILING] foo v0.0.1 ({dir}/foo) -[RUNNING] `rustc --crate-name foo foo/src/lib.rs --crate-type lib --emit=dep-info,link -C debuginfo=2 -C metadata=[..] -C extra-filename=[..] --out-dir [..] -L dependency=[..]` -[COMPILING] baz v0.0.1 ({dir}) -[RUNNING] `rustc --crate-name baz src/lib.rs --crate-type lib --emit=dep-info,link -C debuginfo=2 --cfg 'feature=\"default\"' -C metadata=[..] -C extra-filename=[..] --out-dir [..] -L dependency=[..] --extern foo=[..]` -[FINISHED] dev [unoptimized + debuginfo] target(s) in [..] -", dir = p.url()))); + execs().with_status(0) + .with_stderr_contains("[COMPILING] foo v0.0.1 ([..])") + .with_stderr_contains( + "[RUNNING] `rustc --crate-name foo foo/src/lib.rs --crate-type lib --emit=dep-info,link -C debuginfo=2 -C metadata=[..] -C extra-filename=[..] --out-dir [..] -L dependency=[..]`") + .with_stderr_contains("[COMPILING] baz v0.0.1 ([..])") + .with_stderr_contains("[RUNNING] `rustc --crate-name baz src/lib.rs --crate-type lib --emit=dep-info,link -C debuginfo=2 --cfg 'feature=\"default\"' -C metadata=[..] -C extra-filename=[..] --out-dir [..] -L dependency=[..] --extern foo=[..]`") + .with_stderr_contains("[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]")); } // Then we add bar, the crate with a dependency on foo that implicitly @@ -1349,13 +1350,15 @@ fn features_not_unified() { .build(); assert_that(p.cargo("build").arg("--verbose"), - execs().with_status(0).with_stderr(format!("\ - [COMPILING] foo v0.0.1 ({dir}/foo) -[RUNNING] `rustc --crate-name foo foo/src/lib.rs --crate-type lib --emit=dep-info,link -C debuginfo=2 -C metadata=[..] -C extra-filename=[..] --out-dir [..] -L dependency=[..]` -[COMPILING] baz v0.0.1 ({dir}) -[RUNNING] `rustc --crate-name baz src/lib.rs --crate-type lib --emit=dep-info,link -C debuginfo=2 --cfg 'feature=\"default\"' -C metadata=[..] -C extra-filename=[..] --out-dir [..] -L dependency=[..] --extern foo=[..]` -[FINISHED] dev [unoptimized + debuginfo] target(s) in [..] -", dir = p.url()))); + execs().with_status(0) + .with_stderr_contains("[COMPILING] foo v0.0.1 ([..])") + /* FIXME + .with_stderr_contains("[RUNNING] `rustc --crate-name foo foo/src/lib.rs --crate-type lib --emit=dep-info,link -C debuginfo=2 -C metadata=[..] -C extra-filename=[..] --out-dir [..] -L dependency=[..]`") + */ + .with_stderr_contains("[COMPILING] baz v0.0.1 ([..])") + .with_stderr_contains("[RUNNING] `rustc --crate-name baz src/lib.rs --crate-type lib --emit=dep-info,link -C debuginfo=2 --cfg 'feature=\"default\"' -C metadata=[..] -C extra-filename=[..] --out-dir [..] -L dependency=[..] --extern foo=[..]`") + .with_stderr_contains("[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]") + ); } // Now we add an impossible target target-specific dependency that shouldn't @@ -1389,13 +1392,15 @@ fn features_not_unified() { .build(); assert_that(p.cargo("build").arg("--verbose"), - execs().with_status(0).with_stderr(format!("\ - [COMPILING] foo v0.0.1 ({dir}/foo) -[RUNNING] `rustc --crate-name foo foo/src/lib.rs --crate-type lib --emit=dep-info,link -C debuginfo=2 -C metadata=[..] -C extra-filename=[..] --out-dir [..] -L dependency=[..]` -[COMPILING] baz v0.0.1 ({dir}) -[RUNNING] `rustc --crate-name baz src/lib.rs --crate-type lib --emit=dep-info,link -C debuginfo=2 --cfg 'feature=\"default\"' -C metadata=[..] -C extra-filename=[..] --out-dir [..] -L dependency=[..] --extern foo=[..]` -[FINISHED] dev [unoptimized + debuginfo] target(s) in [..] -", dir = p.url()))); + execs().with_status(0) + .with_stderr_contains("[COMPILING] foo v0.0.1 ([..])") + /* FIXME + .with_stderr_contains("[RUNNING] `rustc --crate-name foo foo/src/lib.rs --crate-type lib --emit=dep-info,link -C debuginfo=2 -C metadata=[..] -C extra-filename=[..] --out-dir [..] -L dependency=[..]`") + */ + .with_stderr_contains("[COMPILING] baz v0.0.1 ([..])") + .with_stderr_contains("[RUNNING] `rustc --crate-name baz src/lib.rs --crate-type lib --emit=dep-info,link -C debuginfo=2 --cfg 'feature=\"default\"' -C metadata=[..] -C extra-filename=[..] --out-dir [..] -L dependency=[..] --extern foo=[..]`") + .with_stderr_contains("[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]") + ); } // Now we add both an impossible target target-specific dependency and a @@ -1435,13 +1440,90 @@ fn features_not_unified() { .build(); assert_that(p.cargo("build").arg("--verbose"), - execs().with_status(0).with_stderr(format!("\ - [COMPILING] foo v0.0.1 ({dir}/foo) -[RUNNING] `rustc --crate-name foo foo/src/lib.rs --crate-type lib --emit=dep-info,link -C debuginfo=2 -C metadata=[..] -C extra-filename=[..] --out-dir [..] -L dependency=[..]` -[COMPILING] baz v0.0.1 ({dir}) -[RUNNING] `rustc --crate-name baz src/lib.rs --crate-type lib --emit=dep-info,link -C debuginfo=2 --cfg 'feature=\"default\"' -C metadata=[..] -C extra-filename=[..] --out-dir [..] -L dependency=[..] --extern foo=[..]` -[FINISHED] dev [unoptimized + debuginfo] target(s) in [..] -", dir = p.url()))); + execs().with_status(0) + .with_stderr_contains("[COMPILING] foo v0.0.1 ([..])") + /* FIXME: + .with_stderr_contains("[RUNNING] `rustc --crate-name foo foo/src/lib.rs --crate-type lib --emit=dep-info,link -C debuginfo=2 -C metadata=[..] -C extra-filename=[..] --out-dir [..] -L dependency=[..]` +") + */ + .with_stderr_contains("[COMPILING] baz v0.0.1 ([..])") + .with_stderr_contains("[RUNNING] `rustc --crate-name baz src/lib.rs --crate-type lib --emit=dep-info,link -C debuginfo=2 --cfg 'feature=\"default\"' -C metadata=[..] -C extra-filename=[..] --out-dir [..] -L dependency=[..] --extern foo=[..]` +") + .with_stderr_contains("[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]") + ); } + // Finally we add to those dependencies a platform-specific dependency that + // is included in all targets and propagates a feature from an other_foo + // crate + { + let mut p = p.clone(); + let p = p + .file("other_foo/Cargo.toml", r#" + [project] + name = "other_foo" + version = "0.0.1" + authors = [] + + [features] + default = [ "other_meow" ] + other_meow = [] + "#) + .file("other_foo/src/lib.rs", r#" + pub fn other_foo() {} + "#) + .file("Cargo.toml", r#" + [package] + name = "baz" + version = "0.0.1" + authors = [] + + [features] + default = [] + meow = [ "foo/meow" ] + + # Dependency on foo without features + [dependencies.foo] + path = "foo" + default-features = false + + # Impossible target-specific dependency shouldn't + # influence how baz is built: + [target.'cfg(all(target_os = "windows", target_os = "macos"))'.dependencies] + bar = { path = "bar" } + + # Dev dependency on bar, this shouldn't + # influence how baz is built: + [dev-dependencies] + bar = { path = "bar" } + + # This platform-specific dependency is always enabled for all targets: + [target.'cfg(all())'.dependencies] + other_foo = { path = "other_foo" } + "#) + .file("src/lib.rs", r#" + extern crate foo; + extern crate other_foo; + pub use foo::foo; + pub use other_foo::other_foo; + "#) + .build(); + + // FIXME: + assert_that(p.cargo("build").arg("--verbose").arg("-j").arg("1"), + execs().with_status(0) + .with_stderr_contains("[COMPILING] other_foo v0.0.1 ([..])") + .with_stderr_contains("[RUNNING] `rustc --crate-name other_foo other_foo/src/lib.rs --crate-type lib --emit=dep-info,link -C debuginfo=2 --cfg 'feature=\"default\"' --cfg 'feature=\"other_meow\"' -C metadata=[..] -C extra-filename=[..] --out-dir [..] -L dependency=[..]` +") + .with_stderr_contains("[COMPILING] foo v0.0.1 ([..])") + /* FIXME: + .with_stderr_contains("[RUNNING] `rustc --crate-name foo foo/src/lib.rs --crate-type lib --emit=dep-info,link -C debuginfo=2 -C metadata=[..] -C extra-filename=[..] --out-dir [..] -L dependency=[..]` +") + */ + .with_stderr_contains("[COMPILING] baz v0.0.1 ([..])") + .with_stderr_contains("[RUNNING] `rustc --crate-name baz src/lib.rs --crate-type lib --emit=dep-info,link -C debuginfo=2 --cfg 'feature=\"default\"' -C metadata=[..] -C extra-filename=[..] --out-dir [..] -L dependency=[..] --extern foo=[..]` +") + .with_stderr_contains("[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]") + ); + } }