[Lldb-commits] [lldb] 9c5b975 - [lldb] Report clang module build remarks

Dave Lee via lldb-commits lldb-commits at lists.llvm.org
Fri Dec 16 13:49:34 PST 2022


Author: Dave Lee
Date: 2022-12-16T13:49:17-08:00
New Revision: 9c5b97570502c5c6648730f75d097910ae2faa22

URL: https://github.com/llvm/llvm-project/commit/9c5b97570502c5c6648730f75d097910ae2faa22
DIFF: https://github.com/llvm/llvm-project/commit/9c5b97570502c5c6648730f75d097910ae2faa22.diff

LOG: [lldb] Report clang module build remarks

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.

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

Added: 
    lldb/test/API/functionalities/progress_reporting/clang_modules/Makefile
    lldb/test/API/functionalities/progress_reporting/clang_modules/MyModule.h
    lldb/test/API/functionalities/progress_reporting/clang_modules/TestClangModuleBuildProgress.py
    lldb/test/API/functionalities/progress_reporting/clang_modules/main.m
    lldb/test/API/functionalities/progress_reporting/clang_modules/module.modulemap

Modified: 
    lldb/source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.cpp

Removed: 
    


################################################################################
diff  --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.cpp
index eea21f3f05fc9..2b98fc83097a2 100644
--- a/lldb/source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.cpp
+++ b/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"
@@ -15,7 +18,9 @@
 #include "clang/Parse/Parser.h"
 #include "clang/Sema/Lookup.h"
 #include "clang/Serialization/ASTReader.h"
+#include "llvm/ADT/StringRef.h"
 #include "llvm/Support/FileSystem.h"
+#include "llvm/Support/FormatVariadic.h"
 #include "llvm/Support/Path.h"
 #include "llvm/Support/Threading.h"
 
@@ -25,6 +30,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 +67,9 @@ class StoringDiagnosticConsumer : public clang::DiagnosticConsumer {
   void EndSourceFile() override;
 
 private:
+  bool HandleModuleRemark(const clang::Diagnostic &info);
+  void SetCurrentModuleProgress(llvm::StringRef module_name);
+
   typedef std::pair<clang::DiagnosticsEngine::Level, std::string>
       IDAndDiagnostic;
   std::vector<IDAndDiagnostic> m_diagnostics;
@@ -72,6 +81,9 @@ class StoringDiagnosticConsumer : public clang::DiagnosticConsumer {
   /// Output string filled by m_os. Will be reused for 
diff erent diagnostics.
   std::string m_output;
   Log *m_log;
+  /// A Progress with explicitly managed lifetime.
+  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 +152,9 @@ StoringDiagnosticConsumer::StoringDiagnosticConsumer() {
 
 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 +185,54 @@ void StoringDiagnosticConsumer::BeginSourceFile(
 }
 
 void StoringDiagnosticConsumer::EndSourceFile() {
+  m_current_progress_up = 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);
+    SetCurrentModuleProgress(module_name);
+    m_module_build_stack.push_back(module_name);
+
+    const auto &module_path = info.getArgStdStr(1);
+    LLDB_LOG(log, "Building Clang module {0} as {1}", module_name, module_path);
+    return true;
+  }
+  case clang::diag::remark_module_build_done: {
+    // The current module is done.
+    m_module_build_stack.pop_back();
+    if (m_module_build_stack.empty()) {
+      m_current_progress_up = nullptr;
+    } else {
+      // Update the progress to re-show the module that was currently being
+      // built from the time the now completed module was originally began.
+      const auto &resumed_module_name = m_module_build_stack.back();
+      SetCurrentModuleProgress(resumed_module_name);
+    }
+
+    const auto &module_name = info.getArgStdStr(0);
+    LLDB_LOG(log, "Finished building Clang module {0}", module_name);
+    return true;
+  }
+  default:
+    return false;
+  }
+}
+
+void StoringDiagnosticConsumer::SetCurrentModuleProgress(
+    llvm::StringRef module_name) {
+  // Ensure the ordering of:
+  //   1. Completing the existing progress event.
+  //   2. Beginining a new progress event.
+  m_current_progress_up = nullptr;
+  m_current_progress_up = std::make_unique<Progress>(
+      llvm::formatv("Currently building module {0}", module_name));
+}
+
 ClangModulesDeclVendor::ClangModulesDeclVendor()
     : ClangDeclVendor(eClangModuleDeclVendor) {}
 
@@ -610,7 +670,8 @@ ClangModulesDeclVendor::Create(Target &target) {
       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 +709,18 @@ ClangModulesDeclVendor::Create(Target &target) {
     }
   }
 
-  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(),

diff  --git a/lldb/test/API/functionalities/progress_reporting/clang_modules/Makefile b/lldb/test/API/functionalities/progress_reporting/clang_modules/Makefile
new file mode 100644
index 0000000000000..4ad4c54783a46
--- /dev/null
+++ b/lldb/test/API/functionalities/progress_reporting/clang_modules/Makefile
@@ -0,0 +1,4 @@
+OBJC_SOURCES := main.m
+CFLAGS_EXTRAS = -fmodules -I$(BUILDDIR)
+
+include Makefile.rules

diff  --git a/lldb/test/API/functionalities/progress_reporting/clang_modules/MyModule.h b/lldb/test/API/functionalities/progress_reporting/clang_modules/MyModule.h
new file mode 100644
index 0000000000000..ab96a103ec4ec
--- /dev/null
+++ b/lldb/test/API/functionalities/progress_reporting/clang_modules/MyModule.h
@@ -0,0 +1 @@
+extern int doesNotActuallyExist;

diff  --git a/lldb/test/API/functionalities/progress_reporting/clang_modules/TestClangModuleBuildProgress.py b/lldb/test/API/functionalities/progress_reporting/clang_modules/TestClangModuleBuildProgress.py
new file mode 100644
index 0000000000000..af0b59cd555f1
--- /dev/null
+++ b/lldb/test/API/functionalities/progress_reporting/clang_modules/TestClangModuleBuildProgress.py
@@ -0,0 +1,46 @@
+"""
+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 = self.getBuildArtifact("new-modules")
+        if os.path.isdir(mod_cache):
+            shutil.rmtree(mod_cache)
+        self.runCmd(f"settings set symbols.clang-modules-cache-path '{mod_cache}'")
+
+        # TODO: The need for this seems like a bug.
+        self.runCmd(
+            f"settings set target.clang-module-search-paths '{self.getSourceDir()}'"
+        )
+
+        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("expression @import MyModule")
+
+        event = lldbutil.fetch_next_event(self, listener, broadcaster)
+        payload = lldb.SBDebugger.GetProgressFromEvent(event)
+        message = payload[0]
+        self.assertEqual(message, "Currently building module MyModule")

diff  --git a/lldb/test/API/functionalities/progress_reporting/clang_modules/main.m b/lldb/test/API/functionalities/progress_reporting/clang_modules/main.m
new file mode 100644
index 0000000000000..237c8ce181774
--- /dev/null
+++ b/lldb/test/API/functionalities/progress_reporting/clang_modules/main.m
@@ -0,0 +1 @@
+int main() {}

diff  --git a/lldb/test/API/functionalities/progress_reporting/clang_modules/module.modulemap b/lldb/test/API/functionalities/progress_reporting/clang_modules/module.modulemap
new file mode 100644
index 0000000000000..88caf2cb678ff
--- /dev/null
+++ b/lldb/test/API/functionalities/progress_reporting/clang_modules/module.modulemap
@@ -0,0 +1,4 @@
+module MyModule {
+  header "MyModule.h"
+  export *
+}


        


More information about the lldb-commits mailing list