[clang] 20b4f4f - [Driver] Add callback to Command execution

Serge Pavlov via cfe-commits cfe-commits at lists.llvm.org
Wed Nov 4 21:23:04 PST 2020


Author: Serge Pavlov
Date: 2020-11-05T12:21:40+07:00
New Revision: 20b4f4f76030f8712824c91b5f0b0a611476f747

URL: https://github.com/llvm/llvm-project/commit/20b4f4f76030f8712824c91b5f0b0a611476f747
DIFF: https://github.com/llvm/llvm-project/commit/20b4f4f76030f8712824c91b5f0b0a611476f747.diff

LOG: [Driver] Add callback to Command execution

Summary:
Object of type `Compilation` now can keep a callback that is called
after each execution of `Command`. This must simplify adaptation of
clang in custom distributions and allow facilities like collection of
execution statistics.

Reviewers: rsmith, rjmccall, Eugene.Zelenko

Subscribers: cfe-commits

Tags: #clang

Differential Revision: https://reviews.llvm.org/D78899

Added: 
    

Modified: 
    clang/include/clang/Driver/Compilation.h
    clang/lib/Driver/Compilation.cpp
    clang/unittests/Driver/ToolChainTest.cpp

Removed: 
    


################################################################################
diff  --git a/clang/include/clang/Driver/Compilation.h b/clang/include/clang/Driver/Compilation.h
index 70b901434487..89a43b5b7dc0 100644
--- a/clang/include/clang/Driver/Compilation.h
+++ b/clang/include/clang/Driver/Compilation.h
@@ -115,6 +115,11 @@ class Compilation {
   /// Optional redirection for stdin, stdout, stderr.
   std::vector<Optional<StringRef>> Redirects;
 
+  /// Callback called after compilation job has been finished.
+  /// Arguments of the callback are the compilation job as an instance of
+  /// class Command and the exit status of the corresponding child process.
+  std::function<void(const Command &, int)> PostCallback;
+
   /// Whether we're compiling for diagnostic purposes.
   bool ForDiagnostics = false;
 
@@ -212,6 +217,14 @@ class Compilation {
     return FailureResultFiles;
   }
 
+  /// Installs a handler that is executed when a compilation job is finished.
+  /// The arguments of the callback specify the compilation job as an instance
+  /// of class Command and the exit status of the child process executed that
+  /// job.
+  void setPostCallback(const std::function<void(const Command &, int)> &CB) {
+    PostCallback = CB;
+  }
+
   /// Returns the sysroot path.
   StringRef getSysRoot() const;
 

diff  --git a/clang/lib/Driver/Compilation.cpp b/clang/lib/Driver/Compilation.cpp
index 05ee5091396b..d33055739080 100644
--- a/clang/lib/Driver/Compilation.cpp
+++ b/clang/lib/Driver/Compilation.cpp
@@ -193,6 +193,8 @@ int Compilation::ExecuteCommand(const Command &C,
   std::string Error;
   bool ExecutionFailed;
   int Res = C.Execute(Redirects, &Error, &ExecutionFailed);
+  if (PostCallback)
+    PostCallback(C, Res);
   if (!Error.empty()) {
     assert(Res && "Error string set with 0 result code!");
     getDriver().Diag(diag::err_drv_command_failure) << Error;

diff  --git a/clang/unittests/Driver/ToolChainTest.cpp b/clang/unittests/Driver/ToolChainTest.cpp
index 227f7c76b8a1..35060563ab97 100644
--- a/clang/unittests/Driver/ToolChainTest.cpp
+++ b/clang/unittests/Driver/ToolChainTest.cpp
@@ -289,4 +289,28 @@ TEST(ToolChainTest, CommandOutput) {
   EXPECT_EQ("a.out", ExeFile);
 }
 
+TEST(ToolChainTest, PostCallback) {
+  IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts = new DiagnosticOptions();
+  IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs());
+  struct TestDiagnosticConsumer : public DiagnosticConsumer {};
+  DiagnosticsEngine Diags(DiagID, &*DiagOpts, new TestDiagnosticConsumer);
+  IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> InMemoryFileSystem(
+      new llvm::vfs::InMemoryFileSystem);
+
+  // The executable path must not exist.
+  Driver CCDriver("/home/test/bin/clang", "arm-linux-gnueabi", Diags,
+                  "clang LLVM compiler", InMemoryFileSystem);
+  CCDriver.setCheckInputsExist(false);
+  std::unique_ptr<Compilation> CC(
+      CCDriver.BuildCompilation({"/home/test/bin/clang", "foo.cpp"}));
+  bool CallbackHasCalled = false;
+  CC->setPostCallback(
+      [&](const Command &C, int Ret) { CallbackHasCalled = true; });
+  const JobList &Jobs = CC->getJobs();
+  auto &CmdCompile = Jobs.getJobs().front();
+  const Command *FailingCmd = nullptr;
+  CC->ExecuteCommand(*CmdCompile, FailingCmd);
+  EXPECT_TRUE(CallbackHasCalled);
+}
+
 } // end anonymous namespace.


        


More information about the cfe-commits mailing list