Skip to content

Commit 9c90a47

Browse files
committed
[runtime-cxxmodules] Generate std_darwin.modulemap from active SDK
Dynamically extract and wrap the system modulemap from the active SDK in a top-level 'std' module Also remove 'std_ctype_h' module to break cyclic dependencies.
1 parent fcc727f commit 9c90a47

File tree

2 files changed

+63
-1
lines changed

2 files changed

+63
-1
lines changed
+48
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
#!/usr/bin/env python3
2+
import os
3+
import re
4+
import subprocess
5+
import sys
6+
7+
8+
def get_sdk_path():
9+
result = subprocess.run(["xcrun", "--show-sdk-path"], capture_output=True, text=True)
10+
if result.returncode != 0:
11+
raise RuntimeError("Could not resolve SDK path")
12+
return os.path.realpath(result.stdout.strip())
13+
14+
15+
def remove_ctype_module(content):
16+
# Break cyclic module dependencies
17+
# See: https://github.com/root-project/root/commit/8045591a17125b49c1007787c586868dea764479
18+
pattern = re.compile(r"module\s+std_ctype_h\s+\[system\]\s*\{.*?\}", re.DOTALL)
19+
return pattern.sub("", content)
20+
21+
22+
def main():
23+
if len(sys.argv) < 2:
24+
raise ValueError("Usage: std_modulemap_darwin_fix.py <output_path>")
25+
output_path = sys.argv[1]
26+
sdk = get_sdk_path()
27+
cpp_modulemap = os.path.join(sdk, "usr/include/c++/v1/module.modulemap")
28+
29+
if not os.path.exists(cpp_modulemap):
30+
raise FileNotFoundError(f"Cannot find libc++ modulemap at {cpp_modulemap}")
31+
32+
with open(cpp_modulemap, "r") as f:
33+
original_content = f.read()
34+
35+
cleaned_content = remove_ctype_module(original_content)
36+
37+
os.makedirs(os.path.dirname(output_path), exist_ok=True)
38+
with open(output_path, "w") as f:
39+
f.write("// Auto-generated flat modulemap for Cling\n")
40+
f.write("module std [system] {\n")
41+
f.write("export *\n\n")
42+
f.write("// Entire modulemap wrapped\n")
43+
f.write(cleaned_content)
44+
f.write("\n}\n")
45+
46+
47+
if __name__ == "__main__":
48+
main()

core/clingutils/CMakeLists.txt

+15-1
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,18 @@ if (runtime_cxxmodules)
130130
if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 15.0.0.15000309)
131131
set(custom_modulemaps ${custom_modulemaps} std_darwin.MacOSX14.2.sdk.modulemap)
132132
else()
133-
set(custom_modulemaps ${custom_modulemaps} std_darwin.modulemap)
133+
set(GENERATED_MODULEMAP ${CMAKE_BINARY_DIR}/std_darwin.modulemap)
134+
135+
add_custom_command(
136+
OUTPUT ${GENERATED_MODULEMAP}
137+
COMMAND ${Python3_EXECUTABLE} ${CMAKE_SOURCE_DIR}/cmake/scripts/std_modulemap_darwin_fix.py ${GENERATED_MODULEMAP}
138+
DEPENDS ${CMAKE_SOURCE_DIR}/cmake/scripts/std_modulemap_darwin_fix.py
139+
COMMENT "Generating wrapped std modulemap for macOS SDK"
140+
)
141+
add_custom_target(generate_std_modulemap DEPENDS ${GENERATED_MODULEMAP})
142+
list(APPEND copy_commands COMMAND ${CMAKE_COMMAND} -E copy ${GENERATED_MODULEMAP} ${CMAKE_BINARY_DIR}/etc/cling/std_darwin.modulemap)
143+
list(APPEND files_to_copy ${GENERATED_MODULEMAP})
144+
install(FILES ${CMAKE_BINARY_DIR}/etc/cling/std_darwin.modulemap DESTINATION ${CMAKE_INSTALL_SYSCONFDIR}/cling)
134145
endif()
135146
endif()
136147

@@ -204,6 +215,9 @@ else()
204215
COMMENT "Copying LLVM resource and header files")
205216
endif()
206217
add_custom_target(LLVMRES DEPENDS ${stamp_file} CLING)
218+
if(GENERATED_MODULEMAP)
219+
add_dependencies(LLVMRES generate_std_modulemap)
220+
endif()
207221
# CLING is a shorthand for CLING_LIBRARIES and some other clang-specific
208222
# dependencies which ensure the correct order of building. Then the cling header
209223
# files (such as RuntimeUniverse.h) are moved to a semi-private place in ROOT

0 commit comments

Comments
 (0)