[clang] Support '-fmodule-file-home-is-cwd' for C++ modules. (PR #135147)

via cfe-commits cfe-commits at lists.llvm.org
Thu Apr 10 02:13:03 PDT 2025


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-clang-modules

Author: Michael Park (mpark)

<details>
<summary>Changes</summary>

`-fmodule-file-home-is-cwd` was added in https://github.com/llvm/llvm-project/commit/646e502de0d854cb3ecaca90ab52bebfe59a40cd to support relocatable PCMs for Clang modules. This PR extends the functionality to allow standard C++ modules to be relocatable.

---
Full diff: https://github.com/llvm/llvm-project/pull/135147.diff


2 Files Affected:

- (modified) clang/lib/Serialization/ASTWriter.cpp (+35-33) 
- (added) clang/test/Modules/relocatable-modules.cpp (+43) 


``````````diff
diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp
index a48c05061626a..ae771f8f014e4 100644
--- a/clang/lib/Serialization/ASTWriter.cpp
+++ b/clang/lib/Serialization/ASTWriter.cpp
@@ -1493,42 +1493,44 @@ void ASTWriter::WriteControlBlock(Preprocessor &PP, StringRef isysroot) {
     unsigned AbbrevCode = Stream.EmitAbbrev(std::move(Abbrev));
     RecordData::value_type Record[] = {MODULE_NAME};
     Stream.EmitRecordWithBlob(AbbrevCode, Record, WritingModule->Name);
-  }
 
-  if (WritingModule && WritingModule->Directory) {
-    SmallString<128> BaseDir;
-    if (PP.getHeaderSearchInfo().getHeaderSearchOpts().ModuleFileHomeIsCwd) {
-      // Use the current working directory as the base path for all inputs.
-      auto CWD = FileMgr.getOptionalDirectoryRef(".");
-      BaseDir.assign(CWD->getName());
-    } else {
-      BaseDir.assign(WritingModule->Directory->getName());
-    }
-    cleanPathForOutput(FileMgr, BaseDir);
-
-    // If the home of the module is the current working directory, then we
-    // want to pick up the cwd of the build process loading the module, not
-    // our cwd, when we load this module.
-    if (!PP.getHeaderSearchInfo().getHeaderSearchOpts().ModuleFileHomeIsCwd &&
-        (!PP.getHeaderSearchInfo()
-              .getHeaderSearchOpts()
-              .ModuleMapFileHomeIsCwd ||
-         WritingModule->Directory->getName() != ".")) {
-      // Module directory.
-      auto Abbrev = std::make_shared<BitCodeAbbrev>();
-      Abbrev->Add(BitCodeAbbrevOp(MODULE_DIRECTORY));
-      Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Directory
-      unsigned AbbrevCode = Stream.EmitAbbrev(std::move(Abbrev));
+    auto BaseDir = [&]() -> std::optional<SmallString<128>> {
+      if (PP.getHeaderSearchInfo().getHeaderSearchOpts().ModuleFileHomeIsCwd) {
+        // Use the current working directory as the base path for all inputs.
+        auto CWD = FileMgr.getOptionalDirectoryRef(".");
+        return CWD->getName();
+      }
+      if (WritingModule->Directory) {
+        return WritingModule->Directory->getName();
+      }
+      return std::nullopt;
+    }();
+    if (BaseDir) {
+      cleanPathForOutput(FileMgr, *BaseDir);
+      // If the home of the module is the current working directory, then we
+      // want to pick up the cwd of the build process loading the module, not
+      // our cwd, when we load this module.
+      if (!PP.getHeaderSearchInfo().getHeaderSearchOpts().ModuleFileHomeIsCwd &&
+          (!PP.getHeaderSearchInfo()
+                .getHeaderSearchOpts()
+                .ModuleMapFileHomeIsCwd ||
+           WritingModule->Directory->getName() != ".")) {
+        // Module directory.
+        auto Abbrev = std::make_shared<BitCodeAbbrev>();
+        Abbrev->Add(BitCodeAbbrevOp(MODULE_DIRECTORY));
+        Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Directory
+        unsigned AbbrevCode = Stream.EmitAbbrev(std::move(Abbrev));
+
+        RecordData::value_type Record[] = {MODULE_DIRECTORY};
+        Stream.EmitRecordWithBlob(AbbrevCode, Record, *BaseDir);
+      }
 
-      RecordData::value_type Record[] = {MODULE_DIRECTORY};
-      Stream.EmitRecordWithBlob(AbbrevCode, Record, BaseDir);
+      // Write out all other paths relative to the base directory if possible.
+      BaseDirectory.assign(BaseDir->begin(), BaseDir->end());
+    } else if (!isysroot.empty()) {
+      // Write out paths relative to the sysroot if possible.
+      BaseDirectory = std::string(isysroot);
     }
-
-    // Write out all other paths relative to the base directory if possible.
-    BaseDirectory.assign(BaseDir.begin(), BaseDir.end());
-  } else if (!isysroot.empty()) {
-    // Write out paths relative to the sysroot if possible.
-    BaseDirectory = std::string(isysroot);
   }
 
   // Module map file
diff --git a/clang/test/Modules/relocatable-modules.cpp b/clang/test/Modules/relocatable-modules.cpp
new file mode 100644
index 0000000000000..27e7330835b34
--- /dev/null
+++ b/clang/test/Modules/relocatable-modules.cpp
@@ -0,0 +1,43 @@
+// RUN: rm -rf %t
+// RUN: mkdir -p %t
+// RUN: split-file %s %t
+
+// CHECK-NOT: MODULE_DIRECTORY
+
+// RUN: cd %t
+// RUN: %clang_cc1 -std=c++20 -emit-module-interface %t/a.cppm -o %t/a-abs.pcm
+
+// RUN: llvm-bcanalyzer --dump --disable-histogram %t/a-abs.pcm | FileCheck %s
+// RUN: llvm-bcanalyzer --dump --disable-histogram %t/a-abs.pcm \
+// RUN:   | FileCheck %s --check-prefix=INPUT-ABS -DPREFIX=%t
+
+// RUN: %clang_cc1 -std=c++20 -emit-module-interface %t/a.cppm -o %t/a-rel.pcm \
+// RUN:   -fmodule-file-home-is-cwd
+
+// RUN: llvm-bcanalyzer --dump --disable-histogram %t/a-rel.pcm | FileCheck %s
+// RUN: llvm-bcanalyzer --dump --disable-histogram %t/a-rel.pcm \
+// RUN:   | FileCheck %s --check-prefix=INPUT-REL
+
+// INPUT-ABS: <INPUT_FILE {{.*}}/> blob data = '[[PREFIX]]{{/|\\}}a.cppm'
+// INPUT-REL: <INPUT_FILE {{.*}}/> blob data = 'a.cppm'
+
+//--- a.cppm
+export module a;
+
+// RUN: cd %S
+// RUN: %clang_cc1 -std=c++20 -emit-header-unit -xc++-user-header Inputs/cxx-header.h \
+// RUN:   -o %t/cxx-header-abs.pcm
+
+// RUN: llvm-bcanalyzer --dump --disable-histogram %t/cxx-header-abs.pcm | FileCheck %s
+// RUN: llvm-bcanalyzer --dump --disable-histogram %t/cxx-header-abs.pcm \
+// RUN:   | FileCheck %s --check-prefix=HU-INPUT-ABS -DPREFIX=%S
+
+// RUN: %clang_cc1 -std=c++20 -emit-header-unit -xc++-user-header Inputs/cxx-header.h \
+// RUN:   -fmodule-file-home-is-cwd -o %t/cxx-header-rel.pcm
+
+// RUN: llvm-bcanalyzer --dump --disable-histogram %t/cxx-header-rel.pcm | FileCheck %s
+// RUN: llvm-bcanalyzer --dump --disable-histogram %t/cxx-header-rel.pcm \
+// RUN:   | FileCheck %s --check-prefix=HU-INPUT-REL
+
+// HU-INPUT-ABS: <INPUT_FILE {{.*}}/> blob data = '[[PREFIX]]{{/|\\}}Inputs{{/|\\}}cxx-header.h'
+// HU-INPUT-REL: <INPUT_FILE {{.*}}/> blob data = 'Inputs{{/|\\}}cxx-header.h'

``````````

</details>


https://github.com/llvm/llvm-project/pull/135147


More information about the cfe-commits mailing list