Skip to content

Commit 1101d73

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.
1 parent 17aa9cf commit 1101d73

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
@@ -26,9 +26,11 @@
2626
#include "clang/Tooling/DependencyScanning/ScanAndUpdateArgs.h"
2727
#include "llvm/ADT/ArrayRef.h"
2828
#include "llvm/ADT/ScopeExit.h"
29+
#include "llvm/ADT/SmallVector.h"
2930
#include "llvm/ADT/Statistic.h"
3031
#include "llvm/Bitstream/BitstreamReader.h"
3132
#include "llvm/CAS/ActionCache.h"
33+
#include "llvm/CAS/BuiltinUnifiedCASDatabases.h"
3234
#include "llvm/CAS/CASProvidingFileSystem.h"
3335
#include "llvm/CAS/CachingOnDiskFileSystem.h"
3436
#include "llvm/CAS/HierarchicalTreeBuilder.h"
@@ -39,6 +41,7 @@
3941
#include "llvm/Support/Compiler.h"
4042
#include "llvm/Support/Error.h"
4143
#include "llvm/Support/ErrorHandling.h"
44+
#include "llvm/Support/FileSystem.h"
4245
#include "llvm/Support/ManagedStatic.h"
4346
#include "llvm/Support/Path.h"
4447
#include "llvm/Support/PrefixMapper.h"
@@ -50,6 +53,7 @@
5053
#include "llvm/Support/raw_ostream.h"
5154
#include <cstdio>
5255
#include <mutex>
56+
#include <optional>
5357
#include <shared_mutex>
5458

