Skip to content

Commit 100c577

Browse files
committed
Fix preprocessor cache mode with distributed builds
...and disable the workaround that disabled the former in case of the latter. Under the following conditions: - Build with preprocessor cache mode enabled - Distributed build - Preprocessor cache hit - Main cache miss the compile that was run as "fallback" after the cache miss did not have preprocessed sources passed to it since skipping the preprocessing step is the whole point of preprocessor cache mode. But local preprocessing is what enables distributed compilation. To fix this, when the problem occurs, recursively re-invoke get_cached_or_compile() with ForceRecache(*) so that the preprocessor cache hit is (mostly) ignored, which makes get_cached_or_compile() invoke the local preprocessing codepath, which yields code suitable for distributed compilation. (*) which also prevents further recursion
1 parent fa0e46d commit 100c577

2 files changed

Lines changed: 42 additions & 4 deletions

File tree

src/compiler/c.rs

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -401,8 +401,8 @@ where
401401
}
402402

403403
let use_preprocessor_cache_mode = {
404-
let can_use_preprocessor_cache_mode = !may_dist
405-
&& preprocessor_cache_mode_config.use_preprocessor_cache_mode
404+
let can_use_preprocessor_cache_mode =
405+
preprocessor_cache_mode_config.use_preprocessor_cache_mode
406406
&& !too_hard_for_preprocessor_cache_mode;
407407

408408
let mut use_preprocessor_cache_mode = can_use_preprocessor_cache_mode;
@@ -429,7 +429,6 @@ where
429429
use_preprocessor_cache_mode
430430
};
431431

432-
// Disable preprocessor cache when doing distributed compilation
433432
let mut preprocessor_key = if use_preprocessor_cache_mode {
434433
preprocessor_cache_entry_hash_key(
435434
&self.executable_digest,
@@ -492,7 +491,7 @@ where
492491
compilation: Box::new(CCompilation {
493492
parsed_args: self.parsed_args.to_owned(),
494493
#[cfg(feature = "dist-client")]
495-
preprocessed_input: vec![],
494+
preprocessed_input: PREPROCESSING_SKIPPED_COMPILE_POISON.to_vec(),
496495
executable: self.executable.to_owned(),
497496
compiler: self.compiler.to_owned(),
498497
cwd: cwd.to_owned(),
@@ -1143,6 +1142,12 @@ fn include_is_too_new(
11431142
false
11441143
}
11451144

1145+
// Used as "preprocessed code" when no preprocessing took place to immediately produce an error (which
1146+
// should never happen / be caught earlier though!). Previously, an empty u8 vector was used, which is
1147+
// unfortunately a valid C/C++ program and caused errors that only surfaced when linking.
1148+
#[cfg(feature = "dist-client")]
1149+
const PREPROCESSING_SKIPPED_COMPILE_POISON: &[u8] = b"([{SCCACHE -*-* INVALID_C_CPP_CODE([{\"";
1150+
11461151
impl<T: CommandCreatorSync, I: CCompilerImpl> Compilation<T> for CCompilation<I> {
11471152
fn generate_compile_commands(
11481153
&self,
@@ -1194,6 +1199,11 @@ impl<T: CommandCreatorSync, I: CCompilerImpl> Compilation<T> for CCompilation<I>
11941199
Ok((inputs_packager, toolchain_packager, outputs_rewriter))
11951200
}
11961201

1202+
#[cfg(feature = "dist-client")]
1203+
fn is_preprocessed_for_distribution(&self) -> bool {
1204+
self.preprocessed_input != PREPROCESSING_SKIPPED_COMPILE_POISON
1205+
}
1206+
11971207
fn outputs<'a>(&'a self) -> Box<dyn Iterator<Item = FileObjectSource> + 'a> {
11981208
Box::new(
11991209
self.parsed_args

src/compiler/compiler.rs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -567,6 +567,29 @@ where
567567
// Cache miss, so compile it.
568568
let start = Instant::now();
569569

570+
#[cfg(feature = "dist-client")]
571+
if may_dist
572+
&& !compilation.is_preprocessed_for_distribution()
573+
&& cache_control == CacheControl::Default
574+
{
575+
// This compilation only had enough information to find and use a cache entry (or to
576+
// run a local compile, which doesn't need locally preprocessed code).
577+
// For distributed compilation, the local preprocessing step still needs to be done.
578+
return self
579+
.get_cached_or_compile(
580+
service,
581+
dist_client,
582+
creator,
583+
storage,
584+
arguments,
585+
cwd,
586+
env_vars,
587+
CacheControl::ForceRecache,
588+
pool,
589+
)
590+
.await;
591+
}
592+
570593
let (cacheable, dist_type, compiler_result) = dist_or_local_compile(
571594
service,
572595
dist_client,
@@ -932,6 +955,11 @@ where
932955
_path_transformer: dist::PathTransformer,
933956
) -> Result<DistPackagers>;
934957

958+
#[cfg(feature = "dist-client")]
959+
fn is_preprocessed_for_distribution(&self) -> bool {
960+
true
961+
}
962+
935963
/// Returns an iterator over the results of this compilation.
936964
///
937965
/// Each item is a descriptive (and unique) name of the output paired with

0 commit comments

Comments
 (0)