kastiglione created this revision. kastiglione added reviewers: JDevlieghere, aprantl, mib. Herald added a project: All. kastiglione requested review of this revision. Herald added a project: LLDB. Herald added a subscriber: lldb-commits.
Update the Clang diagnostic consumer (in ClangModulesDeclVendor) to report progress on Clang module builds, as both progress events and expression logs. Module build remarks are enabled by with clang's `-Rmodule-build` flag. With this change, command line users of lldb will see progress events showing which modules are being built, and - by how long they stay on screen - how much time it takes to build them. IDEs that show progress events can show these updates if desired. This does not show module-import remarks, although that may be added as a future change. Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D140056 Files: lldb/source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.cpp lldb/test/API/functionalities/progress_reporting/clang_modules/Makefile lldb/test/API/functionalities/progress_reporting/clang_modules/TestClangModuleBuildProgress.py lldb/test/API/functionalities/progress_reporting/clang_modules/main.m
Index: lldb/test/API/functionalities/progress_reporting/clang_modules/main.m =================================================================== --- /dev/null +++ lldb/test/API/functionalities/progress_reporting/clang_modules/main.m @@ -0,0 +1,3 @@ +@import Foundation; + +int main() {} Index: lldb/test/API/functionalities/progress_reporting/clang_modules/TestClangModuleBuildProgress.py =================================================================== --- /dev/null +++ lldb/test/API/functionalities/progress_reporting/clang_modules/TestClangModuleBuildProgress.py @@ -0,0 +1,41 @@ +""" +Test clang module build progress events. +""" +import os +import shutil + +import lldb +import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * + + +class TestCase(TestBase): + @skipUnlessDarwin + def test_clang_module_build_progress_report(self): + """Test receipt of progress events for clang module builds""" + self.build() + + # Ensure an empty module cache. + mod_cache = os.path.join(self.getBuildDir(), "new-modules") + if os.path.isdir(mod_cache): + shutil.rmtree(mod_cache) + self.runCmd(f"settings set symbols.clang-modules-cache-path {mod_cache}") + + lldbutil.run_to_name_breakpoint(self, "main") + + # Just before triggering module builds, start listening for progress + # events. Listening any earlier would result in a queue filled with + # other unrelated progress events. + broadcaster = self.dbg.GetBroadcaster() + listener = lldbutil.start_listening_from( + broadcaster, lldb.SBDebugger.eBroadcastBitProgress + ) + + # Trigger module builds. + self.expect("p @2") + + event = lldbutil.fetch_next_event(self, listener, broadcaster) + payload = lldb.SBDebugger.GetProgressFromEvent(event) + message = payload[0] + self.assertEqual(message, "Currently building module Foundation") Index: lldb/test/API/functionalities/progress_reporting/clang_modules/Makefile =================================================================== --- /dev/null +++ lldb/test/API/functionalities/progress_reporting/clang_modules/Makefile @@ -0,0 +1,5 @@ +OBJC_SOURCES := main.m +CFLAGS_EXTRAS := -fmodules +LD_EXTRAS := -framework Foundation + +include Makefile.rules Index: lldb/source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.cpp =================================================================== --- lldb/source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.cpp +++ lldb/source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.cpp @@ -6,6 +6,9 @@ // //===----------------------------------------------------------------------===// +#include "clang/Basic/Diagnostic.h" +#include "clang/Basic/DiagnosticFrontend.h" +#include "clang/Basic/DiagnosticSerialization.h" #include "clang/Basic/TargetInfo.h" #include "clang/Frontend/CompilerInstance.h" #include "clang/Frontend/FrontendActions.h" @@ -16,6 +19,7 @@ #include "clang/Sema/Lookup.h" #include "clang/Serialization/ASTReader.h" #include "llvm/Support/FileSystem.h" +#include "llvm/Support/FormatVariadic.h" #include "llvm/Support/Path.h" #include "llvm/Support/Threading.h" @@ -25,6 +29,7 @@ #include "Plugins/TypeSystem/Clang/TypeSystemClang.h" #include "lldb/Core/ModuleList.h" +#include "lldb/Core/Progress.h" #include "lldb/Host/Host.h" #include "lldb/Host/HostInfo.h" #include "lldb/Symbol/CompileUnit.h" @@ -61,6 +66,8 @@ void EndSourceFile() override; private: + bool HandleModuleRemark(const clang::Diagnostic &info); + typedef std::pair<clang::DiagnosticsEngine::Level, std::string> IDAndDiagnostic; std::vector<IDAndDiagnostic> m_diagnostics; @@ -72,6 +79,8 @@ /// Output string filled by m_os. Will be reused for different diagnostics. std::string m_output; Log *m_log; + std::unique_ptr<Progress> m_current_progress_up; + std::vector<std::string> m_module_build_stack; }; /// The private implementation of our ClangModulesDeclVendor. Contains all the @@ -140,6 +149,9 @@ void StoringDiagnosticConsumer::HandleDiagnostic( clang::DiagnosticsEngine::Level DiagLevel, const clang::Diagnostic &info) { + if (HandleModuleRemark(info)) + return; + // Print the diagnostic to m_output. m_output.clear(); m_diag_printer->HandleDiagnostic(DiagLevel, info); @@ -170,9 +182,42 @@ } void StoringDiagnosticConsumer::EndSourceFile() { + m_current_progress_up.reset(nullptr); m_diag_printer->EndSourceFile(); } +bool StoringDiagnosticConsumer::HandleModuleRemark( + const clang::Diagnostic &info) { + Log *log = GetLog(LLDBLog::Expressions); + switch (info.getID()) { + case clang::diag::remark_module_build: { + const auto &module_name = info.getArgStdStr(0); + const auto &module_file_name = info.getArgStdStr(1); + m_module_build_stack.push_back(module_name); + // End the previous event before starting a new event. + m_current_progress_up.reset(nullptr); + m_current_progress_up.reset(new Progress( + llvm::formatv("Currently building module {0}", module_name))); + LLDB_LOG(log, "Building Clang module {0} as {1}", module_name, + module_file_name); + return true; + } + case clang::diag::remark_module_build_done: { + const auto &module_name = info.getArgStdStr(0); + const auto &parent_module_name = m_module_build_stack.back(); + // End the previous event before starting a new event. + m_current_progress_up.reset(nullptr); + m_current_progress_up.reset(new Progress( + llvm::formatv("Currently building module {0}", parent_module_name))); + LLDB_LOG(log, "Finished building Clang module {0}", module_name); + m_module_build_stack.pop_back(); + return true; + } + default: + return false; + } +} + ClangModulesDeclVendor::ClangModulesDeclVendor() : ClangDeclVendor(eClangModuleDeclVendor) {} @@ -610,7 +655,8 @@ arch.GetTriple().str(), "-fmodules-validate-system-headers", "-Werror=non-modular-include-in-framework-module", - "-Xclang=-fincremental-extensions"}; + "-Xclang=-fincremental-extensions", + "-Rmodule-build"}; target.GetPlatform()->AddClangModuleCompilationOptions( &target, compiler_invocation_arguments); @@ -648,16 +694,18 @@ } } - llvm::IntrusiveRefCntPtr<clang::DiagnosticsEngine> diagnostics_engine = - clang::CompilerInstance::createDiagnostics(new clang::DiagnosticOptions, - new StoringDiagnosticConsumer); - std::vector<const char *> compiler_invocation_argument_cstrs; compiler_invocation_argument_cstrs.reserve( compiler_invocation_arguments.size()); for (const std::string &arg : compiler_invocation_arguments) compiler_invocation_argument_cstrs.push_back(arg.c_str()); + auto diag_options_up = + clang::CreateAndPopulateDiagOpts(compiler_invocation_argument_cstrs); + llvm::IntrusiveRefCntPtr<clang::DiagnosticsEngine> diagnostics_engine = + clang::CompilerInstance::createDiagnostics(diag_options_up.release(), + new StoringDiagnosticConsumer); + Log *log = GetLog(LLDBLog::Expressions); LLDB_LOG(log, "ClangModulesDeclVendor's compiler flags {0:$[ ]}", llvm::make_range(compiler_invocation_arguments.begin(),
_______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits