[clang-tools-extra] [clangd] [C++20] [Modules] Don't reuse prebuilt module files on windows (PR #193426)

Chuanqi Xu via cfe-commits cfe-commits at lists.llvm.org
Wed Apr 22 00:31:07 PDT 2026


https://github.com/ChuanqiXu9 created https://github.com/llvm/llvm-project/pull/193426

Fix https://github.com/clangd/clangd/issues/2497

Note that this only works for --experimental-modules-support. Otherwise, it is a natural fallback by the design clang based tools.

>From 8ce7a324eb9a3aa9890c466f882b94be94d65774 Mon Sep 17 00:00:00 2001
From: Chuanqi Xu <yedeng.yd at linux.alibaba.com>
Date: Wed, 22 Apr 2026 15:25:09 +0800
Subject: [PATCH] [clangd] [C++20] [Modules] Don't reuse prebuilt module files
 on windows

Fix https://github.com/clangd/clangd/issues/2497

Note that this only works for --experimental-modules-support. Otherwise,
it is a natural fallback by the design clang based tools.
---
 clang-tools-extra/clangd/ModulesBuilder.cpp   | 23 +++++++-
 .../test/prebuilt_module_file_reuse.test      | 58 +++++++++++++++++++
 2 files changed, 79 insertions(+), 2 deletions(-)
 create mode 100644 clang-tools-extra/clangd/test/prebuilt_module_file_reuse.test

diff --git a/clang-tools-extra/clangd/ModulesBuilder.cpp b/clang-tools-extra/clangd/ModulesBuilder.cpp
index c4a0c54a8fc2f..b7e4ebe314a76 100644
--- a/clang-tools-extra/clangd/ModulesBuilder.cpp
+++ b/clang-tools-extra/clangd/ModulesBuilder.cpp
@@ -29,6 +29,23 @@ llvm::cl::opt<bool> DebugModulesBuilder(
                    "Remember to remove them later after debugging."),
     llvm::cl::init(false));
 
+// Disable reusing prebuilt module files on windows by default.
+// As clangd may lock these module files on windows to prevent
+// these module files to be updated by buiild system on windows.
+//
+// See https://github.com/clangd/clangd/issues/2497 for details.
+#ifdef _WIN32
+constexpr bool DisablePrebuiltModuleFileReuseDefault = true;
+#else
+constexpr bool DisablePrebuiltModuleFileReuseDefault = false;
+#endif
+
+llvm::cl::opt<bool> DisablePrebuiltModuleFileReuse(
+    "disable-prebuilt-module-file-reuse",
+    llvm::cl::desc("Do not reuse prebuilt module files from existing build "
+                   "artifacts."),
+    llvm::cl::init(DisablePrebuiltModuleFileReuseDefault));
+
 // Create a path to store module files. Generally it should be:
 //
 //   {TEMP_DIRS}/clangd/module_files/{hashed-file-name}-%%-%%-%%-%%-%%-%%/.
@@ -92,8 +109,7 @@ class FailedPrerequisiteModules : public PrerequisiteModules {
 
   // We shouldn't adjust the compilation commands based on
   // FailedPrerequisiteModules.
-  void adjustHeaderSearchOptions(HeaderSearchOptions &Options) const override {
-  }
+  void adjustHeaderSearchOptions(HeaderSearchOptions &Options) const override {}
 
   // FailedPrerequisiteModules can never be reused.
   bool
@@ -561,6 +577,9 @@ class ModulesBuilder::ModulesBuilderImpl {
 void ModulesBuilder::ModulesBuilderImpl::getPrebuiltModuleFile(
     StringRef ModuleName, PathRef ModuleUnitFileName, const ThreadsafeFS &TFS,
     ReusablePrerequisiteModules &BuiltModuleFiles) {
+  if (DisablePrebuiltModuleFileReuse)
+    return;
+
   auto Cmd = getCDB().getCompileCommand(ModuleUnitFileName);
   if (!Cmd)
     return;
diff --git a/clang-tools-extra/clangd/test/prebuilt_module_file_reuse.test b/clang-tools-extra/clangd/test/prebuilt_module_file_reuse.test
new file mode 100644
index 0000000000000..bc0d667c77991
--- /dev/null
+++ b/clang-tools-extra/clangd/test/prebuilt_module_file_reuse.test
@@ -0,0 +1,58 @@
+# Check that clangd can optionally avoid reusing prebuilt module files.
+#
+# Windows uses a different default for this flag and has different escaping
+# modes, so keep this test non-Windows for now.
+# UNSUPPORTED: system-windows
+#
+# RUN: rm -fr %t
+# RUN: mkdir -p %t
+# RUN: split-file %s %t
+# RUN: sed -e "s|DIR|%/t|g" %t/compile_commands.json.tmpl > %t/compile_commands.json.tmp
+# RUN: sed -e "s|CLANG_CC|clang|g" %t/compile_commands.json.tmp > %t/compile_commands.json
+# RUN: clang -std=c++20 %t/M.cppm --precompile -o %t/M.pcm
+# RUN: clangd -enable-config=0 -experimental-modules-support -log=verbose \
+# RUN:   -compile-commands-dir=%t -check=%t/Use.cpp 2>&1 \
+# RUN:   | FileCheck %s --check-prefix=REUSE
+# RUN: clangd -enable-config=0 -experimental-modules-support -log=verbose \
+# RUN:   -compile-commands-dir=%t -check=%t/Use.cpp \
+# RUN:   --disable-prebuilt-module-file-reuse 2>&1 \
+# RUN:   | FileCheck %s --check-prefix=NOREUSE
+
+// REUSE: Built module M to [[PCM:.*clangd.*/module_files/.*/M\.pcm]]
+// REUSE: All checks completed, 0 errors
+
+// NOREUSE-NOT: Reusing prebuilt module file
+// NOREUSE: Built module M to [[BUILT:.*clangd.*/module_files/.*/M\.pcm]]
+// NOREUSE: All checks completed, 0 errors
+
+#--- M.cppm
+export module M;
+export int value() { return 42; }
+
+#--- A.cppm
+export module A;
+import M;
+export int useM() { return value(); }
+
+#--- Use.cpp
+import A;
+int use() { return useM(); }
+
+#--- compile_commands.json.tmpl
+[
+  {
+    "directory": "DIR",
+    "command": "CLANG_CC -std=c++20 DIR/M.cppm --precompile -o DIR/M-from-cdb.pcm",
+    "file": "DIR/M.cppm"
+  },
+  {
+    "directory": "DIR",
+    "command": "CLANG_CC -std=c++20 -fmodule-file=M=DIR/M.pcm DIR/A.cppm --precompile -o DIR/A-from-cdb.pcm",
+    "file": "DIR/A.cppm"
+  },
+  {
+    "directory": "DIR",
+    "command": "CLANG_CC -std=c++20 -fprebuilt-module-path=DIR -c DIR/Use.cpp -o DIR/Use.o",
+    "file": "DIR/Use.cpp"
+  }
+]



More information about the cfe-commits mailing list