Skip to content

Commit 87b9f40

Browse files
committed
[clang][cas] Adopt validate-if-needed in clang scanning daemon
Use the new validate-if-needed functionality to ensure the clang scanning daemon's CAS data is valid. (cherry picked from commit 1101d73)
1 parent 46e43bb commit 87b9f40

File tree

6 files changed

+93
-21
lines changed

6 files changed

+93
-21
lines changed

clang/include/clang/CAS/CASOptions.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,8 @@ class CASOptions : public CASConfiguration {
117117
/// default on-disk CAS, otherwise this is a noop.
118118
void ensurePersistentCAS();
119119

120+
std::string getResolvedCASPath() const;
121+
120122
private:
121123
/// Initialize Cached CAS and ActionCache.
122124
llvm::Error initCache() const;

clang/lib/CAS/CASOptions.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,3 +119,12 @@ llvm::Error CASOptions::initCache() const {
119119
std::tie(Cache.CAS, Cache.AC) = std::move(DBs);
120120
return llvm::Error::success();
121121
}
122+
123+
std::string CASOptions::getResolvedCASPath() const {
124+
if (CASPath != "auto")
125+
return CASPath;
126+
127+
SmallString<256> PathBuf;
128+
getDefaultOnDiskCASPath(PathBuf);
129+
return std::string(PathBuf);
130+
}

clang/test/CAS/depscan-cas-log.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
// enable logging there are currently zero records in the log.
44

55
// RUN: rm -rf %t && mkdir %t
6-
// RUN: env LLVM_CACHE_CAS_PATH=%t/cas LLVM_CAS_LOG=1 %clang \
6+
// RUN: env LLVM_CACHE_CAS_PATH=%t/cas LLVM_CAS_LOG=1 LLVM_CAS_DISABLE_VALIDATION=1 %clang \
77
// RUN: -cc1depscan -fdepscan=daemon -fdepscan-include-tree -o - \
88
// RUN: -cc1-args -cc1 -triple x86_64-apple-macosx11.0.0 -emit-obj %s -o %t/t.o -fcas-path %t/cas
99
// RUN: FileCheck %s --input-file %t/cas/v1.log

clang/test/CAS/validate-once.c

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// RUN: rm -rf %t
2+
3+
// RUN: llvm-cas --cas %t/cas --ingest %s
4+
// RUN: mv %t/cas/v1.1/v8.data %t/cas/v1.1/v8.data.bak
5+
6+
// RUN: %clang -cc1depscand -execute %{clang-daemon-dir}/%basename_t -cas-args -fcas-path %t/cas -- \
7+
// RUN: %clang -target x86_64-apple-macos11 -I %S/Inputs \
8+
// RUN: -Xclang -fcas-path -Xclang %t/cas \
9+
// RUN: -fdepscan=daemon -fdepscan-daemon=%{clang-daemon-dir}/%basename_t -fsyntax-only -x c %s
10+
11+
// RUN: ls %t/cas/corrupt.0.v1.1
12+
13+
// RUN: llvm-cas --cas %t/cas --validate-if-needed | FileCheck %s -check-prefix=SKIPPED
14+
// SKIPPED: validation skipped
15+
16+
#include "test.h"
17+
18+
int func(void);

clang/tools/driver/cc1depscanProtocol.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -188,7 +188,8 @@ Expected<ScanDaemon> ScanDaemon::launchDaemon(StringRef BasePath,
188188
#endif
189189

190190
static constexpr const char *PassThroughEnv[] = {
191-
"LLVM_CAS_LOG",
191+
"LLVM_CAS_LOG",
192+
"LLVM_CAS_DISABLE_VALIDATION",
192193
};
193194
SmallVector<const char *> EnvP;
194195
for (const char *Name : PassThroughEnv)

clang/tools/driver/cc1depscan_main.cpp

Lines changed: 61 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,11 @@
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"
@@ -41,6 +43,7 @@
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"
@@ -52,6 +55,7 @@
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 {
631635
struct 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,59 @@ 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+
ExitOnErr(llvm::cas::validateOnDiskUnifiedCASDatabasesIfNeeded(
840+
CASOpts.getResolvedCASPath(), /*CheckHash=*/true,
841+
/*AllowRecovery=*/true,
842+
/*Force=*/false, findLLVMCasBinary(Argv0, LLVMCasStorage)));
843+
});
844+
793845
// Check the pidfile.
794846
SmallString<128> PidPath;
795847
(BasePath + ".pid").toVector(PidPath);
@@ -828,16 +880,6 @@ int ScanServer::listen() {
828880
llvm::DefaultThreadPool Pool;
829881

830882
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-
841883
std::shared_ptr<llvm::cas::ObjectStore> CAS;
842884
std::shared_ptr<llvm::cas::ActionCache> Cache;
843885
std::tie(CAS, Cache) = CASOpts.getOrCreateDatabases(Diags);

0 commit comments

Comments
 (0)