[libcxx-commits] [libcxx] d1784c0 - [libc++] Generate a per-target modulemap when using per-target runtime dirs (#209312)
via libcxx-commits
libcxx-commits at lists.llvm.org
Fri Aug 7 06:22:38 PDT 2026
Author: Louis Dionne
Date: 2026-08-07T09:22:32-04:00
New Revision: d1784c08ac847c9ee2a92c2634c24d5696f5d9c1
URL: https://github.com/llvm/llvm-project/commit/d1784c08ac847c9ee2a92c2634c24d5696f5d9c1
DIFF: https://github.com/llvm/llvm-project/commit/d1784c08ac847c9ee2a92c2634c24d5696f5d9c1.diff
LOG: [libc++] Generate a per-target modulemap when using per-target runtime dirs (#209312)
This allows making __config_site modular. It also removes a workaround
where the __config_site and __assertion_handler headers were previously
excluded from the modulemap test.
Added:
libcxx/include/target.modulemap
Modified:
libcxx/include/CMakeLists.txt
libcxx/test/libcxx-03/lint/lint_headers.sh.py
libcxx/test/libcxx/headers_in_modulemap.sh.py
libcxx/test/libcxx/lint/lint_headers.sh.py
libcxx/utils/libcxx/header_information.py
Removed:
################################################################################
diff --git a/libcxx/include/CMakeLists.txt b/libcxx/include/CMakeLists.txt
index f6911b8ff05c5..d24ae7a73a825 100644
--- a/libcxx/include/CMakeLists.txt
+++ b/libcxx/include/CMakeLists.txt
@@ -1712,9 +1712,11 @@ set(files
configure_file("__config_site.in" "${LIBCXX_GENERATED_INCLUDE_TARGET_DIR}/__config_site" @ONLY)
configure_file("${LIBCXX_ASSERTION_HANDLER_FILE}" "${LIBCXX_GENERATED_INCLUDE_DIR}/__assertion_handler" COPYONLY)
-# We generate the modulemap file so that we can include __config_site in it. For now, we don't know how to
-# make __config_site modular when per-target runtime directories are used.
-if (NOT LLVM_ENABLE_PER_TARGET_RUNTIME_DIR)
+# We generate the main modulemap file so that we can include __config_site in it. When using a target-specific
+# include directory, give it its own modulemap.
+if (LLVM_ENABLE_PER_TARGET_RUNTIME_DIR)
+ configure_file("target.modulemap" "${LIBCXX_GENERATED_INCLUDE_TARGET_DIR}/module.modulemap" COPYONLY)
+else()
set(LIBCXX_CONFIG_SITE_MODULE_ENTRY "textual header \"__config_site\"")
endif()
configure_file("module.modulemap.in" "${LIBCXX_GENERATED_INCLUDE_DIR}/module.modulemap" @ONLY)
@@ -1722,6 +1724,9 @@ configure_file("module.modulemap.in" "${LIBCXX_GENERATED_INCLUDE_DIR}/module.mod
set(_all_includes "${LIBCXX_GENERATED_INCLUDE_TARGET_DIR}/__config_site"
"${LIBCXX_GENERATED_INCLUDE_DIR}/__assertion_handler"
"${LIBCXX_GENERATED_INCLUDE_DIR}/module.modulemap")
+if (LLVM_ENABLE_PER_TARGET_RUNTIME_DIR)
+ list(APPEND _all_includes "${LIBCXX_GENERATED_INCLUDE_TARGET_DIR}/module.modulemap")
+endif()
foreach(f ${files})
set(src "${CMAKE_CURRENT_SOURCE_DIR}/${f}")
set(dst "${LIBCXX_GENERATED_INCLUDE_DIR}/${f}")
@@ -1790,6 +1795,14 @@ if (LIBCXX_INSTALL_HEADERS)
PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ
COMPONENT cxx-headers)
+ # Install the per-target modulemap when we use per-target include dirs.
+ if (LLVM_ENABLE_PER_TARGET_RUNTIME_DIR)
+ install(FILES "${LIBCXX_GENERATED_INCLUDE_TARGET_DIR}/module.modulemap"
+ DESTINATION "${LIBCXX_INSTALL_INCLUDE_TARGET_DIR}"
+ PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ
+ COMPONENT cxx-headers)
+ endif()
+
if (NOT CMAKE_CONFIGURATION_TYPES)
add_custom_target(install-cxx-headers
DEPENDS cxx-headers
diff --git a/libcxx/include/target.modulemap b/libcxx/include/target.modulemap
new file mode 100644
index 0000000000000..77735e5ad7564
--- /dev/null
+++ b/libcxx/include/target.modulemap
@@ -0,0 +1,3 @@
+module std_config_site {
+ textual header "__config_site"
+}
diff --git a/libcxx/test/libcxx-03/lint/lint_headers.sh.py b/libcxx/test/libcxx-03/lint/lint_headers.sh.py
index ab237c968da7e..34eb5c000d237 100644
--- a/libcxx/test/libcxx-03/lint/lint_headers.sh.py
+++ b/libcxx/test/libcxx-03/lint/lint_headers.sh.py
@@ -12,6 +12,7 @@ def exclude_from_consideration(path):
return (
path.endswith(".txt")
or path.endswith(".modulemap.in")
+ or os.path.basename(path) == "target.modulemap"
or os.path.basename(path) == "__config"
or os.path.basename(path) == "__config_site.in"
or os.path.basename(path) == "libcxx.imp"
diff --git a/libcxx/test/libcxx/headers_in_modulemap.sh.py b/libcxx/test/libcxx/headers_in_modulemap.sh.py
index d4a18a20c8926..e44937b49409f 100644
--- a/libcxx/test/libcxx/headers_in_modulemap.sh.py
+++ b/libcxx/test/libcxx/headers_in_modulemap.sh.py
@@ -1,11 +1,18 @@
-# RUN: %{python} %s %{libcxx-dir}/utils
+# RUN: %{python} %s %{libcxx-dir}/utils %{include-dir} %{target-include-dir}
+import pathlib
import sys
sys.path.append(sys.argv[1])
-from libcxx.header_information import all_headers, libcxx_include
+from libcxx.header_information import all_headers
-with open(libcxx_include / "module.modulemap.in") as f:
+# Check both the generic modulemap and the target-specific modulemap, if there is one.
+include = pathlib.Path(sys.argv[2])
+target_include = pathlib.Path(sys.argv[3])
+with open(include / "module.modulemap") as f:
modulemap = f.read()
+if target_include.resolve() != include.resolve():
+ with open(target_include / "module.modulemap") as f:
+ modulemap += f.read()
isHeaderMissing = False
for header in all_headers:
diff --git a/libcxx/test/libcxx/lint/lint_headers.sh.py b/libcxx/test/libcxx/lint/lint_headers.sh.py
index ab237c968da7e..34eb5c000d237 100644
--- a/libcxx/test/libcxx/lint/lint_headers.sh.py
+++ b/libcxx/test/libcxx/lint/lint_headers.sh.py
@@ -12,6 +12,7 @@ def exclude_from_consideration(path):
return (
path.endswith(".txt")
or path.endswith(".modulemap.in")
+ or os.path.basename(path) == "target.modulemap"
or os.path.basename(path) == "__config"
or os.path.basename(path) == "__config_site.in"
or os.path.basename(path) == "libcxx.imp"
diff --git a/libcxx/utils/libcxx/header_information.py b/libcxx/utils/libcxx/header_information.py
index c6bcbe829a571..7316662171b77 100644
--- a/libcxx/utils/libcxx/header_information.py
+++ b/libcxx/utils/libcxx/header_information.py
@@ -9,13 +9,13 @@
import pathlib, functools
libcxx_root = pathlib.Path(__file__).resolve().parent.parent.parent
-libcxx_include = libcxx_root / "include"
assert libcxx_root.exists()
def _is_header_file(file):
"""Returns whether the given file is a header file, i.e. not a directory or the modulemap file."""
return not file.is_dir() and not file.name in [
"module.modulemap.in",
+ "target.modulemap",
"CMakeLists.txt",
"libcxx.imp",
"__config_site.in",
@@ -102,13 +102,6 @@ def is_cxx03_frozen_header(self) -> bool:
def is_in_modulemap(self) -> bool:
"""Returns whether a header should be listed in the modulemap."""
- # TODO: Should `__config_site` be in the modulemap?
- if self._name == "__config_site":
- return False
-
- if self._name == "__assertion_handler":
- return False
-
# exclude libc++abi files
if self._name in ["cxxabi.h", "__cxxabi_config.h"]:
return False
@@ -151,6 +144,7 @@ def __hash__(self) -> int:
# Commonly-used sets of headers
+libcxx_include = libcxx_root / "include"
all_headers = [Header(p.relative_to(libcxx_include).as_posix()) for p in libcxx_include.rglob("[_a-z]*") if _is_header_file(p)]
all_headers += [Header("__config_site"), Header("__assertion_handler")] # Headers generated during the build process
public_headers = [h for h in all_headers if h.is_public()]
More information about the libcxx-commits
mailing list