From: Alex Lorenz Date: Thu, 29 Aug 2019 22:56:38 +0000 (+0000) Subject: [clang-scan-deps] reuse the file manager across invocations of X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=6dae4ca453a79d710b66138df19b6f8a352450da;p=clang [clang-scan-deps] reuse the file manager across invocations of the dependency scanner on a single worker thread This behavior can be controlled using the new `-reuse-filemanager` clang-scan-deps option. By default the file manager is reused. The added test/ClangScanDeps/symlink.cpp is able to pass with the reused filemanager after the related FileEntryRef changes landed earlier. The test test/ClangScanDeps/subframework_header_dir_symlink.m still fails when the file manager is reused (I run the FileCheck with not to make it PASS). I will address this in a follow-up patch that improves the DirectoryEntry name modelling in the FileManager. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@370420 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Tooling/DependencyScanning/DependencyScanningService.h b/include/clang/Tooling/DependencyScanning/DependencyScanningService.h index 0dde0ad35d..c49f92d082 100644 --- a/include/clang/Tooling/DependencyScanning/DependencyScanningService.h +++ b/include/clang/Tooling/DependencyScanning/DependencyScanningService.h @@ -34,16 +34,19 @@ enum class ScanningMode { /// the invidual dependency scanning workers. class DependencyScanningService { public: - DependencyScanningService(ScanningMode Mode); + DependencyScanningService(ScanningMode Mode, bool ReuseFileManager = true); ScanningMode getMode() const { return Mode; } + bool canReuseFileManager() const { return ReuseFileManager; } + DependencyScanningFilesystemSharedCache &getSharedCache() { return SharedCache; } private: const ScanningMode Mode; + const bool ReuseFileManager; /// The global file system cache. DependencyScanningFilesystemSharedCache SharedCache; }; diff --git a/include/clang/Tooling/DependencyScanning/DependencyScanningWorker.h b/include/clang/Tooling/DependencyScanning/DependencyScanningWorker.h index 79c652ef5a..d56f5395da 100644 --- a/include/clang/Tooling/DependencyScanning/DependencyScanningWorker.h +++ b/include/clang/Tooling/DependencyScanning/DependencyScanningWorker.h @@ -54,6 +54,9 @@ private: /// dependencies. This filesystem persists accross multiple compiler /// invocations. llvm::IntrusiveRefCntPtr DepFS; + /// The file manager that is reused accross multiple invocations by this + /// worker. If null, the file manager will not be reused. + llvm::IntrusiveRefCntPtr Files; }; } // end namespace dependencies diff --git a/include/clang/Tooling/Tooling.h b/include/clang/Tooling/Tooling.h index 5df816e671..b8c7435c5e 100644 --- a/include/clang/Tooling/Tooling.h +++ b/include/clang/Tooling/Tooling.h @@ -349,12 +349,15 @@ public: /// clang modules. /// \param BaseFS VFS used for all underlying file accesses when running the /// tool. + /// \param Files The file manager to use for underlying file operations when + /// running the tool. ClangTool(const CompilationDatabase &Compilations, ArrayRef SourcePaths, std::shared_ptr PCHContainerOps = std::make_shared(), IntrusiveRefCntPtr BaseFS = - llvm::vfs::getRealFileSystem()); + llvm::vfs::getRealFileSystem(), + IntrusiveRefCntPtr Files = nullptr); ~ClangTool(); diff --git a/lib/Tooling/DependencyScanning/DependencyScanningService.cpp b/lib/Tooling/DependencyScanning/DependencyScanningService.cpp index 48aa68218c..6ddce0dcee 100644 --- a/lib/Tooling/DependencyScanning/DependencyScanningService.cpp +++ b/lib/Tooling/DependencyScanning/DependencyScanningService.cpp @@ -12,5 +12,6 @@ using namespace clang; using namespace tooling; using namespace dependencies; -DependencyScanningService::DependencyScanningService(ScanningMode Mode) - : Mode(Mode) {} +DependencyScanningService::DependencyScanningService(ScanningMode Mode, + bool ReuseFileManager) + : Mode(Mode), ReuseFileManager(ReuseFileManager) {} diff --git a/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp b/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp index c80a55645e..2d49e0d794 100644 --- a/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp +++ b/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp @@ -148,6 +148,8 @@ DependencyScanningWorker::DependencyScanningWorker( if (Service.getMode() == ScanningMode::MinimizedSourcePreprocessing) DepFS = new DependencyScanningWorkerFilesystem(Service.getSharedCache(), RealFS); + if (Service.canReuseFileManager()) + Files = new FileManager(FileSystemOptions(), RealFS); } llvm::Expected @@ -164,7 +166,7 @@ DependencyScanningWorker::getDependencyFile(const std::string &Input, /// Create the tool that uses the underlying file system to ensure that any /// file system requests that are made by the driver do not go through the /// dependency scanning filesystem. - tooling::ClangTool Tool(CDB, Input, PCHContainerOps, RealFS); + tooling::ClangTool Tool(CDB, Input, PCHContainerOps, RealFS, Files); Tool.clearArgumentsAdjusters(); Tool.setRestoreWorkingDir(false); Tool.setPrintErrorMessage(false); diff --git a/lib/Tooling/Tooling.cpp b/lib/Tooling/Tooling.cpp index 8c0d13d243..472a3ab57c 100644 --- a/lib/Tooling/Tooling.cpp +++ b/lib/Tooling/Tooling.cpp @@ -378,16 +378,20 @@ bool FrontendActionFactory::runInvocation( ClangTool::ClangTool(const CompilationDatabase &Compilations, ArrayRef SourcePaths, std::shared_ptr PCHContainerOps, - IntrusiveRefCntPtr BaseFS) + IntrusiveRefCntPtr BaseFS, + IntrusiveRefCntPtr Files) : Compilations(Compilations), SourcePaths(SourcePaths), PCHContainerOps(std::move(PCHContainerOps)), OverlayFileSystem(new llvm::vfs::OverlayFileSystem(std::move(BaseFS))), InMemoryFileSystem(new llvm::vfs::InMemoryFileSystem), - Files(new FileManager(FileSystemOptions(), OverlayFileSystem)) { + Files(Files ? Files + : new FileManager(FileSystemOptions(), OverlayFileSystem)) { OverlayFileSystem->pushOverlay(InMemoryFileSystem); appendArgumentsAdjuster(getClangStripOutputAdjuster()); appendArgumentsAdjuster(getClangSyntaxOnlyAdjuster()); appendArgumentsAdjuster(getClangStripDependencyFileAdjuster()); + if (Files) + Files->setVirtualFileSystem(OverlayFileSystem); } ClangTool::~ClangTool() = default; diff --git a/test/ClangScanDeps/Inputs/subframework_header_dir_symlink_cdb.json b/test/ClangScanDeps/Inputs/subframework_header_dir_symlink_cdb.json new file mode 100644 index 0000000000..a405c6b3af --- /dev/null +++ b/test/ClangScanDeps/Inputs/subframework_header_dir_symlink_cdb.json @@ -0,0 +1,12 @@ +[ +{ + "directory": "DIR", + "command": "clang -E DIR/subframework_header_dir_symlink.m -D EMPTY -iframework Inputs/frameworks", + "file": "DIR/subframework_header_dir_symlink.m" +}, +{ + "directory": "DIR", + "command": "clang -E DIR/subframework_header_dir_symlink2.m -FInputs/frameworks_symlink -iframework Inputs/frameworks", + "file": "DIR/subframework_header_dir_symlink2.m" +} +] diff --git a/test/ClangScanDeps/Inputs/symlink_cdb.json b/test/ClangScanDeps/Inputs/symlink_cdb.json new file mode 100644 index 0000000000..43bb418adb --- /dev/null +++ b/test/ClangScanDeps/Inputs/symlink_cdb.json @@ -0,0 +1,12 @@ +[ +{ + "directory": "DIR", + "command": "clang -E DIR/symlink.cpp -IInputs", + "file": "DIR/symlink.cpp" +}, +{ + "directory": "DIR", + "command": "clang -E DIR/symlink2.cpp -IInputs", + "file": "DIR/symlink2.cpp" +} +] diff --git a/test/ClangScanDeps/subframework_header_dir_symlink.m b/test/ClangScanDeps/subframework_header_dir_symlink.m new file mode 100644 index 0000000000..5cc17851e7 --- /dev/null +++ b/test/ClangScanDeps/subframework_header_dir_symlink.m @@ -0,0 +1,25 @@ +// REQUIRES: shell +// RUN: rm -rf %t.dir +// RUN: rm -rf %t.cdb +// RUN: mkdir -p %t.dir +// RUN: cp %s %t.dir/subframework_header_dir_symlink.m +// RUN: cp %s %t.dir/subframework_header_dir_symlink2.m +// RUN: mkdir %t.dir/Inputs +// RUN: cp -R %S/Inputs/frameworks %t.dir/Inputs/frameworks +// RUN: ln -s %t.dir/Inputs/frameworks %t.dir/Inputs/frameworks_symlink +// RUN: sed -e "s|DIR|%/t.dir|g" %S/Inputs/subframework_header_dir_symlink_cdb.json > %t.cdb +// RUN: clang-scan-deps -compilation-database %t.cdb -j 1 -reuse-filemanager=0 | \ +// RUN: FileCheck %s +// FIXME: Make this work when the filemanager is reused: +// RUN: clang-scan-deps -compilation-database %t.cdb -j 1 -reuse-filemanager=1 | \ +// RUN: not FileCheck %s + +#ifndef EMPTY +#include "Framework/Framework.h" +#endif + +// CHECK: clang-scan-deps dependency +// CHECK-NEXT: subframework_header_dir_symlink.m +// CHECK: clang-scan-deps dependency +// CHECK-NEXT: subframework_header_dir_symlink.m +// CHECK-NEXT: Inputs{{/|\\}}frameworks_symlink{{/|\\}}Framework.framework{{/|\\}}Headers{{/|\\}}Framework.h diff --git a/test/ClangScanDeps/symlink.cpp b/test/ClangScanDeps/symlink.cpp new file mode 100644 index 0000000000..e1a6ac931a --- /dev/null +++ b/test/ClangScanDeps/symlink.cpp @@ -0,0 +1,23 @@ +// REQUIRES: shell +// RUN: rm -rf %t.dir +// RUN: rm -rf %t.cdb +// RUN: mkdir -p %t.dir +// RUN: cp %s %t.dir/symlink.cpp +// RUN: cp %s %t.dir/symlink2.cpp +// RUN: mkdir %t.dir/Inputs +// RUN: cp %S/Inputs/header.h %t.dir/Inputs/header.h +// RUN: ln -s %t.dir/Inputs/header.h %t.dir/Inputs/symlink.h +// RUN: sed -e "s|DIR|%/t.dir|g" %S/Inputs/symlink_cdb.json > %t.cdb +// RUN: clang-scan-deps -compilation-database %t.cdb -j 1 -reuse-filemanager=0 | FileCheck %s +// RUN: clang-scan-deps -compilation-database %t.cdb -j 1 -reuse-filemanager=1 | FileCheck %s + +#include "symlink.h" +#include "header.h" + +// CHECK: symlink.cpp +// CHECK-NEXT: Inputs{{/|\\}}symlink.h +// CHECK-NEXT: Inputs{{/|\\}}header.h + +// CHECK: symlink2.cpp +// CHECK-NEXT: Inputs{{/|\\}}symlink.h +// CHECK-NEXT: Inputs{{/|\\}}header.h diff --git a/tools/clang-scan-deps/ClangScanDeps.cpp b/tools/clang-scan-deps/ClangScanDeps.cpp index b838845c44..5e567fef9d 100644 --- a/tools/clang-scan-deps/ClangScanDeps.cpp +++ b/tools/clang-scan-deps/ClangScanDeps.cpp @@ -107,6 +107,11 @@ llvm::cl::opt llvm::cl::desc("Compilation database"), llvm::cl::Required, llvm::cl::cat(DependencyScannerCategory)); +llvm::cl::opt ReuseFileManager( + "reuse-filemanager", + llvm::cl::desc("Reuse the file manager and its cache between invocations."), + llvm::cl::init(true), llvm::cl::cat(DependencyScannerCategory)); + } // end anonymous namespace int main(int argc, const char **argv) { @@ -153,7 +158,7 @@ int main(int argc, const char **argv) { // Print out the dependency results to STDOUT by default. SharedStream DependencyOS(llvm::outs()); - DependencyScanningService Service(ScanMode); + DependencyScanningService Service(ScanMode, ReuseFileManager); #if LLVM_ENABLE_THREADS unsigned NumWorkers = NumThreads == 0 ? llvm::hardware_concurrency() : NumThreads;