aboutsummaryrefslogtreecommitdiff
path: root/clang
diff options
context:
space:
mode:
Diffstat (limited to 'clang')
-rw-r--r--clang/include/clang/Basic/DiagnosticFrontendKinds.td5
-rw-r--r--clang/include/clang/Driver/Options.td2
-rw-r--r--clang/include/clang/Frontend/CompilerInvocation.h1
-rw-r--r--clang/include/clang/Lex/HeaderSearchOptions.h7
-rw-r--r--clang/lib/Frontend/ASTUnit.cpp2
-rw-r--r--clang/lib/Frontend/CompilerInvocation.cpp28
-rw-r--r--clang/test/CMakeLists.txt1
-rw-r--r--clang/test/Driver/vfsstatcache.c5
-rw-r--r--clang/test/clang-stat-cache/cache-effects.c63
-rw-r--r--clang/test/clang-stat-cache/errors.test42
-rw-r--r--clang/tools/CMakeLists.txt1
-rw-r--r--clang/tools/clang-stat-cache/CMakeLists.txt19
-rw-r--r--clang/tools/clang-stat-cache/clang-stat-cache.cpp318
13 files changed, 2 insertions, 492 deletions
diff --git a/clang/include/clang/Basic/DiagnosticFrontendKinds.td b/clang/include/clang/Basic/DiagnosticFrontendKinds.td
index e106858..d0f672a 100644
--- a/clang/include/clang/Basic/DiagnosticFrontendKinds.td
+++ b/clang/include/clang/Basic/DiagnosticFrontendKinds.td
@@ -256,11 +256,6 @@ def err_test_module_file_extension_version : Error<
"test module file extension '%0' has different version (%1.%2) than expected "
"(%3.%4)">;
-def err_missing_vfs_stat_cache_file : Error<
- "stat cache file '%0' not found">, DefaultFatal;
-def err_invalid_vfs_stat_cache : Error<
- "invalid stat cache file '%0'">, DefaultFatal;
-
def err_missing_vfs_overlay_file : Error<
"virtual filesystem overlay file '%0' not found">, DefaultFatal;
def err_invalid_vfs_overlay : Error<
diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td
index 9334e63..ba49b33 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -3357,8 +3357,6 @@ def iwithsysroot : JoinedOrSeparate<["-"], "iwithsysroot">, Group<clang_i_Group>
HelpText<"Add directory to SYSTEM include search path, "
"absolute paths are relative to -isysroot">, MetaVarName<"<directory>">,
Flags<[CC1Option]>;
-def ivfsstatcache : JoinedOrSeparate<["-"], "ivfsstatcache">, Group<clang_i_Group>, Flags<[CC1Option]>,
- HelpText<"Use the stat data cached in file instead of doing filesystem syscalls. See clang-stat-cache utility.">;
def ivfsoverlay : JoinedOrSeparate<["-"], "ivfsoverlay">, Group<clang_i_Group>, Flags<[CC1Option]>,
HelpText<"Overlay the virtual filesystem described by file over the real file system">;
def imultilib : Separate<["-"], "imultilib">, Group<gfortran_Group>;
diff --git a/clang/include/clang/Frontend/CompilerInvocation.h b/clang/include/clang/Frontend/CompilerInvocation.h
index 9cc6aa5..254f048 100644
--- a/clang/include/clang/Frontend/CompilerInvocation.h
+++ b/clang/include/clang/Frontend/CompilerInvocation.h
@@ -296,7 +296,6 @@ IntrusiveRefCntPtr<llvm::vfs::FileSystem> createVFSFromCompilerInvocation(
IntrusiveRefCntPtr<llvm::vfs::FileSystem>
createVFSFromOverlayFiles(ArrayRef<std::string> VFSOverlayFiles,
- ArrayRef<std::string> VFSStatCacheFiles,
DiagnosticsEngine &Diags,
IntrusiveRefCntPtr<llvm::vfs::FileSystem> BaseFS);
diff --git a/clang/include/clang/Lex/HeaderSearchOptions.h b/clang/include/clang/Lex/HeaderSearchOptions.h
index 548f7d4..6436a9b 100644
--- a/clang/include/clang/Lex/HeaderSearchOptions.h
+++ b/clang/include/clang/Lex/HeaderSearchOptions.h
@@ -181,9 +181,6 @@ public:
/// of computing the module hash.
llvm::SmallSetVector<llvm::CachedHashString, 16> ModulesIgnoreMacros;
- /// The set of user-provided stat cache files.
- std::vector<std::string> VFSStatCacheFiles;
-
/// The set of user-provided virtual filesystem overlay files.
std::vector<std::string> VFSOverlayFiles;
@@ -253,10 +250,6 @@ public:
SystemHeaderPrefixes.emplace_back(Prefix, IsSystemHeader);
}
- void AddVFSStatCacheFile(StringRef Name) {
- VFSStatCacheFiles.push_back(std::string(Name));
- }
-
void AddVFSOverlayFile(StringRef Name) {
VFSOverlayFiles.push_back(std::string(Name));
}
diff --git a/clang/lib/Frontend/ASTUnit.cpp b/clang/lib/Frontend/ASTUnit.cpp
index dbf55d9..3b4f251 100644
--- a/clang/lib/Frontend/ASTUnit.cpp
+++ b/clang/lib/Frontend/ASTUnit.cpp
@@ -574,7 +574,7 @@ public:
// performs the initialization too late (once both target and language
// options are read).
PP.getFileManager().setVirtualFileSystem(createVFSFromOverlayFiles(
- HSOpts.VFSOverlayFiles, HSOpts.VFSStatCacheFiles, PP.getDiagnostics(),
+ HSOpts.VFSOverlayFiles, PP.getDiagnostics(),
PP.getFileManager().getVirtualFileSystemPtr()));
InitializedHeaderSearchPaths = true;
diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp
index b0ef37fa..0bb9c8c 100644
--- a/clang/lib/Frontend/CompilerInvocation.cpp
+++ b/clang/lib/Frontend/CompilerInvocation.cpp
@@ -83,7 +83,6 @@
#include "llvm/Support/Path.h"
#include "llvm/Support/Process.h"
#include "llvm/Support/Regex.h"
-#include "llvm/Support/StatCacheFileSystem.h"
#include "llvm/Support/VersionTuple.h"
#include "llvm/Support/VirtualFileSystem.h"
#include "llvm/Support/raw_ostream.h"
@@ -3085,9 +3084,6 @@ static void GenerateHeaderSearchArgs(HeaderSearchOptions &Opts,
GenerateArg(Args, Opt, P.Prefix, SA);
}
- for (const std::string &F : Opts.VFSStatCacheFiles)
- GenerateArg(Args, OPT_ivfsstatcache, F, SA);
-
for (const std::string &F : Opts.VFSOverlayFiles)
GenerateArg(Args, OPT_ivfsoverlay, F, SA);
}
@@ -3221,9 +3217,6 @@ static bool ParseHeaderSearchArgs(HeaderSearchOptions &Opts, ArgList &Args,
Opts.AddSystemHeaderPrefix(
A->getValue(), A->getOption().matches(OPT_system_header_prefix));
- for (const auto *A : Args.filtered(OPT_ivfsstatcache))
- Opts.AddVFSStatCacheFile(A->getValue());
-
for (const auto *A : Args.filtered(OPT_ivfsoverlay))
Opts.AddVFSOverlayFile(A->getValue());
@@ -4754,31 +4747,12 @@ clang::createVFSFromCompilerInvocation(
const CompilerInvocation &CI, DiagnosticsEngine &Diags,
IntrusiveRefCntPtr<llvm::vfs::FileSystem> BaseFS) {
return createVFSFromOverlayFiles(CI.getHeaderSearchOpts().VFSOverlayFiles,
- CI.getHeaderSearchOpts().VFSStatCacheFiles,
Diags, std::move(BaseFS));
}
IntrusiveRefCntPtr<llvm::vfs::FileSystem> clang::createVFSFromOverlayFiles(
- ArrayRef<std::string> VFSOverlayFiles,
- ArrayRef<std::string> VFSStatCacheFiles, DiagnosticsEngine &Diags,
+ ArrayRef<std::string> VFSOverlayFiles, DiagnosticsEngine &Diags,
IntrusiveRefCntPtr<llvm::vfs::FileSystem> BaseFS) {
- for (const auto &File : VFSStatCacheFiles) {
- llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> Buffer =
- BaseFS->getBufferForFile(File);
- if (!Buffer) {
- Diags.Report(diag::err_missing_vfs_stat_cache_file) << File;
- continue;
- }
-
- auto StatCache =
- llvm::vfs::StatCacheFileSystem::create(std::move(*Buffer), BaseFS);
-
- if (errorToBool(StatCache.takeError()))
- Diags.Report(diag::err_invalid_vfs_stat_cache) << File;
- else
- BaseFS = std::move(*StatCache);
- }
-
if (VFSOverlayFiles.empty())
return BaseFS;
diff --git a/clang/test/CMakeLists.txt b/clang/test/CMakeLists.txt
index cd3775b..1d6377b 100644
--- a/clang/test/CMakeLists.txt
+++ b/clang/test/CMakeLists.txt
@@ -71,7 +71,6 @@ list(APPEND CLANG_TEST_DEPS
clang-refactor
clang-diff
clang-scan-deps
- clang-stat-cache
diagtool
hmaptool
)
diff --git a/clang/test/Driver/vfsstatcache.c b/clang/test/Driver/vfsstatcache.c
deleted file mode 100644
index ec3c279..0000000
--- a/clang/test/Driver/vfsstatcache.c
+++ /dev/null
@@ -1,5 +0,0 @@
-// RUN: %clang -ivfsstatcache foo.h -### %s 2>&1 | FileCheck %s
-// CHECK: "-ivfsstatcache" "foo.h"
-
-// RUN: not %clang -ivfsstatcache foo.h %s 2>&1 | FileCheck -check-prefix=CHECK-MISSING %s
-// CHECK-MISSING: stat cache file 'foo.h' not found
diff --git a/clang/test/clang-stat-cache/cache-effects.c b/clang/test/clang-stat-cache/cache-effects.c
deleted file mode 100644
index bf2e2db..0000000
--- a/clang/test/clang-stat-cache/cache-effects.c
+++ /dev/null
@@ -1,63 +0,0 @@
-#include "foo.h"
-
-// Testing the effects of a cache is tricky, because it's just supposed to speed
-// things up, not change the behavior. In this test, we are using an outdated
-// cache to trick HeaderSearch into finding the wrong module and show that it is
-// being used.
-
-// Clear the module cache.
-// RUN: rm -rf %t
-// RUN: mkdir -p %t/Inputs
-// RUN: mkdir -p %t/Inputs/Foo1
-// RUN: mkdir -p %t/Inputs/Foo2
-// RUN: mkdir -p %t/modules-to-compare
-
-// ===
-// Create a Foo module in the Foo1 direcotry.
-// RUN: echo 'void meow(void);' > %t/Inputs/Foo1/foo.h
-// RUN: echo 'module Foo { header "foo.h" }' > %t/Inputs/Foo1/module.map
-
-// ===
-// Compile the module. Note that the compiler has 2 header search paths:
-// Foo2 and Foo1 in that order. The module has been created in Foo1, and
-// it is the only version available now.
-// RUN: %clang_cc1 -cc1 -fmodules -fimplicit-module-maps -fdisable-module-hash -fmodules-cache-path=%t/modules-cache -fsyntax-only -I %t/Inputs/Foo2 -I %t/Inputs/Foo1 -Rmodule-build %s 2>&1
-// RUN: cp %t/modules-cache/Foo.pcm %t/modules-to-compare/Foo-before.pcm
-
-// ===
-// Create a stat cache for our inputs directory
-// RUN: clang-stat-cache %t/Inputs -o %t/stat.cache
-
-// ===
-// As a sanity check, re-run the same compilation with the cache and check that
-// the module does not change.
-// RUN: %clang_cc1 -cc1 -fmodules -fimplicit-module-maps -fdisable-module-hash -fmodules-cache-path=%t/modules-cache -fsyntax-only -I %t/Inputs/Foo2 -I %t/Inputs/Foo1 -ivfsstatcache %t/stat.cache %s -Rmodule-build 2>&1
-// RUN: cp %t/modules-cache/Foo.pcm %t/modules-to-compare/Foo-after.pcm
-
-// RUN: diff %t/modules-to-compare/Foo-before.pcm %t/modules-to-compare/Foo-after.pcm
-
-// ===
-// Now introduce a different Foo module in the Foo2 directory which is before
-// Foo1 in the search paths.
-// RUN: echo 'void meow2(void);' > %t/Inputs/Foo2/foo.h
-// RUN: echo 'module Foo { header "foo.h" }' > %t/Inputs/Foo2/module.map
-
-// ===
-// Because we're using the (now-outdated) stat cache, this compilation
-// should still be using the first module. It will not see the new one
-// which is earlier in the search paths.
-// RUN: %clang_cc1 -cc1 -fmodules -fimplicit-module-maps -fdisable-module-hash -fmodules-cache-path=%t/modules-cache -fsyntax-only -I %t/Inputs/Foo2 -I %t/Inputs/Foo1 -ivfsstatcache %t/stat.cache -Rmodule-build -Rmodule-import %s 2>&1
-// RUN: cp %t/modules-cache/Foo.pcm %t/modules-to-compare/Foo-after.pcm
-
-// RUN: diff %t/modules-to-compare/Foo-before.pcm %t/modules-to-compare/Foo-after.pcm
-
-// ===
-// Regenerate the stat cache for our Inputs directory
-// RUN: clang-stat-cache -f %t/Inputs -o %t/stat.cache 2>&1
-
-// ===
-// Use the module and now see that we are recompiling the new one.
-// RUN: %clang_cc1 -cc1 -fmodules -fimplicit-module-maps -fdisable-module-hash -fmodules-cache-path=%t/modules-cache -fsyntax-only -I %t/Inputs/Foo2 -I %t/Inputs/Foo1 -ivfsstatcache %t/stat.cache -Rmodule-build %s 2>&1
-// RUN: cp %t/modules-cache/Foo.pcm %t/modules-to-compare/Foo-after.pcm
-
-// RUN: not diff %t/modules-to-compare/Foo-before.pcm %t/modules-to-compare/Foo-after.pcm
diff --git a/clang/test/clang-stat-cache/errors.test b/clang/test/clang-stat-cache/errors.test
deleted file mode 100644
index ab73a134..0000000
--- a/clang/test/clang-stat-cache/errors.test
+++ /dev/null
@@ -1,42 +0,0 @@
-RUN: rm -rf %t
-RUN: mkdir -p %t
-
-RUN: not clang-stat-cache %t/not-there -o %t/stat.cache 2>&1 | FileCheck --check-prefix=NO-SUCH-DIR %s
-NO-SUCH-DIR: Failed to stat the target directory: {{[Nn]}}o such file or directory
-
-RUN: not clang-stat-cache %t -o %t/not-there/stat.cache 2>&1 | FileCheck --check-prefix=NO-SUCH-FILE %s
-NO-SUCH-FILE: Failed to open cache file: '{{.*}}': {{[Nn]}}o such file or directory
-
-# Use mixed-case directories to exercise the case insensitive implementation.
-RUN: mkdir -p %t/Dir
-RUN: mkdir -p %t/Dir2
-
-# Try to overwrite a few invalid caches
-RUN: echo "Not a stat cache" > %t/stat.cache
-RUN: not clang-stat-cache %t/Dir -o %t/stat.cache 2>&1 | FileCheck --check-prefix=INVALID-CACHE %s
-RUN: echo "Not a stat cache, but bigger than the stat cache header" > %t/stat.cache
-RUN: not clang-stat-cache %t/Dir -o %t/stat.cache 2>&1 | FileCheck --check-prefix=INVALID-CACHE %s
-RUN: echo "STAT. This has the correct MAGIC and is bigger than the header." > %t/stat.cache
-RUN: not clang-stat-cache %t/Dir -o %t/stat.cache 2>&1 | FileCheck --check-prefix=INVALID-CACHE %s
-
-INVALID-CACHE: The output cache file exists and is not a valid stat cache. Aborting.
-
-# Test the force flag
-RUN: echo "STAT. This has the correct MAGIC and is bigger than the header." > %t/stat.cache
-RUN: clang-stat-cache %t/Dir -f -o %t/stat.cache 2>&1 | FileCheck --check-prefix=INVALID-CACHE-FORCE %s
-INVALID-CACHE-FORCE: The output cache file exists and is not a valid stat cache. Forced update.
-
-# Generate a valid cache for dir
-RUN: rm %t/stat.cache
-RUN: clang-stat-cache %t/Dir -o %t/stat.cache
-RUN: cp %t/stat.cache %t/stat.cache.save
-
-# Try with same base direcotry but with extraneous separators
-RUN: clang-stat-cache %t/Dir/// -v -o %t/stat.cache | FileCheck --check-prefix=EXTRA-SEP %s
-EXTRA-SEP-NOT: Existing cache has different directory. Regenerating...
-EXTRA-SEP: Cache up-to-date, exiting
-
-# Rewrite the cache with a different base directory
-RUN: clang-stat-cache %t/Dir2 -o %t/stat.cache 2>&1 | FileCheck --check-prefix=OTHER-DIR %s
-OTHER-DIR: Existing cache has different directory. Regenerating...
-
diff --git a/clang/tools/CMakeLists.txt b/clang/tools/CMakeLists.txt
index 147555d..f60db6e 100644
--- a/clang/tools/CMakeLists.txt
+++ b/clang/tools/CMakeLists.txt
@@ -15,7 +15,6 @@ add_clang_subdirectory(clang-scan-deps)
if(HAVE_CLANG_REPL_SUPPORT)
add_clang_subdirectory(clang-repl)
endif()
-add_clang_subdirectory(clang-stat-cache)
add_clang_subdirectory(c-index-test)
diff --git a/clang/tools/clang-stat-cache/CMakeLists.txt b/clang/tools/clang-stat-cache/CMakeLists.txt
deleted file mode 100644
index ab93d8b..0000000
--- a/clang/tools/clang-stat-cache/CMakeLists.txt
+++ /dev/null
@@ -1,19 +0,0 @@
-set(LLVM_LINK_COMPONENTS
- Core
- Support
- )
-
-add_clang_tool(clang-stat-cache
- clang-stat-cache.cpp
- )
-
-if(APPLE)
-set(CLANG_STAT_CACHE_LIB_DEPS
- "-framework CoreServices"
- )
-endif()
-
-clang_target_link_libraries(clang-stat-cache
- PRIVATE
- ${CLANG_STAT_CACHE_LIB_DEPS}
- )
diff --git a/clang/tools/clang-stat-cache/clang-stat-cache.cpp b/clang/tools/clang-stat-cache/clang-stat-cache.cpp
deleted file mode 100644
index 183d0d7..0000000
--- a/clang/tools/clang-stat-cache/clang-stat-cache.cpp
+++ /dev/null
@@ -1,318 +0,0 @@
-//===- clang-stat-cache.cpp -----------------------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/Support/CommandLine.h"
-#include "llvm/Support/FileSystem.h"
-#include "llvm/Support/MemoryBuffer.h"
-#include "llvm/Support/Path.h"
-#include "llvm/Support/StatCacheFileSystem.h"
-#include "llvm/Support/Timer.h"
-#include "llvm/Support/raw_ostream.h"
-
-#include <assert.h>
-
-#ifdef __APPLE__
-#include <CoreServices/CoreServices.h>
-
-#include <sys/mount.h>
-#include <sys/param.h>
-#endif // __APPLE__
-
-// The clang-stat-cache utility creates an on-disk cache for the stat data
-// of a file-system tree which is expected to be immutable during a build.
-
-using namespace llvm;
-using llvm::vfs::StatCacheFileSystem;
-
-cl::OptionCategory StatCacheCategory("clang-stat-cache options");
-
-cl::opt<std::string> OutputFilename("o", cl::Required,
- cl::desc("Specify output filename"),
- cl::value_desc("filename"),
- cl::cat(StatCacheCategory));
-
-cl::opt<std::string> TargetDirectory(cl::Positional, cl::Required,
- cl::value_desc("dirname"),
- cl::cat(StatCacheCategory));
-
-cl::opt<bool> Verbose("v", cl::desc("More verbose output"));
-cl::opt<bool> Force("f", cl::desc("Force cache generation"));
-
-#if __APPLE__
-// Used by checkContentsValidity. See below.
-struct CallbackInfo {
- bool SeenChanges = false;
-};
-
-// Used by checkContentsValidity. See below.
-static void FSEventsCallback(ConstFSEventStreamRef streamRef, void *CtxInfo,
- size_t numEvents, void *eventPaths,
- const FSEventStreamEventFlags *eventFlags,
- const FSEventStreamEventId *eventIds) {
- CallbackInfo *Info = static_cast<CallbackInfo *>(CtxInfo);
- for (size_t i = 0; i < numEvents; ++i) {
- // The kFSEventStreamEventFlagHistoryDone is set on the last 'historical'
- // event passed to the callback. This means it is passed after the callback
- // all the relevant activity between the StartEvent of the stream and the
- // point the stream was created.
- // If the callback didn't see any other event, it means there haven't been
- // any alterations to the target directory hierarchy and the cache contents
- // is still up-to-date.
- if (eventFlags[i] & kFSEventStreamEventFlagHistoryDone) {
- // Let's stop the main queue and go back to our non-queue code.
- CFRunLoopStop(CFRunLoopGetCurrent());
- break;
- }
-
- // If we see any event outisde of the kFSEventStreamEventFlagHistoryDone
- // one, there have been changes to the target directory.
- Info->SeenChanges = true;
- }
-}
-
-// FSEvents-based check for cache contents validity. We store the latest
-// FSEventStreamEventId in the cache as a ValidityToken and check if any
-// file system events affected the base directory since the cache was
-// generated.
-static bool checkContentsValidity(uint64_t &ValidityToken) {
- CFStringRef TargetDir = CFStringCreateWithCStringNoCopy(
- kCFAllocatorDefault, TargetDirectory.c_str(), kCFStringEncodingASCII,
- kCFAllocatorNull);
- CFArrayRef PathsToWatch =
- CFArrayCreate(nullptr, (const void **)&TargetDir, 1, nullptr);
- CallbackInfo Info;
- FSEventStreamContext Ctx = {0, &Info, nullptr, nullptr, nullptr};
- FSEventStreamRef Stream;
- CFAbsoluteTime Latency = 0; // Latency in seconds. Do not wait.
-
- // Start at the latest event stored in the cache.
- FSEventStreamEventId StartEvent = ValidityToken;
- // Update the Validity token with the current latest event.
- ValidityToken = FSEventsGetCurrentEventId();
-
- // Create the stream
- Stream =
- FSEventStreamCreate(NULL, &FSEventsCallback, &Ctx, PathsToWatch,
- StartEvent, Latency, kFSEventStreamCreateFlagNone);
-
- // Associate the stream with the main queue.
- FSEventStreamSetDispatchQueue(Stream, dispatch_get_main_queue());
- // Start the stream (needs the queue to run to do anything).
- if (!FSEventStreamStart(Stream)) {
- errs() << "Failed to create FS event stream. "
- << "Considering the cache up-to-date.\n";
- return true;
- }
-
- // Start the main queue. It will be exited by our callback when it got
- // confirmed it processed all events.
- CFRunLoopRun();
-
- return !Info.SeenChanges;
-}
-
-#else // __APPLE__
-
-// There is no cross-platform way to implement a validity check. If this
-// platform doesn't support it, just consider the cache contents always
-// valid. When that's the case, the tool running cache generation needs
-// to have the knowledge to do it only when needed.
-static bool checkContentsValidity(uint64_t &ValidityToken) { return true; }
-
-#endif // __APPLE__
-
-// Populate Generator with the stat cache data for the filesystem tree
-// rooted at BasePath.
-static std::error_code
-populateHashTable(StringRef BasePath,
- StatCacheFileSystem::StatCacheWriter &Generator) {
- using namespace llvm;
- using namespace sys::fs;
-
- std::error_code ErrorCode;
-
- // Just loop over the target directory using a recursive iterator.
- // This invocation follows symlinks, so we are going to potentially
- // store the status of the same file multiple times with different
- // names.
- for (recursive_directory_iterator I(BasePath, ErrorCode), E;
- I != E && !ErrorCode; I.increment(ErrorCode)) {
- StringRef Path = I->path();
- sys::fs::file_status s;
- // This can fail (broken symlink) and leave the file_status with
- // its default values. The reader knows this.
- status(Path, s);
-
- Generator.addEntry(Path, s);
- }
-
- return ErrorCode;
-}
-
-static bool checkCacheValid(int FD, raw_fd_ostream &Out,
- uint64_t &ValidityToken) {
- sys::fs::file_status Status;
- auto EC = sys::fs::status(FD, Status);
- if (EC) {
- llvm::errs() << "fstat failed: "
- << llvm::toString(llvm::errorCodeToError(EC)) << "\n";
- return false;
- }
-
- auto Size = Status.getSize();
- if (Size == 0) {
- // New file.
-#ifdef __APPLE__
- // Get the current (global) FSEvent id and use this as ValidityToken.
- ValidityToken = FSEventsGetCurrentEventId();
-#endif
- return false;
- }
-
- auto ErrorOrBuffer = MemoryBuffer::getOpenFile(
- sys::fs::convertFDToNativeFile(FD), OutputFilename, Status.getSize());
-
- // Refuse to write to this cache file if it exists but its contents do
- // not look like a valid cache file.
- StringRef BaseDir;
- bool IsCaseSensitive;
- bool VersionMatch;
- if (auto E = StatCacheFileSystem::validateCacheFile(
- (*ErrorOrBuffer)->getMemBufferRef(), BaseDir, IsCaseSensitive,
- VersionMatch, ValidityToken)) {
- llvm::errs() << "The output cache file exists and is not a valid stat "
- "cache.";
- if (!Force) {
- llvm::errs() << " Aborting.\n";
- exit(1);
- }
-
- consumeError(std::move(E));
- llvm::errs() << " Forced update.\n";
- return false;
- }
-
- if (BaseDir != TargetDirectory &&
- (IsCaseSensitive || !BaseDir.equals_insensitive(TargetDirectory))) {
- llvm::errs() << "Existing cache has different directory. Regenerating...\n";
- return false;
- }
-
- if (!VersionMatch) {
- llvm::errs()
- << "Exisitng cache has different version number. Regenerating...\n";
- return false;
- }
-
- // Basic structure checks have passed. Lets see if we can prove that the cache
- // contents are still valid.
- bool IsValid = checkContentsValidity(ValidityToken);
- if (IsValid) {
- // The cache is valid, but we might have gotten an updated ValidityToken.
- // Update the cache with it as clang-stat-cache is just going to exit after
- // returning from this function.
- StatCacheFileSystem::updateValidityToken(Out, ValidityToken);
- }
- return IsValid && !Force;
-}
-
-int main(int argc, char *argv[]) {
- cl::ParseCommandLineOptions(argc, argv);
-
- llvm::SmallString<128> CanonicalDirectory = StringRef(TargetDirectory);
-
- // Remove extraneous separators from the end of the basename.
- while (!CanonicalDirectory.empty() &&
- sys::path::is_separator(CanonicalDirectory.back()))
- CanonicalDirectory.pop_back();
- // Canonicalize separators on Windows
- llvm::sys::path::make_preferred(CanonicalDirectory);
- TargetDirectory = std::string(CanonicalDirectory);
-
- StringRef Dirname(TargetDirectory);
-
- std::error_code EC;
- int FD;
- EC = sys::fs::openFileForReadWrite(
- OutputFilename, FD, llvm::sys::fs::CD_OpenAlways, llvm::sys::fs::OF_None);
- if (EC) {
- llvm::errs() << "Failed to open cache file: "
- << toString(llvm::createFileError(OutputFilename, EC)) << "\n";
- return 1;
- }
-
- raw_fd_ostream Out(FD, /* ShouldClose=*/true);
-
- uint64_t ValidityToken = 0;
- // Check if the cache is valid and up-to-date.
- if (checkCacheValid(FD, Out, ValidityToken)) {
- if (Verbose)
- outs() << "Cache up-to-date, exiting\n";
- return 0;
- }
-
- if (Verbose)
- outs() << "Building a stat cache for '" << TargetDirectory << "' into '"
- << OutputFilename << "'\n";
-
- // Do not generate a cache for NFS. Iterating huge directory hierarchies
- // over NFS will be very slow. Better to let the compiler search only the
- // pieces that it needs than use a cache that takes ages to populate.
- bool IsLocal;
- EC = sys::fs::is_local(Dirname, IsLocal);
- if (EC) {
- errs() << "Failed to stat the target directory: "
- << llvm::toString(llvm::errorCodeToError(EC)) << "\n";
- return 1;
- }
-
- if (!IsLocal && !Force) {
- errs() << "Target directory is not a local filesystem. "
- << "Not populating the cache.\n";
- return 0;
- }
-
- sys::fs::file_status BaseDirStatus;
- if (std::error_code EC = status(Dirname, BaseDirStatus)) {
- errs() << "Failed to stat the target directory: "
- << llvm::toString(llvm::errorCodeToError(EC)) << "\n";
- return 1;
- }
-
- // Check if the filesystem hosting the target directory is case sensitive.
- bool IsCaseSensitive = true;
-#ifdef _PC_CASE_SENSITIVE
- IsCaseSensitive =
- ::pathconf(TargetDirectory.c_str(), _PC_CASE_SENSITIVE) == 1;
-#endif
- StatCacheFileSystem::StatCacheWriter Generator(
- Dirname, BaseDirStatus, IsCaseSensitive, ValidityToken);
-
- // Populate the cache.
- auto startTime = llvm::TimeRecord::getCurrentTime();
- populateHashTable(Dirname, Generator);
- auto duration = llvm::TimeRecord::getCurrentTime();
- duration -= startTime;
-
- if (Verbose)
- errs() << "populateHashTable took: " << duration.getWallTime() << "s\n";
-
- // Write the cache to disk.
- startTime = llvm::TimeRecord::getCurrentTime();
- int Size = Generator.writeStatCache(Out);
- duration = llvm::TimeRecord::getCurrentTime();
- duration -= startTime;
-
- if (Verbose)
- errs() << "writeStatCache took: " << duration.getWallTime() << "s\n";
-
- // We might have opened a pre-exising cache which was bigger.
- llvm::sys::fs::resize_file(FD, Size);
-
- return 0;
-}