Skip to content

Commit 8ca426a

Browse files
committed
Fix caching of supported compiler flag
The cache needs to include compiler, since user can always changes the compiler by `Build::compiler` or by setting/changing environment variables. Signed-off-by: Jiahao XU <[email protected]>
1 parent 77a54a9 commit 8ca426a

File tree

1 file changed

+43
-20
lines changed

1 file changed

+43
-20
lines changed

src/lib.rs

Lines changed: 43 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,12 @@ use tool::ToolFamily;
249249

250250
mod target_info;
251251

252+
#[derive(Debug, Eq, PartialEq, Hash)]
253+
struct CompilerFlag {
254+
compiler: Box<Path>,
255+
flag: Box<str>,
256+
}
257+
252258
/// A builder for compilation of a native library.
253259
///
254260
/// A `Build` is the main type of the `cc` crate and is used to control all the
@@ -261,7 +267,7 @@ pub struct Build {
261267
objects: Vec<Arc<Path>>,
262268
flags: Vec<Arc<str>>,
263269
flags_supported: Vec<Arc<str>>,
264-
known_flag_support_status: Arc<Mutex<HashMap<String, bool>>>,
270+
known_flag_support_status_cache: Arc<Mutex<HashMap<CompilerFlag, bool>>>,
265271
ar_flags: Vec<Arc<str>>,
266272
asm_flags: Vec<Arc<str>>,
267273
no_default_flags: bool,
@@ -382,7 +388,7 @@ impl Build {
382388
objects: Vec::new(),
383389
flags: Vec::new(),
384390
flags_supported: Vec::new(),
385-
known_flag_support_status: Arc::new(Mutex::new(HashMap::new())),
391+
known_flag_support_status_cache: Arc::new(Mutex::new(HashMap::new())),
386392
ar_flags: Vec::new(),
387393
asm_flags: Vec::new(),
388394
no_default_flags: false,
@@ -592,29 +598,42 @@ impl Build {
592598
/// `known_flag_support` field. If `is_flag_supported(flag)`
593599
/// is called again, the result will be read from the hash table.
594600
pub fn is_flag_supported(&self, flag: &str) -> Result<bool, Error> {
595-
let mut known_status = self.known_flag_support_status.lock().unwrap();
596-
if let Some(is_supported) = known_status.get(flag).cloned() {
601+
let target = self.get_target()?;
602+
603+
let mut compiler = {
604+
let mut cfg = Build::new();
605+
cfg.flag(flag)
606+
.cargo_metadata(self.cargo_output.metadata)
607+
.target(&target)
608+
.opt_level(0)
609+
.host(&self.get_host()?)
610+
.debug(false)
611+
.cpp(self.cpp)
612+
.cuda(self.cuda);
613+
if let Some(ref c) = self.compiler {
614+
cfg.compiler(c.clone());
615+
}
616+
cfg.try_get_compiler()?
617+
};
618+
619+
let compiler_flag = CompilerFlag {
620+
compiler: compiler.path.clone().into(),
621+
flag: flag.into(),
622+
};
623+
624+
if let Some(is_supported) = self
625+
.known_flag_support_status_cache
626+
.lock()
627+
.unwrap()
628+
.get(&compiler_flag)
629+
.cloned()
630+
{
597631
return Ok(is_supported);
598632
}
599633

600634
let out_dir = self.get_out_dir()?;
601635
let src = self.ensure_check_file()?;
602636
let obj = out_dir.join("flag_check");
603-
let target = self.get_target()?;
604-
let host = self.get_host()?;
605-
let mut cfg = Build::new();
606-
cfg.flag(flag)
607-
.cargo_metadata(self.cargo_output.metadata)
608-
.target(&target)
609-
.opt_level(0)
610-
.host(&host)
611-
.debug(false)
612-
.cpp(self.cpp)
613-
.cuda(self.cuda);
614-
if let Some(ref c) = self.compiler {
615-
cfg.compiler(c.clone());
616-
}
617-
let mut compiler = cfg.try_get_compiler()?;
618637

619638
// Clang uses stderr for verbose output, which yields a false positive
620639
// result if the CFLAGS/CXXFLAGS include -v to aid in debugging.
@@ -650,7 +669,11 @@ impl Build {
650669
let output = cmd.output()?;
651670
let is_supported = output.status.success() && output.stderr.is_empty();
652671

653-
known_status.insert(flag.to_owned(), is_supported);
672+
self.known_flag_support_status_cache
673+
.lock()
674+
.unwrap()
675+
.insert(compiler_flag, is_supported);
676+
654677
Ok(is_supported)
655678
}
656679

0 commit comments

Comments
 (0)