@@ -97,7 +97,8 @@ ModuleDepCollector::makeInvocationForModuleBuildWithoutOutputs(
97
97
// differ between identical modules discovered from different translation
98
98
// units.
99
99
CI.getFrontendOpts ().Inputs .clear ();
100
- CI.getFrontendOpts ().OutputFile .clear ();
100
+ // CAS: OutputFile cannot be empty when computing a cache key.
101
+ CI.getFrontendOpts ().OutputFile = " -" ;
101
102
// FIXME: a build system may want to provide a new path.
102
103
CI.getFrontendOpts ().IndexUnitOutputPath .clear ();
103
104
@@ -117,7 +118,9 @@ ModuleDepCollector::makeInvocationForModuleBuildWithoutOutputs(
117
118
CI.getDiagnosticOpts ().DiagnosticSerializationFile = " -" ;
118
119
if (!CI.getDependencyOutputOpts ().OutputFile .empty ())
119
120
CI.getDependencyOutputOpts ().OutputFile = " -" ;
120
- CI.getDependencyOutputOpts ().Targets .clear ();
121
+ // CAS: -MT must be preserved for cache key.
122
+ if (!CI.getDependencyOutputOpts ().Targets .empty ())
123
+ CI.getDependencyOutputOpts ().Targets = {" -" };
121
124
122
125
CI.getFrontendOpts ().ProgramAction = frontend::GenerateModule;
123
126
CI.getLangOpts ()->ModuleName = Deps.ID .ModuleName ;
@@ -285,6 +288,22 @@ static std::string getModuleContextHash(const ModuleDeps &MD,
285
288
HashBuilder;
286
289
SmallString<32 > Scratch;
287
290
291
+ auto FormatHash = [&](llvm::BLAKE3Result<16 > Hash) {
292
+ std::array<uint64_t , 2 > Words;
293
+ static_assert (sizeof (Hash) == sizeof (Words), " Hash must match Words" );
294
+ std::memcpy (Words.data (), Hash.data (), sizeof (Hash));
295
+ return toString (llvm::APInt (sizeof (Words) * 8 , Words), 36 ,
296
+ /* Signed=*/ false );
297
+ };
298
+
299
+ if (MD.ModuleCacheKey ) {
300
+ // Cache keys have better canonicalization, so use them as the context hash.
301
+ // This reduces the number of modules needed when compatible configurations
302
+ // are used (e.g. change in -fmessage-length).
303
+ HashBuilder.add (*MD.ModuleCacheKey );
304
+ return FormatHash (HashBuilder.final ());
305
+ }
306
+
288
307
// Hash the compiler version and serialization version to ensure the module
289
308
// will be readable.
290
309
HashBuilder.add (getClangFullRepositoryVersion ());
@@ -320,13 +339,30 @@ static std::string getModuleContextHash(const ModuleDeps &MD,
320
339
}
321
340
322
341
HashBuilder.add (EagerLoadModules);
342
+ return FormatHash (HashBuilder.final ());
343
+ }
323
344
324
- llvm::BLAKE3Result<16 > Hash = HashBuilder.final ();
325
- std::array<uint64_t , 2 > Words;
326
- static_assert (sizeof (Hash) == sizeof (Words), " Hash must match Words" );
327
- std::memcpy (Words.data (), Hash.data (), sizeof (Hash));
328
- return toString (llvm::APInt (sizeof (Words) * 8 , Words), 36 , /* Signed=*/ false );
345
+ #ifndef NDEBUG
346
+ static void checkCompileCacheKeyMatch (cas::ObjectStore &CAS,
347
+ StringRef OldKeyStr, cas::CASID NewKey) {
348
+ if (NewKey.toString () == OldKeyStr)
349
+ return ;
350
+
351
+ // Mismatched keys, report error.
352
+ auto OldKey = CAS.parseID (OldKeyStr);
353
+ if (!OldKey)
354
+ llvm::report_fatal_error (OldKey.takeError ());
355
+ SmallString<256 > Err;
356
+ llvm::raw_svector_ostream OS (Err);
357
+ OS << " Compile cache key for module changed; previously:" ;
358
+ if (auto E = printCompileJobCacheKey (CAS, *OldKey, OS))
359
+ OS << std::move (E);
360
+ OS << " \n key is now:" ;
361
+ if (auto E = printCompileJobCacheKey (CAS, NewKey, OS))
362
+ OS << std::move (E);
363
+ llvm::report_fatal_error (OS.str ());
329
364
}
365
+ #endif
330
366
331
367
void ModuleDepCollector::associateWithContextHash (const CompilerInvocation &CI,
332
368
ModuleDeps &Deps) {
@@ -521,17 +557,27 @@ ModuleDepCollectorPP::handleTopLevelModule(const Module *M) {
521
557
if (auto E = MDC.Controller .finalizeModuleInvocation (CI, MD))
522
558
Diags.Report (diag::err_cas_depscan_failed) << std::move (E);
523
559
560
+ // Compute the cache key, if needed. Requires dependencies.
561
+ if (MDC.ScanInstance .getFrontendOpts ().CacheCompileJob ) {
562
+ auto &CAS = MDC.ScanInstance .getOrCreateObjectStore ();
563
+ if (auto Key = createCompileJobCacheKey (CAS, Diags, CI))
564
+ MD.ModuleCacheKey = Key->toString ();
565
+ }
566
+
524
567
MDC.associateWithContextHash (CI, MD);
525
568
526
569
// Finish the compiler invocation. Requires dependencies and the context hash.
527
570
MDC.addOutputPaths (CI, MD);
528
571
529
- // Compute the cache key, if needed. Requires dependencies and outputs.
530
- if (MDC.ScanInstance .getFrontendOpts ().CacheCompileJob ) {
572
+ #ifndef NDEBUG
573
+ // Verify the key has not changed with final arguments.
574
+ if (MD.ModuleCacheKey ) {
531
575
auto &CAS = MDC.ScanInstance .getOrCreateObjectStore ();
532
- if (auto Key = createCompileJobCacheKey (CAS, Diags, CI))
533
- MD.ModuleCacheKey = Key->toString ();
576
+ auto Key = createCompileJobCacheKey (CAS, Diags, CI);
577
+ assert (Key);
578
+ checkCompileCacheKeyMatch (CAS, *MD.ModuleCacheKey , *Key);
534
579
}
580
+ #endif
535
581
536
582
MD.BuildArguments = CI.getCC1CommandLine ();
537
583
0 commit comments