@@ -51,6 +51,11 @@ class CompileJobCache::CachingOutputs {
51
51
52
52
void stopDiagnosticsCapture ();
53
53
54
+ // / This is for an output file that was written directly on the file system.
55
+ // / It's a workaround until all compilation consumers adopt
56
+ // / \c llvm::vfs::OutputBackend.
57
+ virtual Error addNonVirtualOutputFile (StringRef FilePath) = 0;
58
+
54
59
// / Finish writing outputs from a computed result, after a cache miss.
55
60
// / If SkipCache is true, it should not insert the ResultCacheKey into
56
61
// / Cache for future uses.
@@ -105,6 +110,8 @@ class ObjectStoreCachingOutputs : public CompileJobCache::CachingOutputs {
105
110
106
111
bool prepareOutputCollection () override ;
107
112
113
+ Error addNonVirtualOutputFile (StringRef FilePath) override ;
114
+
108
115
Error finishComputedResult (const llvm::cas::CASID &ResultCacheKey,
109
116
bool SkipCache) override ;
110
117
@@ -143,6 +150,11 @@ class CollectingOutputBackend : public llvm::vfs::ProxyOutputBackend {
143
150
KindMaps.push_back ({Saver.save (Kind), Saver.save (Path)});
144
151
}
145
152
153
+ void addOutput (StringRef Path) {
154
+ StringRef Name = tryRemapPath (Path);
155
+ OutputNames.push_back (Name.str ());
156
+ }
157
+
146
158
private:
147
159
llvm::BumpPtrAllocator Alloc;
148
160
llvm::StringSaver Saver{Alloc};
@@ -166,8 +178,7 @@ class CollectingOutputBackend : public llvm::vfs::ProxyOutputBackend {
166
178
Expected<std::unique_ptr<llvm::vfs::OutputFileImpl>>
167
179
createFileImpl (StringRef Path,
168
180
std::optional<llvm::vfs::OutputConfig> Config) override {
169
- StringRef Name = tryRemapPath (Path);
170
- OutputNames.push_back (Name.str ());
181
+ addOutput (Path);
171
182
return ProxyOutputBackend::createFileImpl (Path, std::move (Config));
172
183
}
173
184
@@ -198,6 +209,8 @@ class RemoteCachingOutputs : public CompileJobCache::CachingOutputs {
198
209
199
210
bool prepareOutputCollection () override ;
200
211
212
+ Error addNonVirtualOutputFile (StringRef FilePath) override ;
213
+
201
214
Error finishComputedResult (const llvm::cas::CASID &ResultCacheKey,
202
215
bool SkipCache) override ;
203
216
@@ -514,9 +527,18 @@ bool CompileJobCache::finishComputedResult(CompilerInstance &Clang,
514
527
515
528
DiagnosticsEngine &Diags = Clang.getDiagnostics ();
516
529
530
+ bool UnsupportedOutput;
531
+ if (Error E = maybeIngestNonVirtualOutputFromFileSystem (Clang).moveInto (
532
+ UnsupportedOutput)) {
533
+ reportCachingBackendError (Diags, std::move (E));
534
+ return false ;
535
+ }
536
+
517
537
// Check if we encounter any source that would generate non-reproducible
518
538
// outputs.
519
- bool SkipCache = Clang.hasPreprocessor () && Clang.isSourceNonReproducible ();
539
+ bool SkipCache =
540
+ (Clang.hasPreprocessor () && Clang.isSourceNonReproducible ()) ||
541
+ UnsupportedOutput;
520
542
if (SkipCache) {
521
543
switch (Clang.getPreprocessorOpts ().CachingDiagOption ) {
522
544
case CachingDiagKind::None:
@@ -538,6 +560,31 @@ bool CompileJobCache::finishComputedResult(CompilerInstance &Clang,
538
560
return true ;
539
561
}
540
562
563
+ Expected<bool > CompileJobCache::maybeIngestNonVirtualOutputFromFileSystem (
564
+ CompilerInstance &Clang) {
565
+ // FIXME: All consumers should adopt \c llvm::vfs::OutputBackend and this
566
+ // function should go away.
567
+
568
+ const auto &FrontendOpts = Clang.getFrontendOpts ();
569
+ if (FrontendOpts.ProgramAction == frontend::RunAnalysis) {
570
+ StringRef OutputPath = FrontendOpts.OutputFile ;
571
+ if (OutputPath.empty ())
572
+ return false ;
573
+ if (llvm::sys::fs::is_directory (OutputPath)) {
574
+ // FIXME: A directory is produced for the 'html' output of the analyzer,
575
+ // support it for caching purposes.
576
+ Clang.getDiagnostics ().Report (diag::warn_clang_cache_disabled_caching)
577
+ << " analyzer output is not supported" ;
578
+ return true ;
579
+ }
580
+ if (Error E = CacheBackend->addNonVirtualOutputFile (OutputPath))
581
+ return std::move (E);
582
+ return false ;
583
+ }
584
+
585
+ return false ;
586
+ }
587
+
541
588
Expected<std::optional<int >> CompileJobCache::replayCachedResult (
542
589
std::shared_ptr<CompilerInvocation> Invok, StringRef WorkingDir,
543
590
const llvm::cas::CASID &CacheKey, cas::CompileJobCacheResult &CachedResult,
@@ -633,6 +680,20 @@ Expected<llvm::cas::ObjectRef> ObjectStoreCachingOutputs::writeOutputs(
633
680
return CachedResultBuilder.build (*CAS);
634
681
}
635
682
683
+ Error ObjectStoreCachingOutputs::addNonVirtualOutputFile (StringRef FilePath) {
684
+ auto F = llvm::sys::fs::openNativeFileForRead (FilePath);
685
+ if (!F)
686
+ return F.takeError ();
687
+ auto CloseOnExit =
688
+ llvm::make_scope_exit ([&F]() { llvm::sys::fs::closeFile (*F); });
689
+
690
+ std::optional<llvm::cas::ObjectRef> ObjRef;
691
+ if (Error E = CAS->storeFromOpenFile (*F).moveInto (ObjRef))
692
+ return E;
693
+ CASOutputs->addObject (FilePath, *ObjRef);
694
+ return Error::success ();
695
+ }
696
+
636
697
Error ObjectStoreCachingOutputs::finishComputedResult (
637
698
const llvm::cas::CASID &ResultCacheKey, bool SkipCache) {
638
699
Expected<llvm::cas::ObjectRef> Result = writeOutputs (ResultCacheKey);
@@ -1017,6 +1078,11 @@ RemoteCachingOutputs::saveOutputs(const llvm::cas::CASID &ResultCacheKey) {
1017
1078
return std::move (CompResult);
1018
1079
}
1019
1080
1081
+ Error RemoteCachingOutputs::addNonVirtualOutputFile (StringRef FilePath) {
1082
+ CollectingOutputs->addOutput (FilePath);
1083
+ return Error::success ();
1084
+ }
1085
+
1020
1086
Error RemoteCachingOutputs::finishComputedResult (
1021
1087
const llvm::cas::CASID &ResultCacheKey, bool SkipCache) {
1022
1088
if (SkipCache)
0 commit comments