Skip to content

[runtime-cxxmodules] Generate std_darwin.modulemap from active SDK #18235

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 48 additions & 0 deletions cmake/scripts/std_modulemap_darwin_fix.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
#!/usr/bin/env python3
import os
import re
import subprocess
import sys


def get_sdk_path():
result = subprocess.run(["xcrun", "--show-sdk-path"], capture_output=True, text=True)
if result.returncode != 0:
raise RuntimeError("Could not resolve SDK path")
return os.path.realpath(result.stdout.strip())


def remove_ctype_module(content):
# Break cyclic module dependencies
# See: https://github.com/root-project/root/commit/8045591a17125b49c1007787c586868dea764479
pattern = re.compile(r"module\s+std_ctype_h\s+\[system\]\s*\{.*?\}", re.DOTALL)
return pattern.sub("", content)


def main():
if len(sys.argv) < 2:
raise ValueError("Usage: std_modulemap_darwin_fix.py <output_path>")
output_path = sys.argv[1]
sdk = get_sdk_path()
cpp_modulemap = os.path.join(sdk, "usr/include/c++/v1/module.modulemap")

if not os.path.exists(cpp_modulemap):
raise FileNotFoundError(f"Cannot find libc++ modulemap at {cpp_modulemap}")

with open(cpp_modulemap, "r") as f:
original_content = f.read()

cleaned_content = remove_ctype_module(original_content)

os.makedirs(os.path.dirname(output_path), exist_ok=True)
with open(output_path, "w") as f:
f.write("// Auto-generated flat modulemap for Cling\n")
f.write("module std [system] {\n")
f.write("export *\n\n")
f.write("// Entire modulemap wrapped\n")
f.write(cleaned_content)
f.write("\n}\n")


if __name__ == "__main__":
main()
18 changes: 15 additions & 3 deletions core/clingutils/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -129,10 +129,19 @@ if (runtime_cxxmodules)
if (APPLE)
if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 15.0.0.15000309)
set(custom_modulemaps ${custom_modulemaps} std_darwin.MacOSX14.2.sdk.modulemap)
elseif(CMAKE_CXX_COMPILER_VERSION VERSION_LESS 17.0.0.17000013)
set(custom_modulemaps ${custom_modulemaps} std_darwin.MacOSX15.2.sdk.modulemap)
else()
set(custom_modulemaps ${custom_modulemaps} std_darwin.modulemap)
set(GENERATED_MODULEMAP ${CMAKE_BINARY_DIR}/std_darwin.modulemap)

add_custom_command(
OUTPUT ${GENERATED_MODULEMAP}
COMMAND ${Python3_EXECUTABLE} ${CMAKE_SOURCE_DIR}/cmake/scripts/std_modulemap_darwin_fix.py ${GENERATED_MODULEMAP}
DEPENDS ${CMAKE_SOURCE_DIR}/cmake/scripts/std_modulemap_darwin_fix.py
COMMENT "Generating wrapped std modulemap for macOS SDK"
)
add_custom_target(generate_std_modulemap DEPENDS ${GENERATED_MODULEMAP})
list(APPEND copy_commands COMMAND ${CMAKE_COMMAND} -E copy ${GENERATED_MODULEMAP} ${CMAKE_BINARY_DIR}/etc/cling/std_darwin.modulemap)
list(APPEND files_to_copy ${GENERATED_MODULEMAP})
install(FILES ${CMAKE_BINARY_DIR}/etc/cling/std_darwin.modulemap DESTINATION ${CMAKE_INSTALL_SYSCONFDIR}/cling)
endif()
endif()

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