28
28
#include " clang/Tooling/DependencyScanning/ScanAndUpdateArgs.h"
29
29
#include " llvm/ADT/ArrayRef.h"
30
30
#include " llvm/ADT/ScopeExit.h"
31
+ #include " llvm/ADT/SmallVector.h"
31
32
#include " llvm/ADT/Statistic.h"
32
33
#include " llvm/Bitstream/BitstreamReader.h"
33
34
#include " llvm/CAS/ActionCache.h"
35
+ #include " llvm/CAS/BuiltinUnifiedCASDatabases.h"
34
36
#include " llvm/CAS/CASProvidingFileSystem.h"
35
37
#include " llvm/CAS/CachingOnDiskFileSystem.h"
36
38
#include " llvm/CAS/HierarchicalTreeBuilder.h"
41
43
#include " llvm/Support/Compiler.h"
42
44
#include " llvm/Support/Error.h"
43
45
#include " llvm/Support/ErrorHandling.h"
46
+ #include " llvm/Support/FileSystem.h"
44
47
#include " llvm/Support/ManagedStatic.h"
45
48
#include " llvm/Support/Path.h"
46
49
#include " llvm/Support/PrefixMapper.h"
52
55
#include " llvm/Support/raw_ostream.h"
53
56
#include < cstdio>
54
57
#include < mutex>
58
+ #include < optional>
55
59
#include < shared_mutex>
56
60
57
61
#if LLVM_ON_UNIX
@@ -631,8 +635,8 @@ namespace {
631
635
struct ScanServer {
632
636
const char *Argv0 = nullptr ;
633
637
SmallString<128 > BasePath;
634
- // / List of cas options.
635
- ArrayRef< const char *> CASArgs ;
638
+ CASOptions CASOpts;
639
+ bool ProduceIncludeTree = true ;
636
640
int PidFD = -1 ;
637
641
int ListenSocket = -1 ;
638
642
// / \p std::nullopt means it runs indefinitely.
@@ -641,7 +645,7 @@ struct ScanServer {
641
645
642
646
~ScanServer () { shutdown (); }
643
647
644
- void start (bool Exclusive);
648
+ void start (bool Exclusive, ArrayRef< const char *> CASArgs );
645
649
int listen ();
646
650
647
651
// / Tear down the socket and bind file immediately but wait till all existing
@@ -706,13 +710,13 @@ int cc1depscand_main(ArrayRef<const char *> Argv, const char *Argv0,
706
710
// particular "build session", to shutdown, then have it stay alive until the
707
711
// session is finished.
708
712
bool LongRunning = false ;
709
-
713
+ ArrayRef< const char *> CASArgs;
710
714
for (const auto *A = Argv.begin () + 2 ; A != Argv.end (); ++A) {
711
715
StringRef Arg (*A);
712
716
if (Arg == " -long-running" )
713
717
LongRunning = true ;
714
718
else if (Arg == " -cas-args" ) {
715
- Server. CASArgs = ArrayRef (A + 1 , Argv.end ());
719
+ CASArgs = ArrayRef (A + 1 , Argv.end ());
716
720
break ;
717
721
}
718
722
}
@@ -723,7 +727,7 @@ int cc1depscand_main(ArrayRef<const char *> Argv, const char *Argv0,
723
727
reportError (Twine (" cannot create basedir: " ) + EC.message ());
724
728
725
729
if (Command == " -serve" ) {
726
- Server.start (/* Exclusive*/ true );
730
+ Server.start (/* Exclusive*/ true , CASArgs );
727
731
return Server.listen ();
728
732
729
733
} else if (Command == " -execute" ) {
@@ -734,7 +738,7 @@ int cc1depscand_main(ArrayRef<const char *> Argv, const char *Argv0,
734
738
}
735
739
736
740
// Make sure to start the server before executing the command.
737
- Server.start (/* Exclusive*/ true );
741
+ Server.start (/* Exclusive*/ true , CASArgs );
738
742
std::thread ServerThread ([&Server]() { Server.listen (); });
739
743
740
744
setenv (" CLANG_CACHE_SCAN_DAEMON_SOCKET_PATH" , Server.BasePath .c_str (),
@@ -785,11 +789,59 @@ int cc1depscand_main(ArrayRef<const char *> Argv, const char *Argv0,
785
789
openAndReplaceFD (1 , LogOutPath);
786
790
openAndReplaceFD (2 , LogErrPath);
787
791
788
- Server.start (/* Exclusive*/ false );
792
+ Server.start (/* Exclusive*/ false , CASArgs );
789
793
return Server.listen ();
790
794
}
791
795
792
- void ScanServer::start (bool Exclusive) {
796
+ static std::optional<StringRef>
797
+ findLLVMCasBinary (const char *Argv0, llvm::SmallVectorImpl<char > &Storage) {
798
+ using namespace llvm ::sys;
799
+ std::string Path = fs::getMainExecutable (Argv0, (void *)cc1depscan_main);
800
+ Storage.assign (Path.begin (), Path.end ());
801
+ path::remove_filename (Storage);
802
+ path::append (Storage, " llvm-cas" );
803
+ StringRef PathStr (Storage.data (), Storage.size ());
804
+ if (fs::exists (PathStr))
805
+ return PathStr;
806
+ // Look for a corresponding usr/local/bin/llvm-cas
807
+ PathStr = path::parent_path (PathStr);
808
+ if (path::filename (PathStr) != " bin" )
809
+ return std::nullopt;
810
+ PathStr = path::parent_path (PathStr);
811
+ Storage.truncate (PathStr.size ());
812
+ path::append (Storage, " local" , " bin" , " llvm-cas" );
813
+ PathStr = StringRef{Storage.data (), Storage.size ()};
814
+ if (fs::exists (PathStr))
815
+ return PathStr;
816
+ return std::nullopt;
817
+ }
818
+
819
+ void ScanServer::start (bool Exclusive, ArrayRef<const char *> CASArgs) {
820
+ // Parse CAS options and validate if needed.
821
+ DiagnosticsEngine Diags (new DiagnosticIDs (), new DiagnosticOptions ());
822
+
823
+ const OptTable &Opts = clang::driver::getDriverOptTable ();
824
+ unsigned MissingArgIndex, MissingArgCount;
825
+ auto ParsedCASArgs =
826
+ Opts.ParseArgs (CASArgs, MissingArgIndex, MissingArgCount);
827
+ CompilerInvocation::ParseCASArgs (CASOpts, ParsedCASArgs, Diags);
828
+ CASOpts.ensurePersistentCAS ();
829
+ ProduceIncludeTree =
830
+ ParsedCASArgs.hasArg (driver::options::OPT_fdepscan_include_tree);
831
+
832
+ static std::once_flag ValidateOnce;
833
+ std::call_once (ValidateOnce, [&] {
834
+ if (getenv (" LLVM_CAS_DISABLE_VALIDATION" ))
835
+ return ;
836
+ if (CASOpts.CASPath .empty () || !CASOpts.PluginPath .empty ())
837
+ return ;
838
+ SmallString<64 > LLVMCasStorage;
839
+ ExitOnErr (llvm::cas::validateOnDiskUnifiedCASDatabasesIfNeeded (
840
+ CASOpts.getResolvedCASPath (), /* CheckHash=*/ true ,
841
+ /* AllowRecovery=*/ true ,
842
+ /* Force=*/ false , findLLVMCasBinary (Argv0, LLVMCasStorage)));
843
+ });
844
+
793
845
// Check the pidfile.
794
846
SmallString<128 > PidPath;
795
847
(BasePath + " .pid" ).toVector (PidPath);
@@ -828,16 +880,6 @@ int ScanServer::listen() {
828
880
llvm::DefaultThreadPool Pool;
829
881
830
882
DiagnosticsEngine Diags (new DiagnosticIDs (), new DiagnosticOptions ());
831
- CASOptions CASOpts;
832
- const OptTable &Opts = clang::driver::getDriverOptTable ();
833
- unsigned MissingArgIndex, MissingArgCount;
834
- auto ParsedCASArgs =
835
- Opts.ParseArgs (CASArgs, MissingArgIndex, MissingArgCount);
836
- CompilerInvocation::ParseCASArgs (CASOpts, ParsedCASArgs, Diags);
837
- CASOpts.ensurePersistentCAS ();
838
- bool ProduceIncludeTree =
839
- ParsedCASArgs.hasArg (driver::options::OPT_fdepscan_include_tree);
840
-
841
883
std::shared_ptr<llvm::cas::ObjectStore> CAS;
842
884
std::shared_ptr<llvm::cas::ActionCache> Cache;
843
885
std::tie (CAS, Cache) = CASOpts.getOrCreateDatabases (Diags);
0 commit comments