From 15c8b51d65885e4fdc51df96aa10398a26192bf8 Mon Sep 17 00:00:00 2001 From: Andy Polyakov Date: Wed, 1 Jun 2022 17:02:45 +0200 Subject: [PATCH 1/3] Map source absolute paths to OUT_DIR as relative. If a source file was specified by absolute path, then the corresponding object file was placed into OUT_DIR. This posed a problem if multiple files with the same base name were specified by absolute paths. Fixes #683. --- src/lib.rs | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index 2e9a4501a..e8205f97e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1023,7 +1023,26 @@ impl Build { let mut objects = Vec::new(); for file in self.files.iter() { - let obj = dst.join(file).with_extension("o"); + let obj = if file.has_root() { + // If `file` is an absolute path, try to remove the part + // common with the destination directory, and graft the + // remaining part. Most common outcome would be removal + // of the home directory, next common - removal of the root + // directory. + let mut pre = dst.components(); + let mut dst = dst.clone(); + for comp in file.components() { + if comp != pre.next().unwrap_or(Component::CurDir) { + match comp { + Component::Normal(c) => dst.push(c), + _ => (), + }; + } + } + dst.with_extension("o") + } else { + dst.join(file).with_extension("o") + }; let obj = if !obj.starts_with(&dst) { dst.join(obj.file_name().ok_or_else(|| { Error::new(ErrorKind::IOError, "Getting object file details failed.") From 434f3db3722d96d8c9716b81d2c15a3fcb78506f Mon Sep 17 00:00:00 2001 From: Andy Polyakov Date: Fri, 22 Jul 2022 22:30:11 +0200 Subject: [PATCH 2/3] Prefix absolute file names with directory hashes to ensure name uniqueness. --- src/lib.rs | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index e8205f97e..d59f8f4e7 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -56,11 +56,12 @@ #![allow(deprecated)] #![deny(missing_docs)] -use std::collections::HashMap; +use std::collections::{hash_map, HashMap}; use std::env; use std::ffi::{OsStr, OsString}; use std::fmt::{self, Display, Formatter}; use std::fs; +use std::hash::Hasher; use std::io::{self, BufRead, BufReader, Read, Write}; use std::path::{Component, Path, PathBuf}; use std::process::{Child, Command, Stdio}; @@ -1039,6 +1040,21 @@ impl Build { }; } } + // ... and prefix the `basename` with the `dirname`'s hash + // to ensure name uniqueness. + let basename = file + .file_name() + .ok_or_else(|| Error::new(ErrorKind::InvalidArgument, "file_name() failure"))? + .to_string_lossy(); + let dirname = file + .parent() + .ok_or_else(|| Error::new(ErrorKind::InvalidArgument, "parent() failure"))? + .to_string_lossy(); + let mut hasher = hash_map::DefaultHasher::new(); + hasher.write(dirname.to_string().as_bytes()); + if dst.pop() { + dst.push(format!("{:016x}-{}", hasher.finish(), basename)); + } dst.with_extension("o") } else { dst.join(file).with_extension("o") From 36137ae5ff2a19d358ae629806024474b2169a5b Mon Sep 17 00:00:00 2001 From: Andy Polyakov Date: Tue, 26 Jul 2022 21:27:41 +0200 Subject: [PATCH 3/3] Don't graft subdirectories, rely solely on source directory hashes. --- src/lib.rs | 25 ++++--------------------- 1 file changed, 4 insertions(+), 21 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index d59f8f4e7..fa899df01 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1025,23 +1025,8 @@ impl Build { let mut objects = Vec::new(); for file in self.files.iter() { let obj = if file.has_root() { - // If `file` is an absolute path, try to remove the part - // common with the destination directory, and graft the - // remaining part. Most common outcome would be removal - // of the home directory, next common - removal of the root - // directory. - let mut pre = dst.components(); - let mut dst = dst.clone(); - for comp in file.components() { - if comp != pre.next().unwrap_or(Component::CurDir) { - match comp { - Component::Normal(c) => dst.push(c), - _ => (), - }; - } - } - // ... and prefix the `basename` with the `dirname`'s hash - // to ensure name uniqueness. + // If `file` is an absolute path, prefix the `basename` + // with the `dirname`'s hash to ensure name uniqueness. let basename = file .file_name() .ok_or_else(|| Error::new(ErrorKind::InvalidArgument, "file_name() failure"))? @@ -1052,10 +1037,8 @@ impl Build { .to_string_lossy(); let mut hasher = hash_map::DefaultHasher::new(); hasher.write(dirname.to_string().as_bytes()); - if dst.pop() { - dst.push(format!("{:016x}-{}", hasher.finish(), basename)); - } - dst.with_extension("o") + dst.join(format!("{:016x}-{}", hasher.finish(), basename)) + .with_extension("o") } else { dst.join(file).with_extension("o") };