From: bors Date: Wed, 9 Aug 2017 14:10:12 +0000 (+0000) Subject: Auto merge of #3611 - tylerwhall:stable-metadata, r=alexcrichton X-Git-Tag: archive/raspbian/0.35.0-2+rpi1~3^2^2^2^2^2^2^2~22^2~7^2~25 X-Git-Url: https://dgit.raspbian.org/?a=commitdiff_plain;h=d2e8587dc459d79045675ce721c3ef06220d7c67;p=cargo.git Auto merge of #3611 - tylerwhall:stable-metadata, r=alexcrichton Stable metadata hashes across workspaces Currently a crate from a path source will have its metadata hash incorporate its absolute path on the system where it is built. This always impacts top-level crates, which means that compiling the same source with the same dependencies and compiler version will generate libraries with symbol names that vary depending on where the workspace resides on the machine. This is hopefully a general solution to the hack we've used in meta-rust to make dynamic linking reliable. meta-rust/meta-rust@0e6cf94 For paths inside the Cargo workspace, hash their SourceId relative to the root of the workspace. Paths outside of a workspace are still hashed as absolute. This stability is important for reproducible builds as part of a larger build system that employs caching of artifacts, such as OpenEmbedded. OpenEmbedded tightly controls all inputs to a build and its caching assumes that an equivalent artifact will always result from the same set of inputs. The workspace path is not considered to be an influential input, however. For example, if Cargo is used to compile libstd shared objects which downstream crates link to dynamically, it must be possible to rebuild libstd given the same inputs and produce a library that is at least link-compatible with the original. If the build system happens to cache the downstream crates but needs to rebuild libstd and the user happens to be building in a different workspace path, currently Cargo will generate a library incompatible with the original and the downstream executables will fail at runtime on the target. --- d2e8587dc459d79045675ce721c3ef06220d7c67 diff --cc src/cargo/ops/cargo_rustc/context.rs index bec1fd930,b42247293..5b67830e7 mode 100755,100644..100755 --- a/src/cargo/ops/cargo_rustc/context.rs +++ b/src/cargo/ops/cargo_rustc/context.rs diff --cc tests/build.rs index 2f82def40,f096b8fbd..a673c1fe7 --- a/tests/build.rs +++ b/tests/build.rs @@@ -3449,73 -3270,34 +3450,102 @@@ fn no_bin_in_src_with_lib() assert_that(p.cargo_process("build"), execs().with_status(101) - .with_stderr_contains(r#"[ERROR] couldn't read "[..]main.rs"[..]"#)); + .with_stderr_contains("\ +[ERROR] failed to parse manifest at `[..]` + +Caused by: + can't find `foo` bin, specify bin.path")); +} + + +#[test] +fn dirs_in_bin_dir_with_main_rs() { + let p = project("foo") + .file("Cargo.toml", r#" + [package] + name = "foo" + version = "0.1.0" + authors = [] + "#) + .file("src/main.rs", "fn main() {}") + .file("src/bin/bar.rs", "fn main() {}") + .file("src/bin/bar2.rs", "fn main() {}") + .file("src/bin/bar3/main.rs", "fn main() {}") + .file("src/bin/bar4/main.rs", "fn main() {}"); + + assert_that(p.cargo_process("build"), execs().with_status(0)); + assert_that(&p.bin("foo"), existing_file()); + assert_that(&p.bin("bar"), existing_file()); + assert_that(&p.bin("bar2"), existing_file()); + assert_that(&p.bin("bar3"), existing_file()); + assert_that(&p.bin("bar4"), existing_file()); +} + +#[test] +fn dir_and_file_with_same_name_in_bin() { + // this should fail, because we have two binaries with the same name + let p = project("bar") + .file("Cargo.toml", r#" + [package] + name = "bar" + version = "0.1.0" + authors = [] + "#) + .file("src/main.rs", "fn main() {}") + .file("src/bin/foo.rs", "fn main() {}") + .file("src/bin/foo/main.rs", "fn main() {}"); + + assert_that(p.cargo_process("build"), + execs().with_status(101) + .with_stderr_contains("\ +[..]found duplicate binary name foo, but all binary targets must have a unique name[..] +")); +} + +#[test] +fn inferred_path_in_src_bin_foo() { + let p = project("foo") + .file("Cargo.toml", r#" + [package] + name = "foo" + version = "0.1.0" + authors = [] + + [[bin]] + name = "bar" + # Note, no `path` key! + "#) + .file("src/bin/bar/main.rs", "fn main() {}"); + + assert_that(p.cargo_process("build"), execs().with_status(0)); + assert_that(&p.bin("bar"), existing_file()); } + + #[test] + fn same_metadata_different_directory() { + // A top-level crate built in two different workspaces should have the + // same metadata hash. + let p = project("foo1") + .file("Cargo.toml", &basic_bin_manifest("foo")) + .file("src/foo.rs", &main_file(r#""i am foo""#, &[])); + let output = t!(String::from_utf8( + t!(p.cargo_process("build").arg("-v").exec_with_output()) + .stderr, + )); + let metadata = output + .split_whitespace() + .filter(|arg| arg.starts_with("metadata=")) + .next() + .unwrap(); + + let p = project("foo2") + .file("Cargo.toml", &basic_bin_manifest("foo")) + .file("src/foo.rs", &main_file(r#""i am foo""#, &[])); + + assert_that( + p.cargo_process("build").arg("-v"), + execs().with_status(0).with_stderr_contains( + format!("[..]{}[..]", metadata), + ), + ); + }