2828#include " clang/Tooling/DependencyScanning/ScanAndUpdateArgs.h"
2929#include " llvm/ADT/ArrayRef.h"
3030#include " llvm/ADT/ScopeExit.h"
31+ #include " llvm/ADT/SmallVector.h"
3132#include " llvm/ADT/Statistic.h"
3233#include " llvm/Bitstream/BitstreamReader.h"
3334#include " llvm/CAS/ActionCache.h"
35+ #include " llvm/CAS/BuiltinUnifiedCASDatabases.h"
3436#include " llvm/CAS/CASProvidingFileSystem.h"
3537#include " llvm/CAS/CachingOnDiskFileSystem.h"
3638#include " llvm/CAS/HierarchicalTreeBuilder.h"
4143#include " llvm/Support/Compiler.h"
4244#include " llvm/Support/Error.h"
4345#include " llvm/Support/ErrorHandling.h"
46+ #include " llvm/Support/FileSystem.h"
4447#include " llvm/Support/ManagedStatic.h"
4548#include " llvm/Support/Path.h"
4649#include " llvm/Support/PrefixMapper.h"
5255#include " llvm/Support/raw_ostream.h"
5356#include < cstdio>
5457#include < mutex>
58+ #include < optional>
5559#include < shared_mutex>
5660
5761#if LLVM_ON_UNIX
@@ -631,8 +635,8 @@ namespace {
631635struct ScanServer {
632636 const char *Argv0 = nullptr ;
633637 SmallString<128 > BasePath;
634- // / List of cas options.
635- ArrayRef< const char *> CASArgs ;
638+ CASOptions CASOpts;
639+ bool ProduceIncludeTree = true ;
636640 int PidFD = -1 ;
637641 int ListenSocket = -1 ;
638642 // / \p std::nullopt means it runs indefinitely.
@@ -641,7 +645,7 @@ struct ScanServer {
641645
642646 ~ScanServer () { shutdown (); }
643647
644- void start (bool Exclusive);
648+ void start (bool Exclusive, ArrayRef< const char *> CASArgs );
645649 int listen ();
646650
647651 // / 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,
706710 // particular "build session", to shutdown, then have it stay alive until the
707711 // session is finished.
708712 bool LongRunning = false ;
709-
713+ ArrayRef< const char *> CASArgs;
710714 for (const auto *A = Argv.begin () + 2 ; A != Argv.end (); ++A) {
711715 StringRef Arg (*A);
712716 if (Arg == " -long-running" )
713717 LongRunning = true ;
714718 else if (Arg == " -cas-args" ) {
715- Server. CASArgs = ArrayRef (A + 1 , Argv.end ());
719+ CASArgs = ArrayRef (A + 1 , Argv.end ());
716720 break ;
717721 }
718722 }
@@ -723,7 +727,7 @@ int cc1depscand_main(ArrayRef<const char *> Argv, const char *Argv0,
723727 reportError (Twine (" cannot create basedir: " ) + EC.message ());
724728
725729 if (Command == " -serve" ) {
726- Server.start (/* Exclusive*/ true );
730+ Server.start (/* Exclusive*/ true , CASArgs );
727731 return Server.listen ();
728732
729733 } else if (Command == " -execute" ) {
@@ -734,7 +738,7 @@ int cc1depscand_main(ArrayRef<const char *> Argv, const char *Argv0,
734738 }
735739
736740 // Make sure to start the server before executing the command.
737- Server.start (/* Exclusive*/ true );
741+ Server.start (/* Exclusive*/ true , CASArgs );
738742 std::thread ServerThread ([&Server]() { Server.listen (); });
739743
740744 setenv (" CLANG_CACHE_SCAN_DAEMON_SOCKET_PATH" , Server.BasePath .c_str (),
@@ -785,11 +789,61 @@ int cc1depscand_main(ArrayRef<const char *> Argv, const char *Argv0,
785789 openAndReplaceFD (1 , LogOutPath);
786790 openAndReplaceFD (2 , LogErrPath);
787791
788- Server.start (/* Exclusive*/ false );
792+ Server.start (/* Exclusive*/ false , CASArgs );
789793 return Server.listen ();
790794}
791795
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+ SmallString<64 > CASPath;
840+ CASOpts.getResolvedCASPath (CASPath);
841+ ExitOnErr (llvm::cas::validateOnDiskUnifiedCASDatabasesIfNeeded (
842+ CASPath, /* CheckHash=*/ true ,
843+ /* AllowRecovery=*/ true ,
844+ /* Force=*/ false , findLLVMCasBinary (Argv0, LLVMCasStorage)));
845+ });
846+
793847 // Check the pidfile.
794848 SmallString<128 > PidPath;
795849 (BasePath + " .pid" ).toVector (PidPath);
@@ -828,16 +882,6 @@ int ScanServer::listen() {
828882 llvm::DefaultThreadPool Pool;
829883
830884 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-
841885 std::shared_ptr<llvm::cas::ObjectStore> CAS;
842886 std::shared_ptr<llvm::cas::ActionCache> Cache;
843887 std::tie (CAS, Cache) = CASOpts.getOrCreateDatabases (Diags);
0 commit comments