From 4f9fe856a25ab29345b90e7725509e9ee38a37be Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Wed, 17 Apr 2024 14:19:41 +0200 Subject: Adding upstream version 1.69.0+dfsg1. Signed-off-by: Daniel Baumann --- vendor/cc/src/lib.rs | 95 ++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 77 insertions(+), 18 deletions(-) (limited to 'vendor/cc/src/lib.rs') diff --git a/vendor/cc/src/lib.rs b/vendor/cc/src/lib.rs index 486d67e0b..1ebd2cc7a 100644 --- a/vendor/cc/src/lib.rs +++ b/vendor/cc/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}; @@ -1023,7 +1024,24 @@ 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, 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()); + dst.join(format!("{:016x}-{}", hasher.finish(), basename)) + .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.") @@ -1339,12 +1357,14 @@ impl Build { } fn compile_object(&self, obj: &Object) -> Result<(), Error> { - let is_asm = is_asm(&obj.src); + let asm_ext = AsmFileExt::from_path(&obj.src); + let is_asm = asm_ext.is_some(); let target = self.get_target()?; let msvc = target.contains("msvc"); let compiler = self.try_get_compiler()?; let clang = compiler.family == ToolFamily::Clang; - let (mut cmd, name) = if msvc && is_asm { + + let (mut cmd, name) = if msvc && asm_ext == Some(AsmFileExt::DotAsm) { self.msvc_macro_assembler()? } else { let mut cmd = compiler.to_command(); @@ -1367,7 +1387,7 @@ impl Build { if !msvc || !is_asm || !is_arm { cmd.arg("-c"); } - if self.cuda && self.files.len() > 1 { + if self.cuda && self.cuda_file_count() > 1 { cmd.arg("--device-c"); } if is_asm { @@ -1690,7 +1710,7 @@ impl Build { cmd.args.push("--target=aarch64-unknown-windows-gnu".into()) } } else { - cmd.args.push(format!("--target={}", target).into()); + cmd.push_cc_arg(format!("--target={}", target).into()); } } } @@ -2035,7 +2055,7 @@ impl Build { self.assemble_progressive(dst, chunk)?; } - if self.cuda { + if self.cuda && self.cuda_file_count() > 0 { // Link the device-side code and add it to the target library, // so that non-CUDA linker can link the final binary. @@ -2645,10 +2665,29 @@ impl Build { "emar".to_string() } else if target.contains("msvc") { - match windows_registry::find(&target, "lib.exe") { - Some(t) => return Ok((t, "lib.exe".to_string())), - None => "lib.exe".to_string(), + let compiler = self.get_base_compiler()?; + let mut lib = String::new(); + if compiler.family == (ToolFamily::Msvc { clang_cl: true }) { + // See if there is 'llvm-lib' next to 'clang-cl' + // Another possibility could be to see if there is 'clang' + // next to 'clang-cl' and use 'search_programs()' to locate + // 'llvm-lib'. This is because 'clang-cl' doesn't support + // the -print-search-dirs option. + if let Some(mut cmd) = which(&compiler.path) { + cmd.pop(); + cmd.push("llvm-lib.exe"); + if let Some(llvm_lib) = which(&cmd) { + lib = llvm_lib.to_str().unwrap().to_owned(); + } + } + } + if lib.is_empty() { + lib = match windows_registry::find(&target, "lib.exe") { + Some(t) => return Ok((t, "lib.exe".to_string())), + None => "lib.exe".to_string(), + } } + lib } else if target.contains("illumos") { // The default 'ar' on illumos uses a non-standard flags, // but the OS comes bundled with a GNU-compatible variant. @@ -3010,6 +3049,13 @@ impl Build { cache.insert(sdk.into(), ret.clone()); Ok(ret) } + + fn cuda_file_count(&self) -> usize { + self.files + .iter() + .filter(|file| file.extension() == Some(OsStr::new("cu"))) + .count() + } } impl Default for Build { @@ -3496,14 +3542,27 @@ fn which(tool: &Path) -> Option { }) } -/// Check if the file's extension is either "asm" or "s", case insensitive. -fn is_asm(file: &Path) -> bool { - if let Some(ext) = file.extension() { - if let Some(ext) = ext.to_str() { - let ext = ext.to_lowercase(); - return ext == "asm" || ext == "s"; +#[derive(Clone, Copy, PartialEq)] +enum AsmFileExt { + /// `.asm` files. On MSVC targets, we assume these should be passed to MASM + /// (`ml{,64}.exe`). + DotAsm, + /// `.s` or `.S` files, which do not have the special handling on MSVC targets. + DotS, +} + +impl AsmFileExt { + fn from_path(file: &Path) -> Option { + if let Some(ext) = file.extension() { + if let Some(ext) = ext.to_str() { + let ext = ext.to_lowercase(); + match &*ext { + "asm" => return Some(AsmFileExt::DotAsm), + "s" => return Some(AsmFileExt::DotS), + _ => return None, + } + } } + None } - - false } -- cgit v1.2.3