cargo/tests/testsuite/freshness.rs

1255 lines
29 KiB
Rust
Raw Normal View History

use std::fs::{self, File};
use std::io::prelude::*;
2018-12-06 19:17:36 +00:00
use crate::support::paths::CargoPathExt;
use crate::support::registry::Package;
use crate::support::sleep_ms;
use crate::support::{basic_manifest, project};
#[test]
fn modifying_and_moving() {
let p = project()
.file("src/main.rs", "mod a; fn main() {}")
.file("src/a.rs", "")
.build();
p.cargo("build")
.with_stderr(
2018-03-14 15:17:44 +00:00
"\
[COMPILING] foo v0.0.1 ([CWD])
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
2018-03-14 15:17:44 +00:00
",
2018-12-08 11:19:47 +00:00
)
.run();
p.cargo("build").with_stdout("").run();
p.root().move_into_the_past();
p.root().join("target").move_into_the_past();
2018-03-14 15:17:44 +00:00
File::create(&p.root().join("src/a.rs"))
.unwrap()
.write_all(b"#[allow(unused)]fn main() {}")
.unwrap();
p.cargo("build")
.with_stderr(
2018-03-14 15:17:44 +00:00
"\
[COMPILING] foo v0.0.1 ([CWD])
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
2018-03-14 15:17:44 +00:00
",
2018-12-08 11:19:47 +00:00
)
.run();
fs::rename(&p.root().join("src/a.rs"), &p.root().join("src/b.rs")).unwrap();
p.cargo("build")
.with_status(101)
.with_stderr_contains("[..]file not found[..]")
.run();
}
#[test]
fn modify_only_some_files() {
let p = project()
.file("src/lib.rs", "mod a;")
.file("src/a.rs", "")
.file("src/main.rs", "mod b; fn main() {}")
.file("src/b.rs", "")
.file("tests/test.rs", "")
.build();
p.cargo("build")
.with_stderr(
2018-03-14 15:17:44 +00:00
"\
[COMPILING] foo v0.0.1 ([CWD])
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
2018-03-14 15:17:44 +00:00
",
2018-12-08 11:19:47 +00:00
)
.run();
p.cargo("test").run();
sleep_ms(1000);
2018-08-29 06:11:10 +00:00
assert!(p.bin("foo").is_file());
let lib = p.root().join("src/lib.rs");
let bin = p.root().join("src/b.rs");
2018-03-14 15:17:44 +00:00
File::create(&lib)
.unwrap()
.write_all(b"invalid rust code")
.unwrap();
File::create(&bin)
.unwrap()
.write_all(b"#[allow(unused)]fn foo() {}")
.unwrap();
lib.move_into_the_past();
// Make sure the binary is rebuilt, not the lib
p.cargo("build")
.with_stderr(
2018-03-14 15:17:44 +00:00
"\
[COMPILING] foo v0.0.1 ([CWD])
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
2018-03-14 15:17:44 +00:00
",
2018-12-08 11:19:47 +00:00
)
.run();
2018-08-29 06:11:10 +00:00
assert!(p.bin("foo").is_file());
}
Consider transitive fingerprints for freshness Originally discovered through #1236, this commit fixes a bug in Cargo where crates may not be recompiled when they need to (leading to obscure errors from the compiler). The scenario in question looks like: * Assume a dependency graph of `A -> B -> C` and `A -> C` * Build all packages * Modify C * Rebuild, but hit Ctrl+C while B is building * Modify A * Rebuild again Previously, Cargo only considered the freshness of a package to be the freshness of the package itself (checking source files, for example). To handle transitive recompilations, Cargo propagates a dirty bit throughout the dependency graph automatically (instead if calculating it as such). In the above example, however, we have a problem where as part of the last rebuild Cargo thinks `B` and `C` are fresh! The artifact for `C` was just recompiled, but `B`'s source code is untainted, so Cargo does not think that it needs to recompile `B`. This is wrong, however, because one of `B`'s dependencies was rebuilt, so it needs to be rebuilt. To fix this problem, the fingerprint (a short hash) for all packages is now transitively propagated (the fingerprint changes when an upstream package changes). This should ensure that even when Ctrl+C is hit (or the situation explained in #1236) that Cargo will still consider packages whose source code is untainted as candidates for recompilation. The implementation is somewhat tricky due to the actual fingerprint for a path dependency not being known until *after* the crate is compiled (the fingerprint is the mtime of the dep-info file). Closes #1236
2015-01-29 03:37:19 +00:00
#[test]
fn rebuild_sub_package_then_while_package() {
let p = project()
2018-03-14 15:17:44 +00:00
.file(
"Cargo.toml",
r#"
Consider transitive fingerprints for freshness Originally discovered through #1236, this commit fixes a bug in Cargo where crates may not be recompiled when they need to (leading to obscure errors from the compiler). The scenario in question looks like: * Assume a dependency graph of `A -> B -> C` and `A -> C` * Build all packages * Modify C * Rebuild, but hit Ctrl+C while B is building * Modify A * Rebuild again Previously, Cargo only considered the freshness of a package to be the freshness of the package itself (checking source files, for example). To handle transitive recompilations, Cargo propagates a dirty bit throughout the dependency graph automatically (instead if calculating it as such). In the above example, however, we have a problem where as part of the last rebuild Cargo thinks `B` and `C` are fresh! The artifact for `C` was just recompiled, but `B`'s source code is untainted, so Cargo does not think that it needs to recompile `B`. This is wrong, however, because one of `B`'s dependencies was rebuilt, so it needs to be rebuilt. To fix this problem, the fingerprint (a short hash) for all packages is now transitively propagated (the fingerprint changes when an upstream package changes). This should ensure that even when Ctrl+C is hit (or the situation explained in #1236) that Cargo will still consider packages whose source code is untainted as candidates for recompilation. The implementation is somewhat tricky due to the actual fingerprint for a path dependency not being known until *after* the crate is compiled (the fingerprint is the mtime of the dep-info file). Closes #1236
2015-01-29 03:37:19 +00:00
[package]
name = "foo"
authors = []
version = "0.0.1"
[dependencies.a]
path = "a"
[dependencies.b]
path = "b"
2018-03-14 15:17:44 +00:00
"#,
2018-12-08 11:19:47 +00:00
)
.file("src/lib.rs", "extern crate a; extern crate b;")
2018-03-14 15:17:44 +00:00
.file(
"a/Cargo.toml",
r#"
Consider transitive fingerprints for freshness Originally discovered through #1236, this commit fixes a bug in Cargo where crates may not be recompiled when they need to (leading to obscure errors from the compiler). The scenario in question looks like: * Assume a dependency graph of `A -> B -> C` and `A -> C` * Build all packages * Modify C * Rebuild, but hit Ctrl+C while B is building * Modify A * Rebuild again Previously, Cargo only considered the freshness of a package to be the freshness of the package itself (checking source files, for example). To handle transitive recompilations, Cargo propagates a dirty bit throughout the dependency graph automatically (instead if calculating it as such). In the above example, however, we have a problem where as part of the last rebuild Cargo thinks `B` and `C` are fresh! The artifact for `C` was just recompiled, but `B`'s source code is untainted, so Cargo does not think that it needs to recompile `B`. This is wrong, however, because one of `B`'s dependencies was rebuilt, so it needs to be rebuilt. To fix this problem, the fingerprint (a short hash) for all packages is now transitively propagated (the fingerprint changes when an upstream package changes). This should ensure that even when Ctrl+C is hit (or the situation explained in #1236) that Cargo will still consider packages whose source code is untainted as candidates for recompilation. The implementation is somewhat tricky due to the actual fingerprint for a path dependency not being known until *after* the crate is compiled (the fingerprint is the mtime of the dep-info file). Closes #1236
2015-01-29 03:37:19 +00:00
[package]
name = "a"
authors = []
version = "0.0.1"
[dependencies.b]
path = "../b"
2018-03-14 15:17:44 +00:00
"#,
2018-12-08 11:19:47 +00:00
)
.file("a/src/lib.rs", "extern crate b;")
2018-07-24 22:35:01 +00:00
.file("b/Cargo.toml", &basic_manifest("b", "0.0.1"))
.file("b/src/lib.rs", "")
.build();
Consider transitive fingerprints for freshness Originally discovered through #1236, this commit fixes a bug in Cargo where crates may not be recompiled when they need to (leading to obscure errors from the compiler). The scenario in question looks like: * Assume a dependency graph of `A -> B -> C` and `A -> C` * Build all packages * Modify C * Rebuild, but hit Ctrl+C while B is building * Modify A * Rebuild again Previously, Cargo only considered the freshness of a package to be the freshness of the package itself (checking source files, for example). To handle transitive recompilations, Cargo propagates a dirty bit throughout the dependency graph automatically (instead if calculating it as such). In the above example, however, we have a problem where as part of the last rebuild Cargo thinks `B` and `C` are fresh! The artifact for `C` was just recompiled, but `B`'s source code is untainted, so Cargo does not think that it needs to recompile `B`. This is wrong, however, because one of `B`'s dependencies was rebuilt, so it needs to be rebuilt. To fix this problem, the fingerprint (a short hash) for all packages is now transitively propagated (the fingerprint changes when an upstream package changes). This should ensure that even when Ctrl+C is hit (or the situation explained in #1236) that Cargo will still consider packages whose source code is untainted as candidates for recompilation. The implementation is somewhat tricky due to the actual fingerprint for a path dependency not being known until *after* the crate is compiled (the fingerprint is the mtime of the dep-info file). Closes #1236
2015-01-29 03:37:19 +00:00
p.cargo("build").run();
Consider transitive fingerprints for freshness Originally discovered through #1236, this commit fixes a bug in Cargo where crates may not be recompiled when they need to (leading to obscure errors from the compiler). The scenario in question looks like: * Assume a dependency graph of `A -> B -> C` and `A -> C` * Build all packages * Modify C * Rebuild, but hit Ctrl+C while B is building * Modify A * Rebuild again Previously, Cargo only considered the freshness of a package to be the freshness of the package itself (checking source files, for example). To handle transitive recompilations, Cargo propagates a dirty bit throughout the dependency graph automatically (instead if calculating it as such). In the above example, however, we have a problem where as part of the last rebuild Cargo thinks `B` and `C` are fresh! The artifact for `C` was just recompiled, but `B`'s source code is untainted, so Cargo does not think that it needs to recompile `B`. This is wrong, however, because one of `B`'s dependencies was rebuilt, so it needs to be rebuilt. To fix this problem, the fingerprint (a short hash) for all packages is now transitively propagated (the fingerprint changes when an upstream package changes). This should ensure that even when Ctrl+C is hit (or the situation explained in #1236) that Cargo will still consider packages whose source code is untainted as candidates for recompilation. The implementation is somewhat tricky due to the actual fingerprint for a path dependency not being known until *after* the crate is compiled (the fingerprint is the mtime of the dep-info file). Closes #1236
2015-01-29 03:37:19 +00:00
2018-03-14 15:17:44 +00:00
File::create(&p.root().join("b/src/lib.rs"))
.unwrap()
.write_all(br#"pub fn b() {}"#)
2018-03-14 15:17:44 +00:00
.unwrap();
Consider transitive fingerprints for freshness Originally discovered through #1236, this commit fixes a bug in Cargo where crates may not be recompiled when they need to (leading to obscure errors from the compiler). The scenario in question looks like: * Assume a dependency graph of `A -> B -> C` and `A -> C` * Build all packages * Modify C * Rebuild, but hit Ctrl+C while B is building * Modify A * Rebuild again Previously, Cargo only considered the freshness of a package to be the freshness of the package itself (checking source files, for example). To handle transitive recompilations, Cargo propagates a dirty bit throughout the dependency graph automatically (instead if calculating it as such). In the above example, however, we have a problem where as part of the last rebuild Cargo thinks `B` and `C` are fresh! The artifact for `C` was just recompiled, but `B`'s source code is untainted, so Cargo does not think that it needs to recompile `B`. This is wrong, however, because one of `B`'s dependencies was rebuilt, so it needs to be rebuilt. To fix this problem, the fingerprint (a short hash) for all packages is now transitively propagated (the fingerprint changes when an upstream package changes). This should ensure that even when Ctrl+C is hit (or the situation explained in #1236) that Cargo will still consider packages whose source code is untainted as candidates for recompilation. The implementation is somewhat tricky due to the actual fingerprint for a path dependency not being known until *after* the crate is compiled (the fingerprint is the mtime of the dep-info file). Closes #1236
2015-01-29 03:37:19 +00:00
p.cargo("build -pb").run();
Consider transitive fingerprints for freshness Originally discovered through #1236, this commit fixes a bug in Cargo where crates may not be recompiled when they need to (leading to obscure errors from the compiler). The scenario in question looks like: * Assume a dependency graph of `A -> B -> C` and `A -> C` * Build all packages * Modify C * Rebuild, but hit Ctrl+C while B is building * Modify A * Rebuild again Previously, Cargo only considered the freshness of a package to be the freshness of the package itself (checking source files, for example). To handle transitive recompilations, Cargo propagates a dirty bit throughout the dependency graph automatically (instead if calculating it as such). In the above example, however, we have a problem where as part of the last rebuild Cargo thinks `B` and `C` are fresh! The artifact for `C` was just recompiled, but `B`'s source code is untainted, so Cargo does not think that it needs to recompile `B`. This is wrong, however, because one of `B`'s dependencies was rebuilt, so it needs to be rebuilt. To fix this problem, the fingerprint (a short hash) for all packages is now transitively propagated (the fingerprint changes when an upstream package changes). This should ensure that even when Ctrl+C is hit (or the situation explained in #1236) that Cargo will still consider packages whose source code is untainted as candidates for recompilation. The implementation is somewhat tricky due to the actual fingerprint for a path dependency not being known until *after* the crate is compiled (the fingerprint is the mtime of the dep-info file). Closes #1236
2015-01-29 03:37:19 +00:00
2018-03-14 15:17:44 +00:00
File::create(&p.root().join("src/lib.rs"))
.unwrap()
.write_all(br#"extern crate a; extern crate b; pub fn toplevel() {}"#)
2018-03-14 15:17:44 +00:00
.unwrap();
Consider transitive fingerprints for freshness Originally discovered through #1236, this commit fixes a bug in Cargo where crates may not be recompiled when they need to (leading to obscure errors from the compiler). The scenario in question looks like: * Assume a dependency graph of `A -> B -> C` and `A -> C` * Build all packages * Modify C * Rebuild, but hit Ctrl+C while B is building * Modify A * Rebuild again Previously, Cargo only considered the freshness of a package to be the freshness of the package itself (checking source files, for example). To handle transitive recompilations, Cargo propagates a dirty bit throughout the dependency graph automatically (instead if calculating it as such). In the above example, however, we have a problem where as part of the last rebuild Cargo thinks `B` and `C` are fresh! The artifact for `C` was just recompiled, but `B`'s source code is untainted, so Cargo does not think that it needs to recompile `B`. This is wrong, however, because one of `B`'s dependencies was rebuilt, so it needs to be rebuilt. To fix this problem, the fingerprint (a short hash) for all packages is now transitively propagated (the fingerprint changes when an upstream package changes). This should ensure that even when Ctrl+C is hit (or the situation explained in #1236) that Cargo will still consider packages whose source code is untainted as candidates for recompilation. The implementation is somewhat tricky due to the actual fingerprint for a path dependency not being known until *after* the crate is compiled (the fingerprint is the mtime of the dep-info file). Closes #1236
2015-01-29 03:37:19 +00:00
p.cargo("build").run();
}
#[test]
2016-10-04 22:21:16 +00:00
fn changing_lib_features_caches_targets() {
let p = project()
2018-03-14 15:17:44 +00:00
.file(
"Cargo.toml",
r#"
[package]
name = "foo"
authors = []
version = "0.0.1"
[features]
foo = []
2018-03-14 15:17:44 +00:00
"#,
2018-12-08 11:19:47 +00:00
)
.file("src/lib.rs", "")
.build();
p.cargo("build")
.with_stderr(
2018-03-14 15:17:44 +00:00
"\
[..]Compiling foo v0.0.1 ([..])
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
2018-03-14 15:17:44 +00:00
",
2018-12-08 11:19:47 +00:00
)
.run();
2018-03-14 15:17:44 +00:00
p.cargo("build --features foo")
.with_stderr(
2018-03-14 15:17:44 +00:00
"\
[..]Compiling foo v0.0.1 ([..])
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
2018-03-14 15:17:44 +00:00
",
2018-12-08 11:19:47 +00:00
)
.run();
2016-10-04 22:21:16 +00:00
2016-11-12 08:26:39 +00:00
/* Targets should be cached from the first build */
2016-10-04 22:21:16 +00:00
p.cargo("build")
.with_stderr("[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]")
.run();
p.cargo("build").with_stdout("").run();
2016-10-04 22:21:16 +00:00
p.cargo("build --features foo")
.with_stderr("[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]")
.run();
2016-10-04 22:21:16 +00:00
}
#[test]
fn changing_profiles_caches_targets() {
let p = project()
2018-03-14 15:17:44 +00:00
.file(
"Cargo.toml",
r#"
[package]
name = "foo"
authors = []
version = "0.0.1"
[profile.dev]
panic = "abort"
2018-03-14 15:17:44 +00:00
"#,
2018-12-08 11:19:47 +00:00
)
.file("src/lib.rs", "")
.build();
p.cargo("build")
.with_stderr(
2018-03-14 15:17:44 +00:00
"\
[..]Compiling foo v0.0.1 ([..])
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
2018-03-14 15:17:44 +00:00
",
2018-12-08 11:19:47 +00:00
)
.run();
2018-03-14 15:17:44 +00:00
p.cargo("test")
.with_stderr(
2018-03-14 15:17:44 +00:00
"\
[..]Compiling foo v0.0.1 ([..])
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
[RUNNING] target[..]debug[..]deps[..]foo-[..][EXE]
[DOCTEST] foo
2018-03-14 15:17:44 +00:00
",
2018-12-08 11:19:47 +00:00
)
.run();
2016-11-12 08:26:39 +00:00
/* Targets should be cached from the first build */
p.cargo("build")
.with_stderr("[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]")
.run();
2018-03-14 15:17:44 +00:00
p.cargo("test foo")
.with_stderr(
2018-03-14 15:17:44 +00:00
"\
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
[RUNNING] target[..]debug[..]deps[..]foo-[..][EXE]
[DOCTEST] foo
2018-03-14 15:17:44 +00:00
",
2018-12-08 11:19:47 +00:00
)
.run();
}
2016-10-04 22:21:16 +00:00
#[test]
fn changing_bin_paths_common_target_features_caches_targets() {
// Make sure dep_cache crate is built once per feature
let p = project()
.no_manifest()
2018-03-14 15:17:44 +00:00
.file(
".cargo/config",
r#"
2016-10-04 22:21:16 +00:00
[build]
target-dir = "./target"
2018-03-14 15:17:44 +00:00
"#,
2018-12-08 11:19:47 +00:00
)
.file(
2018-03-14 15:17:44 +00:00
"dep_crate/Cargo.toml",
r#"
2016-10-04 22:21:16 +00:00
[package]
name = "dep_crate"
version = "0.0.1"
authors = []
[features]
ftest = []
2018-03-14 15:17:44 +00:00
"#,
2018-12-08 11:19:47 +00:00
)
.file(
2018-03-14 15:17:44 +00:00
"dep_crate/src/lib.rs",
r#"
2016-10-04 22:21:16 +00:00
#[cfg(feature = "ftest")]
pub fn yo() {
println!("ftest on")
}
#[cfg(not(feature = "ftest"))]
pub fn yo() {
println!("ftest off")
}
2018-03-14 15:17:44 +00:00
"#,
2018-12-08 11:19:47 +00:00
)
.file(
2018-03-14 15:17:44 +00:00
"a/Cargo.toml",
r#"
2016-10-04 22:21:16 +00:00
[package]
name = "a"
version = "0.0.1"
authors = []
[dependencies]
dep_crate = {path = "../dep_crate", features = []}
2018-03-14 15:17:44 +00:00
"#,
2018-12-08 11:19:47 +00:00
)
.file("a/src/lib.rs", "")
2018-03-14 15:17:44 +00:00
.file(
"a/src/main.rs",
r#"
2016-10-04 22:21:16 +00:00
extern crate dep_crate;
use dep_crate::yo;
fn main() {
yo();
}
2018-03-14 15:17:44 +00:00
"#,
2018-12-08 11:19:47 +00:00
)
.file(
2018-03-14 15:17:44 +00:00
"b/Cargo.toml",
r#"
2016-10-04 22:21:16 +00:00
[package]
name = "b"
version = "0.0.1"
authors = []
[dependencies]
dep_crate = {path = "../dep_crate", features = ["ftest"]}
2018-03-14 15:17:44 +00:00
"#,
2018-12-08 11:19:47 +00:00
)
.file("b/src/lib.rs", "")
2018-03-14 15:17:44 +00:00
.file(
"b/src/main.rs",
r#"
2016-10-04 22:21:16 +00:00
extern crate dep_crate;
use dep_crate::yo;
fn main() {
yo();
}
2018-03-14 15:17:44 +00:00
"#,
2018-12-08 11:19:47 +00:00
)
.build();
2016-10-04 22:21:16 +00:00
/* Build and rebuild a/. Ensure dep_crate only builds once */
p.cargo("run")
.cwd(p.root().join("a"))
.with_stdout("ftest off")
.with_stderr(
2018-03-14 15:17:44 +00:00
"\
2016-10-04 22:21:16 +00:00
[..]Compiling dep_crate v0.0.1 ([..])
[..]Compiling a v0.0.1 ([..])
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
2018-08-02 09:18:48 +00:00
[RUNNING] `[..]target/debug/a[EXE]`
2018-03-14 15:17:44 +00:00
",
2018-12-08 11:19:47 +00:00
)
.run();
p.cargo("clean -p a").cwd(p.root().join("a")).run();
p.cargo("run")
.cwd(p.root().join("a"))
.with_stdout("ftest off")
.with_stderr(
2018-03-14 15:17:44 +00:00
"\
2016-10-04 22:21:16 +00:00
[..]Compiling a v0.0.1 ([..])
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
2018-08-02 09:18:48 +00:00
[RUNNING] `[..]target/debug/a[EXE]`
2018-03-14 15:17:44 +00:00
",
2018-12-08 11:19:47 +00:00
)
.run();
2016-10-04 22:21:16 +00:00
/* Build and rebuild b/. Ensure dep_crate only builds once */
p.cargo("run")
.cwd(p.root().join("b"))
.with_stdout("ftest on")
.with_stderr(
2018-03-14 15:17:44 +00:00
"\
2016-10-04 22:21:16 +00:00
[..]Compiling dep_crate v0.0.1 ([..])
[..]Compiling b v0.0.1 ([..])
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
2018-08-02 09:18:48 +00:00
[RUNNING] `[..]target/debug/b[EXE]`
2018-03-14 15:17:44 +00:00
",
2018-12-08 11:19:47 +00:00
)
.run();
p.cargo("clean -p b").cwd(p.root().join("b")).run();
p.cargo("run")
.cwd(p.root().join("b"))
.with_stdout("ftest on")
.with_stderr(
2018-03-14 15:17:44 +00:00
"\
2016-10-04 22:21:16 +00:00
[..]Compiling b v0.0.1 ([..])
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
2018-08-02 09:18:48 +00:00
[RUNNING] `[..]target/debug/b[EXE]`
2018-03-14 15:17:44 +00:00
",
2018-12-08 11:19:47 +00:00
)
.run();
2016-10-04 22:21:16 +00:00
/* Build a/ package again. If we cache different feature dep builds correctly,
* this should not cause a rebuild of dep_crate */
p.cargo("clean -p a").cwd(p.root().join("a")).run();
p.cargo("run")
.cwd(p.root().join("a"))
.with_stdout("ftest off")
.with_stderr(
2018-03-14 15:17:44 +00:00
"\
2016-10-04 22:21:16 +00:00
[..]Compiling a v0.0.1 ([..])
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
2018-08-02 09:18:48 +00:00
[RUNNING] `[..]target/debug/a[EXE]`
2018-03-14 15:17:44 +00:00
",
2018-12-08 11:19:47 +00:00
)
.run();
2016-10-04 22:21:16 +00:00
/* Build b/ package again. If we cache different feature dep builds correctly,
* this should not cause a rebuild */
p.cargo("clean -p b").cwd(p.root().join("b")).run();
p.cargo("run")
.cwd(p.root().join("b"))
.with_stdout("ftest on")
.with_stderr(
2018-03-14 15:17:44 +00:00
"\
2016-10-04 22:21:16 +00:00
[..]Compiling b v0.0.1 ([..])
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
2018-08-02 09:18:48 +00:00
[RUNNING] `[..]target/debug/b[EXE]`
2018-03-14 15:17:44 +00:00
",
2018-12-08 11:19:47 +00:00
)
.run();
2016-10-04 22:21:16 +00:00
}
#[test]
fn changing_bin_features_caches_targets() {
let p = project()
2018-03-14 15:17:44 +00:00
.file(
"Cargo.toml",
r#"
2016-10-04 22:21:16 +00:00
[package]
name = "foo"
authors = []
version = "0.0.1"
[features]
foo = []
2018-03-14 15:17:44 +00:00
"#,
2018-12-08 11:19:47 +00:00
)
.file(
2018-03-14 15:17:44 +00:00
"src/main.rs",
r#"
fn main() {
let msg = if cfg!(feature = "foo") { "feature on" } else { "feature off" };
println!("{}", msg);
}
2018-03-14 15:17:44 +00:00
"#,
2018-12-08 11:19:47 +00:00
)
.build();
2016-10-04 22:21:16 +00:00
// Windows has a problem with replacing a binary that was just executed.
// Unlinking it will succeed, but then attempting to immediately replace
// it will sometimes fail with "Already Exists".
// See https://github.com/rust-lang/cargo/issues/5481
let foo_proc = |name: &str| {
let src = p.bin("foo");
let dst = p.bin(name);
fs::rename(&src, &dst).expect("Failed to rename foo");
p.process(dst)
};
p.cargo("build")
.with_stderr(
"\
[COMPILING] foo v0.0.1 ([..])
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
2018-03-14 15:17:44 +00:00
",
2018-12-08 11:19:47 +00:00
)
.run();
2018-08-28 20:38:26 +00:00
foo_proc("off1").with_stdout("feature off").run();
p.cargo("build --features foo")
.with_stderr(
"\
[COMPILING] foo v0.0.1 ([..])
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
2018-03-14 15:17:44 +00:00
",
2018-12-08 11:19:47 +00:00
)
.run();
2018-08-28 20:38:26 +00:00
foo_proc("on1").with_stdout("feature on").run();
2016-10-04 22:21:16 +00:00
2016-11-12 08:26:39 +00:00
/* Targets should be cached from the first build */
2016-10-04 22:21:16 +00:00
p.cargo("build")
.with_stderr(
"\
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
2018-03-14 15:17:44 +00:00
",
2018-12-08 11:19:47 +00:00
)
.run();
2018-08-28 20:38:26 +00:00
foo_proc("off2").with_stdout("feature off").run();
p.cargo("build --features foo")
.with_stderr(
"\
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
2018-03-14 15:17:44 +00:00
",
2018-12-08 11:19:47 +00:00
)
.run();
2018-08-28 20:38:26 +00:00
foo_proc("on2").with_stdout("feature on").run();
}
#[test]
fn rebuild_tests_if_lib_changes() {
let p = project()
.file("src/lib.rs", "pub fn foo() {}")
2018-03-14 15:17:44 +00:00
.file(
"tests/foo.rs",
r#"
extern crate foo;
#[test]
fn test() { foo::foo(); }
2018-03-14 15:17:44 +00:00
"#,
2018-12-08 11:19:47 +00:00
)
.build();
p.cargo("build").run();
p.cargo("test").run();
sleep_ms(1000);
File::create(&p.root().join("src/lib.rs")).unwrap();
p.cargo("build -v").run();
p.cargo("test -v")
.with_status(101)
.with_stderr_contains("[..]cannot find function `foo`[..]")
.run();
}
Refactor Cargo's backend, again! This commit started out identifying a relatively simple bug in Cargo. A recent change made it such that the resolution graph included all target-specific dependencies, relying on the structure of the backend to filter out those which don't need to get built. This was unfortunately not accounted for in the portion of the backend that schedules work, mistakenly causing spurious rebuilds if different runs of the graph pulled in new crates. For example if `cargo build` didn't build any target-specific dependencies but then later `cargo test` did (e.g. a dev-dep pulled in a target-specific dep unconditionally) then it would cause a rebuild of the entire graph. This class of bug is certainly not the first in a long and storied history of the backend having multiple points where dependencies are calculated and those often don't quite agree with one another. The purpose of this rewrite is twofold: 1. The `Stage` enum in the backend for scheduling work and ensuring that maximum parallelism is achieved is removed entirely. There is already a function on `Context` which expresses the dependency between targets (`dep_targets`) which takes a much finer grain of dependencies into account as well as already having all the logic for what-depends-on-what. This duplication has caused numerous problems in the past, an unifying these two will truly grant maximum parallelism while ensuring that everyone agrees on what their dependencies are. 2. A large number of locations in the backend have grown to take a (Package, Target, Profile, Kind) tuple, or some subset of this tuple. In general this represents a "unit of work" and is much easier to pass around as one variable, so a `Unit` was introduced which references all of these variables. Almost the entire backend was altered to take a `Unit` instead of these variables specifically, typically providing all of the contextual information necessary for an operation. A crucial part of this change is the inclusion of `Kind` in a `Unit` to ensure that everyone *also* agrees on what architecture they're compiling everything for. There have been many bugs in the past where one part of the backend determined that a package was built for one architecture and then another part thought it was built for another. With the inclusion of `Kind` in dependency management this is handled in a much cleaner fashion as it's only calculated in one location. Some other miscellaneous changes made were: * The `Platform` enumeration has finally been removed. This has been entirely subsumed by `Kind`. * The hokey logic for "build this crate once" even though it may be depended on by both the host/target kinds has been removed. This is now handled in a much nicer fashion where if there's no target then Kind::Target is just never used, and multiple requests for a package are just naturally deduplicated. * There's no longer any need to build up the "requirements" for a package in terms of what platforms it's compiled for, this now just naturally falls out of the dependency graph. * If a build script is overridden then its entire tree of dependencies are not compiled, not just the build script itself. * The `threadpool` dependency has been replaced with one on `crossbeam`. The method of calculating dependencies has quite a few non-static lifetimes and the scoped threads of `crossbeam` are now used instead of a thread pool. * Once any thread fails to execute a command work is no longer scheduled unlike before where some extra pending work may continue to start. * Many functions used early on, such as `compile` and `build_map` have been massively simplified by farming out dependency management to `Context::dep_targets`. * There is now a new profile to represent running a build script. This is used to inject dependencies as well as represent that a library depends on running a build script, not just building it. This change has currently been tested against cross-compiling Servo to Android and passes the test suite (which has quite a few corner cases for build scripts and such), so I'm pretty confident that this refactoring won't have at least too many regressions!
2015-10-02 06:48:47 +00:00
#[test]
fn no_rebuild_transitive_target_deps() {
let p = project()
2018-03-14 15:17:44 +00:00
.file(
"Cargo.toml",
r#"
Refactor Cargo's backend, again! This commit started out identifying a relatively simple bug in Cargo. A recent change made it such that the resolution graph included all target-specific dependencies, relying on the structure of the backend to filter out those which don't need to get built. This was unfortunately not accounted for in the portion of the backend that schedules work, mistakenly causing spurious rebuilds if different runs of the graph pulled in new crates. For example if `cargo build` didn't build any target-specific dependencies but then later `cargo test` did (e.g. a dev-dep pulled in a target-specific dep unconditionally) then it would cause a rebuild of the entire graph. This class of bug is certainly not the first in a long and storied history of the backend having multiple points where dependencies are calculated and those often don't quite agree with one another. The purpose of this rewrite is twofold: 1. The `Stage` enum in the backend for scheduling work and ensuring that maximum parallelism is achieved is removed entirely. There is already a function on `Context` which expresses the dependency between targets (`dep_targets`) which takes a much finer grain of dependencies into account as well as already having all the logic for what-depends-on-what. This duplication has caused numerous problems in the past, an unifying these two will truly grant maximum parallelism while ensuring that everyone agrees on what their dependencies are. 2. A large number of locations in the backend have grown to take a (Package, Target, Profile, Kind) tuple, or some subset of this tuple. In general this represents a "unit of work" and is much easier to pass around as one variable, so a `Unit` was introduced which references all of these variables. Almost the entire backend was altered to take a `Unit` instead of these variables specifically, typically providing all of the contextual information necessary for an operation. A crucial part of this change is the inclusion of `Kind` in a `Unit` to ensure that everyone *also* agrees on what architecture they're compiling everything for. There have been many bugs in the past where one part of the backend determined that a package was built for one architecture and then another part thought it was built for another. With the inclusion of `Kind` in dependency management this is handled in a much cleaner fashion as it's only calculated in one location. Some other miscellaneous changes made were: * The `Platform` enumeration has finally been removed. This has been entirely subsumed by `Kind`. * The hokey logic for "build this crate once" even though it may be depended on by both the host/target kinds has been removed. This is now handled in a much nicer fashion where if there's no target then Kind::Target is just never used, and multiple requests for a package are just naturally deduplicated. * There's no longer any need to build up the "requirements" for a package in terms of what platforms it's compiled for, this now just naturally falls out of the dependency graph. * If a build script is overridden then its entire tree of dependencies are not compiled, not just the build script itself. * The `threadpool` dependency has been replaced with one on `crossbeam`. The method of calculating dependencies has quite a few non-static lifetimes and the scoped threads of `crossbeam` are now used instead of a thread pool. * Once any thread fails to execute a command work is no longer scheduled unlike before where some extra pending work may continue to start. * Many functions used early on, such as `compile` and `build_map` have been massively simplified by farming out dependency management to `Context::dep_targets`. * There is now a new profile to represent running a build script. This is used to inject dependencies as well as represent that a library depends on running a build script, not just building it. This change has currently been tested against cross-compiling Servo to Android and passes the test suite (which has quite a few corner cases for build scripts and such), so I'm pretty confident that this refactoring won't have at least too many regressions!
2015-10-02 06:48:47 +00:00
[package]
name = "foo"
version = "0.0.1"
authors = []
[dependencies]
a = { path = "a" }
[dev-dependencies]
b = { path = "b" }
2018-03-14 15:17:44 +00:00
"#,
2018-12-08 11:19:47 +00:00
)
.file("src/lib.rs", "")
Refactor Cargo's backend, again! This commit started out identifying a relatively simple bug in Cargo. A recent change made it such that the resolution graph included all target-specific dependencies, relying on the structure of the backend to filter out those which don't need to get built. This was unfortunately not accounted for in the portion of the backend that schedules work, mistakenly causing spurious rebuilds if different runs of the graph pulled in new crates. For example if `cargo build` didn't build any target-specific dependencies but then later `cargo test` did (e.g. a dev-dep pulled in a target-specific dep unconditionally) then it would cause a rebuild of the entire graph. This class of bug is certainly not the first in a long and storied history of the backend having multiple points where dependencies are calculated and those often don't quite agree with one another. The purpose of this rewrite is twofold: 1. The `Stage` enum in the backend for scheduling work and ensuring that maximum parallelism is achieved is removed entirely. There is already a function on `Context` which expresses the dependency between targets (`dep_targets`) which takes a much finer grain of dependencies into account as well as already having all the logic for what-depends-on-what. This duplication has caused numerous problems in the past, an unifying these two will truly grant maximum parallelism while ensuring that everyone agrees on what their dependencies are. 2. A large number of locations in the backend have grown to take a (Package, Target, Profile, Kind) tuple, or some subset of this tuple. In general this represents a "unit of work" and is much easier to pass around as one variable, so a `Unit` was introduced which references all of these variables. Almost the entire backend was altered to take a `Unit` instead of these variables specifically, typically providing all of the contextual information necessary for an operation. A crucial part of this change is the inclusion of `Kind` in a `Unit` to ensure that everyone *also* agrees on what architecture they're compiling everything for. There have been many bugs in the past where one part of the backend determined that a package was built for one architecture and then another part thought it was built for another. With the inclusion of `Kind` in dependency management this is handled in a much cleaner fashion as it's only calculated in one location. Some other miscellaneous changes made were: * The `Platform` enumeration has finally been removed. This has been entirely subsumed by `Kind`. * The hokey logic for "build this crate once" even though it may be depended on by both the host/target kinds has been removed. This is now handled in a much nicer fashion where if there's no target then Kind::Target is just never used, and multiple requests for a package are just naturally deduplicated. * There's no longer any need to build up the "requirements" for a package in terms of what platforms it's compiled for, this now just naturally falls out of the dependency graph. * If a build script is overridden then its entire tree of dependencies are not compiled, not just the build script itself. * The `threadpool` dependency has been replaced with one on `crossbeam`. The method of calculating dependencies has quite a few non-static lifetimes and the scoped threads of `crossbeam` are now used instead of a thread pool. * Once any thread fails to execute a command work is no longer scheduled unlike before where some extra pending work may continue to start. * Many functions used early on, such as `compile` and `build_map` have been massively simplified by farming out dependency management to `Context::dep_targets`. * There is now a new profile to represent running a build script. This is used to inject dependencies as well as represent that a library depends on running a build script, not just building it. This change has currently been tested against cross-compiling Servo to Android and passes the test suite (which has quite a few corner cases for build scripts and such), so I'm pretty confident that this refactoring won't have at least too many regressions!
2015-10-02 06:48:47 +00:00
.file("tests/foo.rs", "")
2018-03-14 15:17:44 +00:00
.file(
"a/Cargo.toml",
r#"
Refactor Cargo's backend, again! This commit started out identifying a relatively simple bug in Cargo. A recent change made it such that the resolution graph included all target-specific dependencies, relying on the structure of the backend to filter out those which don't need to get built. This was unfortunately not accounted for in the portion of the backend that schedules work, mistakenly causing spurious rebuilds if different runs of the graph pulled in new crates. For example if `cargo build` didn't build any target-specific dependencies but then later `cargo test` did (e.g. a dev-dep pulled in a target-specific dep unconditionally) then it would cause a rebuild of the entire graph. This class of bug is certainly not the first in a long and storied history of the backend having multiple points where dependencies are calculated and those often don't quite agree with one another. The purpose of this rewrite is twofold: 1. The `Stage` enum in the backend for scheduling work and ensuring that maximum parallelism is achieved is removed entirely. There is already a function on `Context` which expresses the dependency between targets (`dep_targets`) which takes a much finer grain of dependencies into account as well as already having all the logic for what-depends-on-what. This duplication has caused numerous problems in the past, an unifying these two will truly grant maximum parallelism while ensuring that everyone agrees on what their dependencies are. 2. A large number of locations in the backend have grown to take a (Package, Target, Profile, Kind) tuple, or some subset of this tuple. In general this represents a "unit of work" and is much easier to pass around as one variable, so a `Unit` was introduced which references all of these variables. Almost the entire backend was altered to take a `Unit` instead of these variables specifically, typically providing all of the contextual information necessary for an operation. A crucial part of this change is the inclusion of `Kind` in a `Unit` to ensure that everyone *also* agrees on what architecture they're compiling everything for. There have been many bugs in the past where one part of the backend determined that a package was built for one architecture and then another part thought it was built for another. With the inclusion of `Kind` in dependency management this is handled in a much cleaner fashion as it's only calculated in one location. Some other miscellaneous changes made were: * The `Platform` enumeration has finally been removed. This has been entirely subsumed by `Kind`. * The hokey logic for "build this crate once" even though it may be depended on by both the host/target kinds has been removed. This is now handled in a much nicer fashion where if there's no target then Kind::Target is just never used, and multiple requests for a package are just naturally deduplicated. * There's no longer any need to build up the "requirements" for a package in terms of what platforms it's compiled for, this now just naturally falls out of the dependency graph. * If a build script is overridden then its entire tree of dependencies are not compiled, not just the build script itself. * The `threadpool` dependency has been replaced with one on `crossbeam`. The method of calculating dependencies has quite a few non-static lifetimes and the scoped threads of `crossbeam` are now used instead of a thread pool. * Once any thread fails to execute a command work is no longer scheduled unlike before where some extra pending work may continue to start. * Many functions used early on, such as `compile` and `build_map` have been massively simplified by farming out dependency management to `Context::dep_targets`. * There is now a new profile to represent running a build script. This is used to inject dependencies as well as represent that a library depends on running a build script, not just building it. This change has currently been tested against cross-compiling Servo to Android and passes the test suite (which has quite a few corner cases for build scripts and such), so I'm pretty confident that this refactoring won't have at least too many regressions!
2015-10-02 06:48:47 +00:00
[package]
name = "a"
version = "0.0.1"
authors = []
[target.foo.dependencies]
c = { path = "../c" }
2018-03-14 15:17:44 +00:00
"#,
2018-12-08 11:19:47 +00:00
)
.file("a/src/lib.rs", "")
2018-03-14 15:17:44 +00:00
.file(
"b/Cargo.toml",
r#"
Refactor Cargo's backend, again! This commit started out identifying a relatively simple bug in Cargo. A recent change made it such that the resolution graph included all target-specific dependencies, relying on the structure of the backend to filter out those which don't need to get built. This was unfortunately not accounted for in the portion of the backend that schedules work, mistakenly causing spurious rebuilds if different runs of the graph pulled in new crates. For example if `cargo build` didn't build any target-specific dependencies but then later `cargo test` did (e.g. a dev-dep pulled in a target-specific dep unconditionally) then it would cause a rebuild of the entire graph. This class of bug is certainly not the first in a long and storied history of the backend having multiple points where dependencies are calculated and those often don't quite agree with one another. The purpose of this rewrite is twofold: 1. The `Stage` enum in the backend for scheduling work and ensuring that maximum parallelism is achieved is removed entirely. There is already a function on `Context` which expresses the dependency between targets (`dep_targets`) which takes a much finer grain of dependencies into account as well as already having all the logic for what-depends-on-what. This duplication has caused numerous problems in the past, an unifying these two will truly grant maximum parallelism while ensuring that everyone agrees on what their dependencies are. 2. A large number of locations in the backend have grown to take a (Package, Target, Profile, Kind) tuple, or some subset of this tuple. In general this represents a "unit of work" and is much easier to pass around as one variable, so a `Unit` was introduced which references all of these variables. Almost the entire backend was altered to take a `Unit` instead of these variables specifically, typically providing all of the contextual information necessary for an operation. A crucial part of this change is the inclusion of `Kind` in a `Unit` to ensure that everyone *also* agrees on what architecture they're compiling everything for. There have been many bugs in the past where one part of the backend determined that a package was built for one architecture and then another part thought it was built for another. With the inclusion of `Kind` in dependency management this is handled in a much cleaner fashion as it's only calculated in one location. Some other miscellaneous changes made were: * The `Platform` enumeration has finally been removed. This has been entirely subsumed by `Kind`. * The hokey logic for "build this crate once" even though it may be depended on by both the host/target kinds has been removed. This is now handled in a much nicer fashion where if there's no target then Kind::Target is just never used, and multiple requests for a package are just naturally deduplicated. * There's no longer any need to build up the "requirements" for a package in terms of what platforms it's compiled for, this now just naturally falls out of the dependency graph. * If a build script is overridden then its entire tree of dependencies are not compiled, not just the build script itself. * The `threadpool` dependency has been replaced with one on `crossbeam`. The method of calculating dependencies has quite a few non-static lifetimes and the scoped threads of `crossbeam` are now used instead of a thread pool. * Once any thread fails to execute a command work is no longer scheduled unlike before where some extra pending work may continue to start. * Many functions used early on, such as `compile` and `build_map` have been massively simplified by farming out dependency management to `Context::dep_targets`. * There is now a new profile to represent running a build script. This is used to inject dependencies as well as represent that a library depends on running a build script, not just building it. This change has currently been tested against cross-compiling Servo to Android and passes the test suite (which has quite a few corner cases for build scripts and such), so I'm pretty confident that this refactoring won't have at least too many regressions!
2015-10-02 06:48:47 +00:00
[package]
name = "b"
version = "0.0.1"
authors = []
[dependencies]
c = { path = "../c" }
2018-03-14 15:17:44 +00:00
"#,
2018-12-08 11:19:47 +00:00
)
.file("b/src/lib.rs", "")
2018-07-24 22:35:01 +00:00
.file("c/Cargo.toml", &basic_manifest("c", "0.0.1"))
.file("c/src/lib.rs", "")
.build();
Refactor Cargo's backend, again! This commit started out identifying a relatively simple bug in Cargo. A recent change made it such that the resolution graph included all target-specific dependencies, relying on the structure of the backend to filter out those which don't need to get built. This was unfortunately not accounted for in the portion of the backend that schedules work, mistakenly causing spurious rebuilds if different runs of the graph pulled in new crates. For example if `cargo build` didn't build any target-specific dependencies but then later `cargo test` did (e.g. a dev-dep pulled in a target-specific dep unconditionally) then it would cause a rebuild of the entire graph. This class of bug is certainly not the first in a long and storied history of the backend having multiple points where dependencies are calculated and those often don't quite agree with one another. The purpose of this rewrite is twofold: 1. The `Stage` enum in the backend for scheduling work and ensuring that maximum parallelism is achieved is removed entirely. There is already a function on `Context` which expresses the dependency between targets (`dep_targets`) which takes a much finer grain of dependencies into account as well as already having all the logic for what-depends-on-what. This duplication has caused numerous problems in the past, an unifying these two will truly grant maximum parallelism while ensuring that everyone agrees on what their dependencies are. 2. A large number of locations in the backend have grown to take a (Package, Target, Profile, Kind) tuple, or some subset of this tuple. In general this represents a "unit of work" and is much easier to pass around as one variable, so a `Unit` was introduced which references all of these variables. Almost the entire backend was altered to take a `Unit` instead of these variables specifically, typically providing all of the contextual information necessary for an operation. A crucial part of this change is the inclusion of `Kind` in a `Unit` to ensure that everyone *also* agrees on what architecture they're compiling everything for. There have been many bugs in the past where one part of the backend determined that a package was built for one architecture and then another part thought it was built for another. With the inclusion of `Kind` in dependency management this is handled in a much cleaner fashion as it's only calculated in one location. Some other miscellaneous changes made were: * The `Platform` enumeration has finally been removed. This has been entirely subsumed by `Kind`. * The hokey logic for "build this crate once" even though it may be depended on by both the host/target kinds has been removed. This is now handled in a much nicer fashion where if there's no target then Kind::Target is just never used, and multiple requests for a package are just naturally deduplicated. * There's no longer any need to build up the "requirements" for a package in terms of what platforms it's compiled for, this now just naturally falls out of the dependency graph. * If a build script is overridden then its entire tree of dependencies are not compiled, not just the build script itself. * The `threadpool` dependency has been replaced with one on `crossbeam`. The method of calculating dependencies has quite a few non-static lifetimes and the scoped threads of `crossbeam` are now used instead of a thread pool. * Once any thread fails to execute a command work is no longer scheduled unlike before where some extra pending work may continue to start. * Many functions used early on, such as `compile` and `build_map` have been massively simplified by farming out dependency management to `Context::dep_targets`. * There is now a new profile to represent running a build script. This is used to inject dependencies as well as represent that a library depends on running a build script, not just building it. This change has currently been tested against cross-compiling Servo to Android and passes the test suite (which has quite a few corner cases for build scripts and such), so I'm pretty confident that this refactoring won't have at least too many regressions!
2015-10-02 06:48:47 +00:00
p.cargo("build").run();
p.cargo("test --no-run")
.with_stderr(
2018-03-14 15:17:44 +00:00
"\
[COMPILING] c v0.0.1 ([..])
[COMPILING] b v0.0.1 ([..])
[COMPILING] foo v0.0.1 ([..])
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
2018-03-14 15:17:44 +00:00
",
2018-12-08 11:19:47 +00:00
)
.run();
}
#[test]
fn rerun_if_changed_in_dep() {
let p = project()
2018-03-14 15:17:44 +00:00
.file(
"Cargo.toml",
r#"
[package]
name = "foo"
version = "0.0.1"
authors = []
[dependencies]
a = { path = "a" }
2018-03-14 15:17:44 +00:00
"#,
2018-12-08 11:19:47 +00:00
)
.file("src/lib.rs", "")
2018-03-14 15:17:44 +00:00
.file(
"a/Cargo.toml",
r#"
[package]
name = "a"
version = "0.0.1"
authors = []
build = "build.rs"
2018-03-14 15:17:44 +00:00
"#,
2018-12-08 11:19:47 +00:00
)
.file(
2018-03-14 15:17:44 +00:00
"a/build.rs",
r#"
fn main() {
println!("cargo:rerun-if-changed=build.rs");
}
2018-03-14 15:17:44 +00:00
"#,
2018-12-08 11:19:47 +00:00
)
.file("a/src/lib.rs", "")
.build();
p.cargo("build").run();
p.cargo("build").with_stdout("").run();
}
#[test]
fn same_build_dir_cached_packages() {
let p = project()
.no_manifest()
2018-03-14 15:17:44 +00:00
.file(
"a1/Cargo.toml",
r#"
[package]
name = "a1"
version = "0.0.1"
authors = []
[dependencies]
b = { path = "../b" }
2018-03-14 15:17:44 +00:00
"#,
2018-12-08 11:19:47 +00:00
)
.file("a1/src/lib.rs", "")
2018-03-14 15:17:44 +00:00
.file(
"a2/Cargo.toml",
r#"
[package]
name = "a2"
version = "0.0.1"
authors = []
[dependencies]
b = { path = "../b" }
2018-03-14 15:17:44 +00:00
"#,
2018-12-08 11:19:47 +00:00
)
.file("a2/src/lib.rs", "")
2018-03-14 15:17:44 +00:00
.file(
"b/Cargo.toml",
r#"
[package]
name = "b"
version = "0.0.1"
authors = []
[dependencies]
c = { path = "../c" }
2018-03-14 15:17:44 +00:00
"#,
2018-12-08 11:19:47 +00:00
)
.file("b/src/lib.rs", "")
2018-03-14 15:17:44 +00:00
.file(
"c/Cargo.toml",
r#"
[package]
name = "c"
version = "0.0.1"
authors = []
[dependencies]
d = { path = "../d" }
2018-03-14 15:17:44 +00:00
"#,
2018-12-08 11:19:47 +00:00
)
.file("c/src/lib.rs", "")
2018-07-24 22:35:01 +00:00
.file("d/Cargo.toml", &basic_manifest("d", "0.0.1"))
.file("d/src/lib.rs", "")
2018-03-14 15:17:44 +00:00
.file(
".cargo/config",
r#"
[build]
target-dir = "./target"
2018-03-14 15:17:44 +00:00
"#,
2018-12-08 11:19:47 +00:00
)
.build();
p.cargo("build")
.cwd(p.root().join("a1"))
.with_stderr(&format!(
2018-03-14 15:17:44 +00:00
"\
[COMPILING] d v0.0.1 ({dir}/d)
[COMPILING] c v0.0.1 ({dir}/c)
[COMPILING] b v0.0.1 ({dir}/b)
[COMPILING] a1 v0.0.1 ([CWD])
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
2018-03-14 15:17:44 +00:00
",
dir = p.url().to_file_path().unwrap().to_str().unwrap()
2018-12-08 11:19:47 +00:00
))
.run();
p.cargo("build")
.cwd(p.root().join("a2"))
.with_stderr(
2018-03-14 15:17:44 +00:00
"\
[COMPILING] a2 v0.0.1 ([CWD])
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
2018-03-14 15:17:44 +00:00
",
2018-12-08 11:19:47 +00:00
)
.run();
}
2016-07-15 14:31:06 +00:00
#[test]
fn no_rebuild_if_build_artifacts_move_backwards_in_time() {
let p = project()
2018-03-14 15:17:44 +00:00
.file(
"Cargo.toml",
r#"
2016-07-15 14:31:06 +00:00
[package]
name = "foo"
2016-07-15 14:31:06 +00:00
version = "0.0.1"
authors = []
[dependencies]
a = { path = "a" }
2018-03-14 15:17:44 +00:00
"#,
2018-12-08 11:19:47 +00:00
)
.file("src/lib.rs", "")
2018-07-24 22:35:01 +00:00
.file("a/Cargo.toml", &basic_manifest("a", "0.0.1"))
.file("a/src/lib.rs", "")
.build();
2016-07-15 14:31:06 +00:00
p.cargo("build").run();
2016-07-15 14:31:06 +00:00
p.root().move_into_the_past();
p.cargo("build")
.with_stdout("")
.with_stderr("[FINISHED] [..]")
.run();
2016-07-15 14:31:06 +00:00
}
#[test]
fn rebuild_if_build_artifacts_move_forward_in_time() {
let p = project()
2018-03-14 15:17:44 +00:00
.file(
"Cargo.toml",
r#"
2016-07-15 14:31:06 +00:00
[package]
name = "foo"
2016-07-15 14:31:06 +00:00
version = "0.0.1"
authors = []
[dependencies]
a = { path = "a" }
2018-03-14 15:17:44 +00:00
"#,
2018-12-08 11:19:47 +00:00
)
.file("src/lib.rs", "")
2018-07-24 22:35:01 +00:00
.file("a/Cargo.toml", &basic_manifest("a", "0.0.1"))
.file("a/src/lib.rs", "")
.build();
2016-07-15 14:31:06 +00:00
p.cargo("build").run();
2016-07-15 14:31:06 +00:00
p.root().move_into_the_future();
p.cargo("build")
.env("RUST_LOG", "")
.with_stdout("")
.with_stderr(
2018-03-14 15:17:44 +00:00
"\
2016-07-15 14:31:06 +00:00
[COMPILING] a v0.0.1 ([..])
[COMPILING] foo v0.0.1 ([..])
2016-11-02 16:18:30 +00:00
[FINISHED] [..]
2018-03-14 15:17:44 +00:00
",
2018-12-08 11:19:47 +00:00
)
.run();
2016-07-15 14:31:06 +00:00
}
#[test]
fn rebuild_if_environment_changes() {
let p = project()
2018-03-14 15:17:44 +00:00
.file(
"Cargo.toml",
r#"
[package]
name = "foo"
description = "old desc"
version = "0.0.1"
authors = []
2018-03-14 15:17:44 +00:00
"#,
2018-12-08 11:19:47 +00:00
)
.file(
2018-03-14 15:17:44 +00:00
"src/main.rs",
r#"
fn main() {
println!("{}", env!("CARGO_PKG_DESCRIPTION"));
}
2018-03-14 15:17:44 +00:00
"#,
2018-12-08 11:19:47 +00:00
)
.build();
p.cargo("run")
.with_stdout("old desc")
.with_stderr(
"\
[COMPILING] foo v0.0.1 ([CWD])
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
2018-08-02 09:18:48 +00:00
[RUNNING] `target/debug/foo[EXE]`
2018-03-14 15:17:44 +00:00
",
2018-12-08 11:19:47 +00:00
)
.run();
2018-03-14 15:17:44 +00:00
File::create(&p.root().join("Cargo.toml"))
.unwrap()
.write_all(
br#"
[package]
name = "foo"
description = "new desc"
version = "0.0.1"
authors = []
2018-03-14 15:17:44 +00:00
"#,
2018-12-08 11:19:47 +00:00
)
.unwrap();
2018-03-14 15:17:44 +00:00
p.cargo("run")
.with_stdout("new desc")
.with_stderr(
"\
[COMPILING] foo v0.0.1 ([CWD])
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
2018-08-02 09:18:48 +00:00
[RUNNING] `target/debug/foo[EXE]`
2018-03-14 15:17:44 +00:00
",
2018-12-08 11:19:47 +00:00
)
.run();
}
Avoid rebuilding a project when cwd changes This commit is targeted at solving a use case which typically comes up during CI builds -- the `target` directory is cached between builds but the cwd of the build changes over time. For example the following scenario can happen: 1. A project is compiled at `/projects/a`. 2. The `target` directory is cached. 3. A new build is started in `/projects/b`. 4. The previous `target` directory is restored to `/projects/b`. 5. The build start, and Cargo rebuilds everything. The last piece of behavior is indeed unfortunate! Cargo's internal hashing currently isn't that resilient to changing cwd and this PR aims to help improve the situation! The first point of too-much-hashing came up with `Target::src_path`. Each `Target` was hashed and stored for all compilations, and the `src_path` field was an absolute path on the filesystem to the file that needed to be compiled. This path then changed over time when cwd changed, but otherwise everything else remained the same! This commit updates the handling of the `src_path` field to simply ignore it when hashing. Instead the path we actually pass to rustc is later calculated and then passed to the fingerprint calculation. The next problem this fixes is that the dep info files were augmented after creation to have the cwd of the compiler at the time to find the files at a later date. This, unfortunately, would cause issues if the cwd itself changed. Instead the cwd is now left out of dep-info files (they're no longer augmented) and instead the cwd is recalculated when parsing the dep info later. The final problem that this commit fixes is actually an existing issue in Cargo today. Right now you can actually execute `cargo build` from anywhere in a project and Cargo will execute the build. Unfortunately though the argument to rustc was actually different depending on what directory you were in (the compiler was invoked with a path relative to cwd). This path ends up being used for metadata like debuginfo which means that different directories would cause different artifacts to be created, but Cargo wouldn't rerun the compiler! To fix this issue the matter of cwd is now entirely excluded from compilation command lines. Instead rustc is unconditionally invoked with a relative path *if* the path is underneath the workspace root, and otherwise it's invoked as an absolute path (in which case the cwd doesn't matter). Once all these fixes were added up it means that now we can have projects where if you move the entire directory Cargo won't rebuild the original source! Note that this may be a bit of a breaking change, however. This means that the paths in error messages for cargo will no longer be unconditionally relative to the current working directory, but rather relative to the root of the workspace itself. Unfortunately this is moreso of a feature right now rather than a bug, so it may be one that we just have to stomach.
2017-12-06 22:53:09 +00:00
#[test]
fn no_rebuild_when_rename_dir() {
let p = project()
2018-03-14 15:17:44 +00:00
.file(
"Cargo.toml",
r#"
Avoid rebuilding a project when cwd changes This commit is targeted at solving a use case which typically comes up during CI builds -- the `target` directory is cached between builds but the cwd of the build changes over time. For example the following scenario can happen: 1. A project is compiled at `/projects/a`. 2. The `target` directory is cached. 3. A new build is started in `/projects/b`. 4. The previous `target` directory is restored to `/projects/b`. 5. The build start, and Cargo rebuilds everything. The last piece of behavior is indeed unfortunate! Cargo's internal hashing currently isn't that resilient to changing cwd and this PR aims to help improve the situation! The first point of too-much-hashing came up with `Target::src_path`. Each `Target` was hashed and stored for all compilations, and the `src_path` field was an absolute path on the filesystem to the file that needed to be compiled. This path then changed over time when cwd changed, but otherwise everything else remained the same! This commit updates the handling of the `src_path` field to simply ignore it when hashing. Instead the path we actually pass to rustc is later calculated and then passed to the fingerprint calculation. The next problem this fixes is that the dep info files were augmented after creation to have the cwd of the compiler at the time to find the files at a later date. This, unfortunately, would cause issues if the cwd itself changed. Instead the cwd is now left out of dep-info files (they're no longer augmented) and instead the cwd is recalculated when parsing the dep info later. The final problem that this commit fixes is actually an existing issue in Cargo today. Right now you can actually execute `cargo build` from anywhere in a project and Cargo will execute the build. Unfortunately though the argument to rustc was actually different depending on what directory you were in (the compiler was invoked with a path relative to cwd). This path ends up being used for metadata like debuginfo which means that different directories would cause different artifacts to be created, but Cargo wouldn't rerun the compiler! To fix this issue the matter of cwd is now entirely excluded from compilation command lines. Instead rustc is unconditionally invoked with a relative path *if* the path is underneath the workspace root, and otherwise it's invoked as an absolute path (in which case the cwd doesn't matter). Once all these fixes were added up it means that now we can have projects where if you move the entire directory Cargo won't rebuild the original source! Note that this may be a bit of a breaking change, however. This means that the paths in error messages for cargo will no longer be unconditionally relative to the current working directory, but rather relative to the root of the workspace itself. Unfortunately this is moreso of a feature right now rather than a bug, so it may be one that we just have to stomach.
2017-12-06 22:53:09 +00:00
[package]
name = "bar"
version = "0.0.1"
authors = []
[dependencies]
foo = { path = "foo" }
2018-03-14 15:17:44 +00:00
"#,
2018-12-08 11:19:47 +00:00
)
.file("src/lib.rs", "")
2018-07-24 22:35:01 +00:00
.file("foo/Cargo.toml", &basic_manifest("foo", "0.0.1"))
Avoid rebuilding a project when cwd changes This commit is targeted at solving a use case which typically comes up during CI builds -- the `target` directory is cached between builds but the cwd of the build changes over time. For example the following scenario can happen: 1. A project is compiled at `/projects/a`. 2. The `target` directory is cached. 3. A new build is started in `/projects/b`. 4. The previous `target` directory is restored to `/projects/b`. 5. The build start, and Cargo rebuilds everything. The last piece of behavior is indeed unfortunate! Cargo's internal hashing currently isn't that resilient to changing cwd and this PR aims to help improve the situation! The first point of too-much-hashing came up with `Target::src_path`. Each `Target` was hashed and stored for all compilations, and the `src_path` field was an absolute path on the filesystem to the file that needed to be compiled. This path then changed over time when cwd changed, but otherwise everything else remained the same! This commit updates the handling of the `src_path` field to simply ignore it when hashing. Instead the path we actually pass to rustc is later calculated and then passed to the fingerprint calculation. The next problem this fixes is that the dep info files were augmented after creation to have the cwd of the compiler at the time to find the files at a later date. This, unfortunately, would cause issues if the cwd itself changed. Instead the cwd is now left out of dep-info files (they're no longer augmented) and instead the cwd is recalculated when parsing the dep info later. The final problem that this commit fixes is actually an existing issue in Cargo today. Right now you can actually execute `cargo build` from anywhere in a project and Cargo will execute the build. Unfortunately though the argument to rustc was actually different depending on what directory you were in (the compiler was invoked with a path relative to cwd). This path ends up being used for metadata like debuginfo which means that different directories would cause different artifacts to be created, but Cargo wouldn't rerun the compiler! To fix this issue the matter of cwd is now entirely excluded from compilation command lines. Instead rustc is unconditionally invoked with a relative path *if* the path is underneath the workspace root, and otherwise it's invoked as an absolute path (in which case the cwd doesn't matter). Once all these fixes were added up it means that now we can have projects where if you move the entire directory Cargo won't rebuild the original source! Note that this may be a bit of a breaking change, however. This means that the paths in error messages for cargo will no longer be unconditionally relative to the current working directory, but rather relative to the root of the workspace itself. Unfortunately this is moreso of a feature right now rather than a bug, so it may be one that we just have to stomach.
2017-12-06 22:53:09 +00:00
.file("foo/src/lib.rs", "")
.build();
p.cargo("build").run();
Avoid rebuilding a project when cwd changes This commit is targeted at solving a use case which typically comes up during CI builds -- the `target` directory is cached between builds but the cwd of the build changes over time. For example the following scenario can happen: 1. A project is compiled at `/projects/a`. 2. The `target` directory is cached. 3. A new build is started in `/projects/b`. 4. The previous `target` directory is restored to `/projects/b`. 5. The build start, and Cargo rebuilds everything. The last piece of behavior is indeed unfortunate! Cargo's internal hashing currently isn't that resilient to changing cwd and this PR aims to help improve the situation! The first point of too-much-hashing came up with `Target::src_path`. Each `Target` was hashed and stored for all compilations, and the `src_path` field was an absolute path on the filesystem to the file that needed to be compiled. This path then changed over time when cwd changed, but otherwise everything else remained the same! This commit updates the handling of the `src_path` field to simply ignore it when hashing. Instead the path we actually pass to rustc is later calculated and then passed to the fingerprint calculation. The next problem this fixes is that the dep info files were augmented after creation to have the cwd of the compiler at the time to find the files at a later date. This, unfortunately, would cause issues if the cwd itself changed. Instead the cwd is now left out of dep-info files (they're no longer augmented) and instead the cwd is recalculated when parsing the dep info later. The final problem that this commit fixes is actually an existing issue in Cargo today. Right now you can actually execute `cargo build` from anywhere in a project and Cargo will execute the build. Unfortunately though the argument to rustc was actually different depending on what directory you were in (the compiler was invoked with a path relative to cwd). This path ends up being used for metadata like debuginfo which means that different directories would cause different artifacts to be created, but Cargo wouldn't rerun the compiler! To fix this issue the matter of cwd is now entirely excluded from compilation command lines. Instead rustc is unconditionally invoked with a relative path *if* the path is underneath the workspace root, and otherwise it's invoked as an absolute path (in which case the cwd doesn't matter). Once all these fixes were added up it means that now we can have projects where if you move the entire directory Cargo won't rebuild the original source! Note that this may be a bit of a breaking change, however. This means that the paths in error messages for cargo will no longer be unconditionally relative to the current working directory, but rather relative to the root of the workspace itself. Unfortunately this is moreso of a feature right now rather than a bug, so it may be one that we just have to stomach.
2017-12-06 22:53:09 +00:00
let mut new = p.root();
new.pop();
new.push("bar");
fs::rename(p.root(), &new).unwrap();
p.cargo("build")
.cwd(&new)
.with_stderr("[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]")
.run();
Avoid rebuilding a project when cwd changes This commit is targeted at solving a use case which typically comes up during CI builds -- the `target` directory is cached between builds but the cwd of the build changes over time. For example the following scenario can happen: 1. A project is compiled at `/projects/a`. 2. The `target` directory is cached. 3. A new build is started in `/projects/b`. 4. The previous `target` directory is restored to `/projects/b`. 5. The build start, and Cargo rebuilds everything. The last piece of behavior is indeed unfortunate! Cargo's internal hashing currently isn't that resilient to changing cwd and this PR aims to help improve the situation! The first point of too-much-hashing came up with `Target::src_path`. Each `Target` was hashed and stored for all compilations, and the `src_path` field was an absolute path on the filesystem to the file that needed to be compiled. This path then changed over time when cwd changed, but otherwise everything else remained the same! This commit updates the handling of the `src_path` field to simply ignore it when hashing. Instead the path we actually pass to rustc is later calculated and then passed to the fingerprint calculation. The next problem this fixes is that the dep info files were augmented after creation to have the cwd of the compiler at the time to find the files at a later date. This, unfortunately, would cause issues if the cwd itself changed. Instead the cwd is now left out of dep-info files (they're no longer augmented) and instead the cwd is recalculated when parsing the dep info later. The final problem that this commit fixes is actually an existing issue in Cargo today. Right now you can actually execute `cargo build` from anywhere in a project and Cargo will execute the build. Unfortunately though the argument to rustc was actually different depending on what directory you were in (the compiler was invoked with a path relative to cwd). This path ends up being used for metadata like debuginfo which means that different directories would cause different artifacts to be created, but Cargo wouldn't rerun the compiler! To fix this issue the matter of cwd is now entirely excluded from compilation command lines. Instead rustc is unconditionally invoked with a relative path *if* the path is underneath the workspace root, and otherwise it's invoked as an absolute path (in which case the cwd doesn't matter). Once all these fixes were added up it means that now we can have projects where if you move the entire directory Cargo won't rebuild the original source! Note that this may be a bit of a breaking change, however. This means that the paths in error messages for cargo will no longer be unconditionally relative to the current working directory, but rather relative to the root of the workspace itself. Unfortunately this is moreso of a feature right now rather than a bug, so it may be one that we just have to stomach.
2017-12-06 22:53:09 +00:00
}
#[test]
fn unused_optional_dep() {
Package::new("registry1", "0.1.0").publish();
Package::new("registry2", "0.1.0").publish();
Package::new("registry3", "0.1.0").publish();
let p = project()
.file(
"Cargo.toml",
r#"
[package]
name = "p"
authors = []
version = "0.1.0"
[dependencies]
bar = { path = "bar" }
baz = { path = "baz" }
registry1 = "*"
"#,
2018-12-08 11:19:47 +00:00
)
.file("src/lib.rs", "")
.file(
"bar/Cargo.toml",
r#"
[package]
name = "bar"
version = "0.1.1"
authors = []
[dev-dependencies]
registry2 = "*"
"#,
2018-12-08 11:19:47 +00:00
)
.file("bar/src/lib.rs", "")
.file(
"baz/Cargo.toml",
r#"
[package]
name = "baz"
version = "0.1.1"
authors = []
[dependencies]
registry3 = { version = "*", optional = true }
"#,
2018-12-08 11:19:47 +00:00
)
.file("baz/src/lib.rs", "")
.build();
p.cargo("build").run();
p.cargo("build").with_stderr("[FINISHED] [..]").run();
}
#[test]
fn path_dev_dep_registry_updates() {
Package::new("registry1", "0.1.0").publish();
Package::new("registry2", "0.1.0").publish();
let p = project()
.file(
"Cargo.toml",
r#"
[package]
name = "p"
authors = []
version = "0.1.0"
[dependencies]
bar = { path = "bar" }
"#,
2018-12-08 11:19:47 +00:00
)
.file("src/lib.rs", "")
.file(
"bar/Cargo.toml",
r#"
[package]
name = "bar"
version = "0.1.1"
authors = []
[dependencies]
registry1 = "*"
[dev-dependencies]
baz = { path = "../baz"}
"#,
2018-12-08 11:19:47 +00:00
)
.file("bar/src/lib.rs", "")
.file(
"baz/Cargo.toml",
r#"
[package]
name = "baz"
version = "0.1.1"
authors = []
[dependencies]
registry2 = "*"
"#,
2018-12-08 11:19:47 +00:00
)
.file("baz/src/lib.rs", "")
.build();
p.cargo("build").run();
p.cargo("build").with_stderr("[FINISHED] [..]").run();
}
#[test]
fn change_panic_mode() {
let p = project()
.file(
"Cargo.toml",
r#"
[workspace]
members = ['bar', 'baz']
[profile.dev]
panic = 'abort'
"#,
2018-12-08 11:19:47 +00:00
)
.file("src/lib.rs", "")
2018-07-24 22:35:01 +00:00
.file("bar/Cargo.toml", &basic_manifest("bar", "0.1.1"))
.file("bar/src/lib.rs", "")
.file(
"baz/Cargo.toml",
r#"
[package]
name = "baz"
version = "0.1.1"
authors = []
[lib]
proc-macro = true
[dependencies]
bar = { path = '../bar' }
"#,
2018-12-08 11:19:47 +00:00
)
.file("baz/src/lib.rs", "extern crate bar;")
.build();
p.cargo("build -p bar").run();
p.cargo("build -p baz").run();
}
#[test]
fn dont_rebuild_based_on_plugins() {
let p = project()
.file(
"Cargo.toml",
r#"
[package]
name = "bar"
version = "0.1.1"
[workspace]
members = ['baz']
[dependencies]
proc-macro-thing = { path = 'proc-macro-thing' }
"#,
2018-12-08 11:19:47 +00:00
)
.file("src/lib.rs", "")
.file(
"proc-macro-thing/Cargo.toml",
r#"
[package]
name = "proc-macro-thing"
version = "0.1.1"
[lib]
proc-macro = true
[dependencies]
qux = { path = '../qux' }
"#,
2018-12-08 11:19:47 +00:00
)
.file("proc-macro-thing/src/lib.rs", "")
.file(
"baz/Cargo.toml",
r#"
[package]
name = "baz"
version = "0.1.1"
[dependencies]
qux = { path = '../qux' }
"#,
2018-12-08 11:19:47 +00:00
)
.file("baz/src/main.rs", "fn main() {}")
2018-07-24 22:35:01 +00:00
.file("qux/Cargo.toml", &basic_manifest("qux", "0.1.1"))
.file("qux/src/lib.rs", "")
.build();
p.cargo("build").run();
p.cargo("build -p baz").run();
p.cargo("build").with_stderr("[FINISHED] [..]\n").run();
p.cargo("build -p bar")
.with_stderr("[FINISHED] [..]\n")
.run();
}
#[test]
fn reuse_workspace_lib() {
let p = project()
.file(
"Cargo.toml",
r#"
[package]
name = "bar"
version = "0.1.1"
[workspace]
[dependencies]
baz = { path = 'baz' }
"#,
2018-12-08 11:19:47 +00:00
)
.file("src/lib.rs", "")
2018-07-24 22:35:01 +00:00
.file("baz/Cargo.toml", &basic_manifest("baz", "0.1.1"))
.file("baz/src/lib.rs", "")
.build();
p.cargo("build").run();
p.cargo("test -p baz -v --no-run")
.with_stderr(
"\
[COMPILING] baz v0.1.1 ([..])
[RUNNING] `rustc[..] --test [..]`
[FINISHED] [..]
",
2018-12-08 11:19:47 +00:00
)
.run();
}
2018-10-12 19:55:31 +00:00
#[test]
fn reuse_shared_build_dep() {
let p = project()
.file(
"Cargo.toml",
r#"
[package]
name = "foo"
version = "0.0.1"
[dependencies]
shared = {path = "shared"}
[workspace]
members = ["shared", "bar"]
"#,
)
.file("src/main.rs", "fn main() {}")
.file("shared/Cargo.toml", &basic_manifest("shared", "0.0.1"))
.file("shared/src/lib.rs", "")
.file(
"bar/Cargo.toml",
r#"
[package]
name = "bar"
version = "0.0.1"
[build-dependencies]
shared = { path = "../shared" }
"#,
)
.file("bar/src/lib.rs", "")
.file("bar/build.rs", "fn main() {}")
.build();
p.cargo("build --all").run();
// This should not recompile!
p.cargo("build -p foo -v")
.with_stderr(
"\
[FRESH] shared [..]
[FRESH] foo [..]
[FINISHED] [..]
",
)
.run();
}
#[test]
fn reuse_panic_build_dep_test() {
let p = project()
.file(
"Cargo.toml",
r#"
[package]
name = "foo"
version = "0.0.1"
[build-dependencies]
bar = { path = "bar" }
[dev-dependencies]
bar = { path = "bar" }
[profile.dev]
panic = "abort"
"#,
)
.file("src/lib.rs", "")
.file("build.rs", "fn main() {}")
.file("bar/Cargo.toml", &basic_manifest("bar", "0.0.1"))
.file("bar/src/lib.rs", "")
.build();
// Check that `bar` is not built twice. It is only needed once (without `panic`).
p.cargo("test --lib --no-run -v")
.with_stderr(
"\
[COMPILING] bar [..]
[RUNNING] `rustc --crate-name bar [..]
[COMPILING] foo [..]
[RUNNING] `rustc --crate-name build_script_build [..]
[RUNNING] [..]build-script-build`
[RUNNING] `rustc --crate-name foo src/lib.rs [..]--test[..]
[FINISHED] [..]
",
)
.run();
}
#[test]
fn reuse_panic_pm() {
// foo(panic) -> bar(panic)
// somepm(nopanic) -> bar(nopanic)
let p = project()
.file(
"Cargo.toml",
r#"
[package]
name = "foo"
version = "0.0.1"
[dependencies]
bar = { path = "bar" }
somepm = { path = "somepm" }
[profile.dev]
panic = "abort"
"#,
)
.file("src/lib.rs", "extern crate bar;")
.file("bar/Cargo.toml", &basic_manifest("bar", "0.0.1"))
.file("bar/src/lib.rs", "")
.file(
"somepm/Cargo.toml",
r#"
[package]
name = "somepm"
version = "0.0.1"
[lib]
proc-macro = true
[dependencies]
bar = { path = "../bar" }
"#,
)
.file("somepm/src/lib.rs", "extern crate bar;")
.build();
// bar is built once without panic (for proc-macro) and once with (for the
// normal dependency).
p.cargo("build -v")
.with_stderr_unordered(
"\
[COMPILING] bar [..]
[RUNNING] `rustc --crate-name bar bar/src/lib.rs [..]--crate-type lib --emit=dep-info,link -C debuginfo=2 [..]
[RUNNING] `rustc --crate-name bar bar/src/lib.rs [..]--crate-type lib --emit=dep-info,link -C panic=abort -C debuginfo=2 [..]
[COMPILING] somepm [..]
[RUNNING] `rustc --crate-name somepm [..]
[COMPILING] foo [..]
[RUNNING] `rustc --crate-name foo src/lib.rs [..]-C panic=abort[..]
[FINISHED] [..]
",
)
.run();
}