https://github.com/qiongsiwu updated 
https://github.com/llvm/llvm-project/pull/211966

>From ea846f6154f0c1fa11bd65996ce1b4b6811559e1 Mon Sep 17 00:00:00 2001
From: Qiongsi Wu <[email protected]>
Date: Fri, 24 Jul 2026 16:13:14 -0700
Subject: [PATCH] Add a clang driver option to enable dependency scanning
 logging.

---
 clang/include/clang/Basic/AtomicLineLogger.h  |  9 ++-
 .../DependencyScanningWorker.h                |  2 +
 clang/include/clang/Options/Options.td        |  7 ++
 clang/lib/Basic/AtomicLineLogger.cpp          | 76 ++++++++++++++-----
 clang/lib/Tooling/DependencyScanningTool.cpp  |  3 +
 .../test/ClangScanDeps/logging-driver-flag.c  | 26 +++++++
 6 files changed, 101 insertions(+), 22 deletions(-)
 create mode 100644 clang/test/ClangScanDeps/logging-driver-flag.c

diff --git a/clang/include/clang/Basic/AtomicLineLogger.h 
b/clang/include/clang/Basic/AtomicLineLogger.h
index 3d06ddfce0262..ddcd5993b060e 100644
--- a/clang/include/clang/Basic/AtomicLineLogger.h
+++ b/clang/include/clang/Basic/AtomicLineLogger.h
@@ -19,6 +19,7 @@
 #include "llvm/ADT/SmallString.h"
 #include "llvm/Support/raw_ostream.h"
 #include <atomic>
+#include <mutex>
 #include <optional>
 #include <string>
 
