in src/compiler/preprocessor_cache.rs [193:352]
fn result_matches(
digest: &str,
includes: &mut [IncludeEntry],
config: PreprocessorCacheModeConfig,
updated: &mut bool,
) -> bool {
for include in includes {
let path = Path::new(include.path.as_os_str());
let meta = match std::fs::symlink_metadata(path) {
Ok(meta) => {
if meta.len() != include.file_size {
return false;
}
meta
}
Err(e) => {
debug!(
"{} is in a preprocessor cache entry but can't be read ({})",
path.display(),
e
);
return false;
}
};
if config.file_stat_matches {
match (include.mtime, include.ctime) {
(Some(mtime), Some(ctime)) if config.use_ctime_for_stat => {
let mtime_matches = meta.modified().map(Into::into).ok() == Some(mtime);
let ctime_matches =
meta.ctime_or_creation().map(Into::into).ok() == Some(ctime);
if mtime_matches && ctime_matches {
trace!("mtime+ctime hit for {}", path.display());
continue;
} else {
trace!("mtime+ctime miss for {}", path.display());
}
}
(Some(mtime), None) => {
let mtime_matches = meta.modified().map(Into::into).ok() == Some(mtime);
if mtime_matches {
trace!("mtime hit for {}", path.display());
continue;
} else {
trace!("mtime miss for {}", path.display());
}
}
_ => { /* Nothing was recorded, fall back to contents comparison */ }
}
}
let file = match std::fs::File::open(path) {
Ok(file) => file,
Err(e) => {
debug!(
"{} is in a preprocessor cache entry but can't be opened ({})",
path.display(),
e
);
return false;
}
};
if config.ignore_time_macros {
match Digest::reader_sync(file) {
Ok(new_digest) => return include.digest == new_digest,
Err(e) => {
debug!(
"{} is in a preprocessor cache entry but can't be read ({})",
path.display(),
e
);
return false;
}
}
} else {
let (new_digest, finder): (String, _) = match Digest::reader_sync_time_macros(file)
{
Ok((new_digest, finder)) => (new_digest, finder),
Err(e) => {
debug!(
"{} is in a preprocessor cache entry but can't be read ({})",
path.display(),
e
);
return false;
}
};
if !finder.found_time_macros() && include.digest != new_digest {
return false;
}
if finder.found_time() {
// We don't know for sure that the program actually uses the __TIME__ macro,
// but we have to assume it anyway and hash the time stamp. However, that's
// not very useful since the chance that we get a cache hit later the same
// second should be quite slim... So, just signal back to the caller that
// __TIME__ has been found so that the preprocessor cache mode can be disabled.
debug!("Found __TIME__ in {}", path.display());
return false;
}
// __DATE__ or __TIMESTAMP__ found. We now make sure that the digest changes
// if the (potential) expansion of those macros changes by computing a new
// digest comprising the file digest and time information that represents the
// macro expansions.
let mut new_digest = Digest::new();
new_digest.update(digest.as_bytes());
if finder.found_date() {
debug!("found __DATE__ in {}", path.display());
new_digest.delimiter(b"date");
let date = chrono::Local::now().date_naive();
new_digest.update(&date.year().to_le_bytes());
new_digest.update(&date.month().to_le_bytes());
new_digest.update(&date.day().to_le_bytes());
// If the compiler has support for it, the expansion of __DATE__ will change
// according to the value of SOURCE_DATE_EPOCH. Note: We have to hash both
// SOURCE_DATE_EPOCH and the current date since we can't be sure that the
// compiler honors SOURCE_DATE_EPOCH.
if let Ok(source_date_epoch) = std::env::var("SOURCE_DATE_EPOCH") {
new_digest.update(source_date_epoch.as_bytes())
}
}
if finder.found_timestamp() {
debug!("found __TIMESTAMP__ in {}", path.display());
let meta = match std::fs::symlink_metadata(path) {
Ok(meta) => meta,
Err(e) => {
debug!(
"{} is in a preprocessor cache entry but can't be read ({})",
path.display(),
e
);
return false;
}
};
let mtime = match meta.modified() {
Ok(mtime) => mtime,
Err(_) => {
debug!(
"Couldn't get mtime of {} which contains __TIMESTAMP__",
path.display()
);
return false;
}
};
let mtime: chrono::DateTime<chrono::Local> = chrono::DateTime::from(mtime);
new_digest.delimiter(b"timestamp");
new_digest.update(&mtime.naive_local().and_utc().timestamp().to_le_bytes());
include.digest = new_digest.finish();
// Signal that the preprocessor cache entry has been updated and needs to be
// written to disk.
*updated = true;
}
}
}
true
}