mirror of
https://github.com/intel/llvm.git
synced 2026-01-26 03:56:16 +08:00
[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
This commit is contained in:
@@ -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 @@ public:
|
||||
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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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.
|
||||
|
||||
Reference in New Issue
Block a user