// unit has never been compiled!
LocalFingerprint::CheckDepInfo { dep_info } => {
let dep_info = target_root.join(dep_info);
- if let Some(paths) = parse_dep_info(pkg_root, &dep_info)? {
+ if let Some(paths) = parse_dep_info(pkg_root, target_root, &dep_info)? {
Ok(find_stale_file(&dep_info, paths.iter()))
} else {
Ok(Some(StaleFile::Missing(dep_info)))
}
// Parse the dep-info into a list of paths
-pub fn parse_dep_info(pkg_root: &Path, dep_info: &Path) -> CargoResult<Option<Vec<PathBuf>>> {
+pub fn parse_dep_info(
+ pkg_root: &Path,
+ target_root: &Path,
+ dep_info: &Path,
+) -> CargoResult<Option<Vec<PathBuf>>> {
let data = match paths::read_bytes(dep_info) {
Ok(data) => data,
Err(_) => return Ok(None),
let paths = data
.split(|&x| x == 0)
.filter(|x| !x.is_empty())
- .map(|p| util::bytes2path(p).map(|p| pkg_root.join(p)))
+ .map(|p| {
+ let ty = match DepInfoPathType::from_byte(p[0]) {
+ Some(ty) => ty,
+ None => return Err(internal("dep-info invalid")),
+ };
+ let path = util::bytes2path(&p[1..])?;
+ match ty {
+ DepInfoPathType::PackageRootRelative => Ok(pkg_root.join(path)),
+ // N.B. path might be absolute here in which case the join will have no effect
+ DepInfoPathType::TargetRootRelative => Ok(target_root.join(path)),
+ }
+ })
.collect::<Result<Vec<_>, _>>()?;
if paths.is_empty() {
Ok(None)
format!("{}{}-{}", flavor, kind, file_stem)
}
+#[repr(u8)]
+enum DepInfoPathType {
+ // src/, e.g. src/lib.rs
+ PackageRootRelative = 1,
+ // target/debug/deps/lib...
+ // or an absolute path /.../sysroot/...
+ TargetRootRelative = 2,
+}
+
+impl DepInfoPathType {
+ fn from_byte(b: u8) -> Option<DepInfoPathType> {
+ match b {
+ 1 => Some(DepInfoPathType::PackageRootRelative),
+ 2 => Some(DepInfoPathType::TargetRootRelative),
+ _ => None,
+ }
+ }
+}
+
/// Parses the dep-info file coming out of rustc into a Cargo-specific format.
///
/// This function will parse `rustc_dep_info` as a makefile-style dep info to
pub fn translate_dep_info(
rustc_dep_info: &Path,
cargo_dep_info: &Path,
- pkg_root: &Path,
rustc_cwd: &Path,
+ pkg_root: &Path,
+ target_root: &Path,
) -> CargoResult<()> {
let target = parse_rustc_dep_info(rustc_dep_info)?;
let deps = &target
let mut new_contents = Vec::new();
for file in deps {
- let absolute = rustc_cwd.join(file);
- let path = absolute.strip_prefix(pkg_root).unwrap_or(&absolute);
- new_contents.extend(util::path2bytes(path)?);
+ let file = rustc_cwd.join(file);
+ let (ty, path) = if let Ok(stripped) = file.strip_prefix(pkg_root) {
+ (DepInfoPathType::PackageRootRelative, stripped)
+ } else if let Ok(stripped) = file.strip_prefix(target_root) {
+ (DepInfoPathType::TargetRootRelative, stripped)
+ } else {
+ // It's definitely not target root relative, but this is an absolute path (since it was
+ // joined to rustc_cwd) and as such re-joining it later to the target root will have no
+ // effect.
+ assert!(file.is_absolute(), "{:?} is absolute", file);
+ (DepInfoPathType::TargetRootRelative, &*file)
+ };
+ new_contents.push(ty as u8);
+ new_contents.extend(util::path2bytes(&path)?);
new_contents.push(0);
}
paths::write(cargo_dep_info, &new_contents)?;
.with_stderr("[FINISHED] [..]")
.run();
}
+
+#[cargo_test]
+fn move_target_directory_with_path_deps() {
+ let p = project()
+ .file(
+ "Cargo.toml",
+ r#"
+ [project]
+ name = "foo"
+ version = "0.5.0"
+ authors = []
+
+ [dependencies]
+ a = { path = "a" }
+ "#,
+ )
+ .file(
+ "a/Cargo.toml",
+ r#"
+ [project]
+ name = "a"
+ version = "0.5.0"
+ authors = []
+ "#,
+ )
+ .file("src/lib.rs", "extern crate a; pub use a::print_msg;")
+ .file(
+ "a/build.rs",
+ r###"
+ use std::env;
+ use std::fs;
+ use std::path::Path;
+
+ fn main() {
+ println!("cargo:rerun-if-changed=build.rs");
+ let out_dir = env::var("OUT_DIR").unwrap();
+ let dest_path = Path::new(&out_dir).join("hello.rs");
+ fs::write(&dest_path, r#"
+ pub fn message() -> &'static str {
+ "Hello, World!"
+ }
+ "#).unwrap();
+ }
+ "###,
+ )
+ .file(
+ "a/src/lib.rs",
+ r#"
+ include!(concat!(env!("OUT_DIR"), "/hello.rs"));
+ pub fn print_msg() { message(); }
+ "#,
+ );
+ let p = p.build();
+
+ let mut parent = p.root();
+ parent.pop();
+
+ p.cargo("build").run();
+
+ let new_target = p.root().join("target2");
+ fs::rename(p.root().join("target"), &new_target).unwrap();
+
+ p.cargo("build")
+ .env("CARGO_TARGET_DIR", &new_target)
+ .with_stderr("[FINISHED] [..]")
+ .run();
+}