@@ -60,9 +61,11 @@ class LogLine {
 };
 
 class AtomicLineLogger {
-  int FD = -1;
+  std::atomic<int> FD{-1};
   std::string LogPath;
   std::atomic<uint64_t> DroppedLines{0};
+  std::mutex EnableMtx;
+  bool WarnedConflict = false;
 
 public:
   AtomicLineLogger() {}
@@ -75,6 +78,10 @@ class AtomicLineLogger {
 
   ~AtomicLineLogger();
 
+  // Enables the logger if it is not already enabled. Thread safe.
+  // If the logger is already enabled, call to enable is a no-op.
+  void enable(StringRef LogFilePath);
+
   LogLine log();
 };
 
diff --git a/clang/include/clang/DependencyScanning/DependencyScanningWorker.h 
b/clang/include/clang/DependencyScanning/DependencyScanningWorker.h
index 638c317d9ce64..2c5c7fbb8f9a0 100644
--- a/clang/include/clang/DependencyScanning/DependencyScanningWorker.h
+++ b/clang/include/clang/DependencyScanning/DependencyScanningWorker.h
@@ -90,6 +90,8 @@ class DependencyScanningWorker {
     return TracingFS.get();
   }
 
+  DependencyScanningService &getService() const { return Service; }
+
   // MaxNumOfByNameQueries is the upper limit of the number of names the 
by-name
   // scanning API (computeDependenciesByName) can drain per call. At the time 
of
   // this commit, the estimated number of total unique importable names is
diff --git a/clang/include/clang/Options/Options.td 
b/clang/include/clang/Options/Options.td
index cf66ee3e52f2d..f8651a7bc42a5 100644
--- a/clang/include/clang/Options/Options.td
+++ b/clang/include/clang/Options/Options.td
@@ -3781,6 +3781,13 @@ def fno_modules_driver :
   Group<f_Group>,
   Visibility<[ClangOption]>,
   HelpText<"Disable support for driver managed module builds (experimental)">;
+def fdepscan_log_path : Joined<["-"], "fdepscan-log-path=">,
+  Group<f_Group>,
+  Visibility<[ClangOption]>,
+  Flags<[NoArgumentUnused]>,
+  MetaVarName<"<file>">,
+  HelpText<"Log the timing of dependency scanning actions to <file>. Only "
+           "takes effect while running the dependency scanner.">;
 
 def fincremental_extensions :
   Flag<["-"], "fincremental-extensions">,
diff --git a/clang/lib/Basic/AtomicLineLogger.cpp 
b/clang/lib/Basic/AtomicLineLogger.cpp
index dc0f2bf5adc6c..4bf26f0cb756d 100644
--- a/clang/lib/Basic/AtomicLineLogger.cpp
+++ b/clang/lib/Basic/AtomicLineLogger.cpp
@@ -41,20 +41,43 @@ static uint64_t getTimestampMillis() {
 #endif
 }
 
+#ifdef _WIN32
+// Write to files opened with OF_Append may not be guaranteed to be atomic
+// on Windows. Both openLogFile and writeLineToFD are noops on Windows.
+static int openLogFile(StringRef Path) {
+  (void)Path;
+  return -1;
+}
+
+static bool writeLineToFD(int FD, const char *Data, size_t Size) {
+  (void)FD, (void)Data, (void)Size;
+  return false;
+}
+
+#else
+
+static int openLogFile(StringRef Path) {
+  int FD = -1;
+  std::error_code EC = llvm::sys::fs::openFileForWrite(
+      Path, FD, llvm::sys::fs::CD_OpenAlways, llvm::sys::fs::OF_Append);
+  if (EC) {
+    llvm::errs() << "warning: unable to open log file '" << Path
+                 << "': " << EC.message() << "\n";
+    return -1;
+  }
+  return FD;
+}
+
 // Writes the whole line into an FD that is opened with OF_Append.
 // This function only does one write (up to retry due to interrupts), and the
 // single write is blocking and atomic on POSIX systems.
 static bool writeLineToFD(int FD, const char *Data, size_t Size) {
-#ifndef _WIN32
   ssize_t Written = llvm::sys::RetryAfterSignal(-1, write, FD, Data, Size);
   return Written >= 0 && (static_cast<size_t>(Written) == Size);
-#else
-  (void)FD, (void)Data, (void)Size;
-  llvm_unreachable("Logging not supported on Windows!");
-  return false;
-#endif
 }
 
+#endif
+
 LogLine::LogLine(int FD, std::atomic<uint64_t> *DroppedLines)
     : FormattingOS(Buffer), FD(FD), DroppedLines(DroppedLines) {
   auto Millis = getTimestampMillis();
@@ -83,33 +106,44 @@ LogLine::~LogLine() {
     DroppedLines->fetch_add(1, std::memory_order_relaxed);
 }
 
-AtomicLineLogger::AtomicLineLogger(StringRef LogFilePath)
-    : LogPath(LogFilePath.str()) {
-#ifndef _WIN32
+AtomicLineLogger::AtomicLineLogger(StringRef LogFilePath) {
   if (LogFilePath.empty())
     return;
+  LogPath = LogFilePath.str();
+  FD.store(openLogFile(LogFilePath), std::memory_order_release);
+}
 
-  std::error_code EC = llvm::sys::fs::openFileForWrite(
-      LogFilePath, FD, llvm::sys::fs::CD_OpenAlways, llvm::sys::fs::OF_Append);
-  if (EC) {
-    llvm::errs() << "warning: unable to open log file '" << LogFilePath
-                 << "': " << EC.message() << "\n";
-    FD = -1;
+void AtomicLineLogger::enable(StringRef LogFilePath) {
+  if (LogFilePath.empty())
+    return;
+  std::lock_guard<std::mutex> Lock(EnableMtx);
+  if (FD.load(std::memory_order_relaxed) != -1) {
+    if (LogFilePath != LogPath && !WarnedConflict) {
+      llvm::errs() << "warning: dependency scanning log path '" << LogFilePath
+                   << "' ignored; already logging to '" << LogPath << "'\n";
+      WarnedConflict = true;
+    }
     return;
   }
-#endif
-  // Write to files opened with OF_Append may not be guaranteed to be atomic
-  // on Windows, so we do not enable logging on Windows.
+
+  int NewFD = openLogFile(LogFilePath);
+  if (NewFD == -1)
+    return;
+  LogPath = LogFilePath.str();
+  FD.store(NewFD, std::memory_order_relaxed);
+  return;
 }
 
 LogLine AtomicLineLogger::log() {
-  if (FD != -1)
-    return LogLine(FD, &DroppedLines);
+  int CurFD = FD.load(std::memory_order_relaxed);
+  if (CurFD != -1)
+    return LogLine(CurFD, &DroppedLines);
   return LogLine();
 }
 
 AtomicLineLogger::~AtomicLineLogger() {
-  if (FD == -1)
+  int CurFD = FD.load(std::memory_order_relaxed);
+  if (CurFD == -1)
     return;
   if (uint64_t Dropped = DroppedLines.load(std::memory_order_relaxed))
     llvm::errs() << "warning: log '" << LogPath
diff --git a/clang/lib/Tooling/DependencyScanningTool.cpp 
b/clang/lib/Tooling/DependencyScanningTool.cpp
index b3332d9d49cd8..3a649c7f2994e 100644
--- a/clang/lib/Tooling/DependencyScanningTool.cpp
+++ b/clang/lib/Tooling/DependencyScanningTool.cpp
@@ -15,6 +15,7 @@
 #include "clang/Driver/Tool.h"
 #include "clang/Frontend/CompilerInstance.h"
 #include "clang/Frontend/Utils.h"
+#include "clang/Options/Options.h"
 #include "llvm/ADT/SmallVectorExtras.h"
 #include "llvm/ADT/iterator.h"
 #include "llvm/TargetParser/Host.h"
@@ -160,6 +161,8 @@ static bool computeDependenciesForDriverCommandLine(
   if (!Compilation)
     return false;
 
+  Worker.getService().getLogger().enable(
+      Compilation->getArgs().getLastArgValue(options::OPT_fdepscan_log_path));
   SmallVector<SmallVector<std::string, 0>> FrontendCommandLines;
   for (const auto &Cmd : Compilation->getJobs())
     FrontendCommandLines.push_back(buildCC1CommandLine(Cmd));
diff --git a/clang/test/ClangScanDeps/logging-driver-flag.c 
b/clang/test/ClangScanDeps/logging-driver-flag.c
new file mode 100644
index 0000000000000..6578f04b1cd4e
--- /dev/null
+++ b/clang/test/ClangScanDeps/logging-driver-flag.c
@@ -0,0 +1,26 @@
+// UNSUPPORTED: system-windows
+// RUN: rm -rf %t
+// RUN: split-file %s %t
+// RUN: sed -e "s|DIR|%/t|g" %t/cdb.json.template > %t/cdb.json
+
+// RUN: clang-scan-deps -compilation-database %t/cdb.json \
+// RUN:   -format experimental-full -j 1 -o %t/deps.json
+// RUN: FileCheck %s --input-file %t/scan.log
+
+// CHECK: [{{[0-9]+\.[0-9]+}}] [[#PID:]] [[#TID:]]: starting scanning 
command:{{.*}}tu.c
+// CHECK: [{{[0-9]+\.[0-9]+}}] {{.*}}: pcm_write: {{.*}}.pcm
+// CHECK: [{{[0-9]+\.[0-9]+}}] {{.*}}: finished scanning command:{{.*}}tu.c
+//--- cdb.json.template
+[{
+  "directory": "DIR",
+  "command": "clang -fsyntax-only DIR/tu.c -fmodules -fimplicit-module-maps 
-fmodules-cache-path=DIR/cache -fbuild-session-timestamp=1 
-fmodules-validate-once-per-build-session -fdepscan-log-path=DIR/scan.log",
+  "file": "DIR/tu.c"
+}]
+
+//--- module.modulemap
+module A { header "A.h" }
+//--- A.h
+void A_func(void);
+//--- tu.c
+#include "A.h"
+void foo(void) { A_func(); }

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to