5559
#if LLVM_ON_UNIX
@@ -630,8 +634,8 @@ namespace {
630634
struct ScanServer {
631635
const char *Argv0 = nullptr;
632636
SmallString<128> BasePath;
633-
/// List of cas options.
634-
ArrayRef<const char *> CASArgs;
637+
CASOptions CASOpts;
638+
bool ProduceIncludeTree = true;
635639
int PidFD = -1;
636640
int ListenSocket = -1;
637641
/// \p std::nullopt means it runs indefinitely.
@@ -640,7 +644,7 @@ struct ScanServer {
640644

641645
~ScanServer() { shutdown(); }
642646

643-
void start(bool Exclusive);
647+
void start(bool Exclusive, ArrayRef<const char *> CASArgs);
644648
int listen();
645649

646650
/// Tear down the socket and bind file immediately but wait till all existing
@@ -705,13 +709,13 @@ int cc1depscand_main(ArrayRef<const char *> Argv, const char *Argv0,
705709
// particular "build session", to shutdown, then have it stay alive until the
706710
// session is finished.
707711
bool LongRunning = false;
708-
712+
ArrayRef<const char *> CASArgs;
709713
for (const auto *A = Argv.begin() + 2; A != Argv.end(); ++A) {
710714
StringRef Arg(*A);
711715
if (Arg == "-long-running")
712716
LongRunning = true;
713717
else if (Arg == "-cas-args") {
714-
Server.CASArgs = ArrayRef(A + 1, Argv.end());
718+
CASArgs = ArrayRef(A + 1, Argv.end());
715719
break;
716720
}
717721
}
@@ -722,7 +726,7 @@ int cc1depscand_main(ArrayRef<const char *> Argv, const char *Argv0,
722726
reportError(Twine("cannot create basedir: ") + EC.message());
723727

724728
if (Command == "-serve") {
725-
Server.start(/*Exclusive*/ true);
729+
Server.start(/*Exclusive*/ true, CASArgs);
726730
return Server.listen();
727731

728732
} else if (Command == "-execute") {
@@ -733,7 +737,7 @@ int cc1depscand_main(ArrayRef<const char *> Argv, const char *Argv0,
733737
}
734738

735739
// Make sure to start the server before executing the command.
736-
Server.start(/*Exclusive*/ true);
740+
Server.start(/*Exclusive*/ true, CASArgs);
737741
std::thread ServerThread([&Server]() { Server.listen(); });
738742

739743
setenv("CLANG_CACHE_SCAN_DAEMON_SOCKET_PATH", Server.BasePath.c_str(),
@@ -784,11 +788,59 @@ int cc1depscand_main(ArrayRef<const char *> Argv, const char *Argv0,
784788
openAndReplaceFD(1, LogOutPath);
785789
openAndReplaceFD(2, LogErrPath);
786790

787-
Server.start(/*Exclusive*/ false);
791+
Server.start(/*Exclusive*/ false, CASArgs);
788792
return Server.listen();
789793
}
790794

791-
void ScanServer::start(bool Exclusive) {
795+
static std::optional<StringRef>
796+
findLLVMCasBinary(const char *Argv0, llvm::SmallVectorImpl<char> &Storage) {
797+
using namespace llvm::sys;
798+
std::string Path = fs::getMainExecutable(Argv0, (void *)cc1depscan_main);
799+
Storage.assign(Path.begin(), Path.end());
800+
path::remove_filename(Storage);
801+
path::append(Storage, "llvm-cas");
802+
StringRef PathStr(Storage.data(), Storage.size());
803+
if (fs::exists(PathStr))
804+
return PathStr;
805+
// Look for a corresponding usr/local/bin/llvm-cas
806+
PathStr = path::parent_path(PathStr);
807+
if (path::filename(PathStr) != "bin")
808+
return std::nullopt;
809+
PathStr = path::parent_path(PathStr);
810+
Storage.truncate(PathStr.size());
811+
path::append(Storage, "local", "bin", "llvm-cas");
812+
PathStr = StringRef{Storage.data(), Storage.size()};
813+
if (fs::exists(PathStr))
814+
return PathStr;
815+
return std::nullopt;
816+
}
817+
818+
void ScanServer::start(bool Exclusive, ArrayRef<const char *> CASArgs) {
819+
// Parse CAS options and validate if needed.
820+
DiagnosticsEngine Diags(new DiagnosticIDs(), new DiagnosticOptions());
821+
822+
const OptTable &Opts = clang::driver::getDriverOptTable();
823+
unsigned MissingArgIndex, MissingArgCount;
824+
auto ParsedCASArgs =
825+
Opts.ParseArgs(CASArgs, MissingArgIndex, MissingArgCount);
826+
CompilerInvocation::ParseCASArgs(CASOpts, ParsedCASArgs, Diags);
827+
CASOpts.ensurePersistentCAS();
828+
ProduceIncludeTree =
829+
ParsedCASArgs.hasArg(driver::options::OPT_fdepscan_include_tree);
830+
831+
static std::once_flag ValidateOnce;
832+
std::call_once(ValidateOnce, [&] {
833+
if (getenv("LLVM_CAS_DISABLE_VALIDATION"))
834+
return;
835+
if (CASOpts.CASPath.empty() || !CASOpts.PluginPath.empty())
836+
return;
837+
SmallString<64> LLVMCasStorage;
838+
ExitOnErr(llvm::cas::validateOnDiskUnifiedCASDatabasesIfNeeded(
839+
CASOpts.getResolvedCASPath(), /*CheckHash=*/true,
840+
/*AllowRecovery=*/true,
841+
/*Force=*/false, findLLVMCasBinary(Argv0, LLVMCasStorage)));
842+
});
843+
792844
// Check the pidfile.
793845
SmallString<128> PidPath;
794846
(BasePath + ".pid").toVector(PidPath);
@@ -827,16 +879,6 @@ int ScanServer::listen() {
827879
llvm::DefaultThreadPool Pool;
828880

829881
DiagnosticsEngine Diags(new DiagnosticIDs(), new DiagnosticOptions());
830-
CASOptions CASOpts;
831-
const OptTable &Opts = clang::driver::getDriverOptTable();
832-
unsigned MissingArgIndex, MissingArgCount;
833-
auto ParsedCASArgs =
834-
Opts.ParseArgs(CASArgs, MissingArgIndex, MissingArgCount);
835-
CompilerInvocation::ParseCASArgs(CASOpts, ParsedCASArgs, Diags);
836-
CASOpts.ensurePersistentCAS();
837-
bool ProduceIncludeTree =
838-
ParsedCASArgs.hasArg(driver::options::OPT_fdepscan_include_tree);
839-
840882
std::shared_ptr<llvm::cas::ObjectStore> CAS;
841883
std::shared_ptr<llvm::cas::ActionCache> Cache;
842884
std::tie(CAS, Cache) = CASOpts.getOrCreateDatabases(Diags);

0 commit comments

Comments
 (0)