Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
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
19 changes: 19 additions & 0 deletions cmake/Modules/Platform/Emscripten.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -380,3 +380,22 @@ endif()
# complain about unused CMake variable.
if (CMAKE_CROSSCOMPILING_EMULATOR)
endif()

# C++23 stl modules (Ref: https://cmake.org/cmake/help/latest/manual/cmake-cxxmodules.7.html#import-std-support)
if(CMAKE_VERSION VERSION_GREATER_EQUAL 4.3 AND CMAKE_CXX_MODULE_STD AND NOT CMAKE_CXX_STDLIB_MODULES_JSON)
set(CMAKE_CXX_STDLIB_MODULES_JSON "${EMSCRIPTEN_SYSROOT}/lib/${CMAKE_LIBRARY_ARCHITECTURE}/libc++.modules.json")

# Ref: https://cmake.org/cmake/help/latest/variable/CMAKE_CXX_COMPILER_IMPORT_STD.html
foreach(_FEATURE IN LISTS CMAKE_CXX_COMPILE_FEATURES)
if(_FEATURE MATCHES [[cxx_std_([0-9]+)]] AND CMAKE_MATCH_1 GREATER_EQUAL 23 AND CMAKE_MATCH_1 LESS 98)
list(APPEND CMAKE_CXX_COMPILER_IMPORT_STD ${CMAKE_MATCH_1})
endif()
endforeach()

set_property(SOURCE
"${EMSCRIPTEN_SYSROOT}/share/libc++/v1/std.cppm"
"${EMSCRIPTEN_SYSROOT}/share/libc++/v1/std.compat.cppm"
PROPERTY
COMPILE_FLAGS -Wno-reserved-module-identifier
)
endif()
52 changes: 52 additions & 0 deletions system/lib/libcxx/build_modules.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import os
import sys
import subprocess
import tempfile
import shutil
from pathlib import Path

cwd = Path(__file__).parent
os.chdir(cwd)

def main():
with tempfile.TemporaryDirectory() as tmp:
src = os.path.abspath('modules')
install_prefix = src + '/prefix'

lib = 'lib/emscripten'
share = 'share/libc++/v1'

build_dir = 'out'
dist = f'{tmp}/{build_dir}/dist/'
build_lib = dist + lib
build_share = dist + share

vars = [
('LIBCXX_INSTALL_LIBRARY_DIR', lib),
('LIBCXX_INSTALL_MODULES_DIR', share),
('LIBCXX_LIBRARY_DIR', build_lib),
('LIBCXX_GENERATED_MODULE_DIR', build_share),
]

args = ''
for var in vars:
args += f' -D{var[0]}={var[1]}'

with open(tmp + '/CMakeLists.txt', 'x', encoding='utf-8') as CMakeLists:
CMakeLists.write(f'''\
cmake_minimum_required(VERSION 3.10)
project(libcxx-modules)
add_subdirectory("{src}" libcxx)
''')

subprocess.run(f'cmake -B {build_dir} -S {tmp} {args}', cwd=tmp, shell=True)
subprocess.run(['cmake', '--build', build_dir], cwd=tmp)
shutil.copytree(dist, install_prefix, dirs_exist_ok=True)

return 0

if __name__ == '__main__':
try:
sys.exit(main())
except KeyboardInterrupt:
sys.exit(1)
3 changes: 3 additions & 0 deletions system/lib/libcxx/modules/.clang-format
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
BasedOnStyle: InheritParentConfig

NamespaceIndentation: All
269 changes: 269 additions & 0 deletions system/lib/libcxx/modules/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,269 @@
# The headers of Table 24: C++ library headers [tab:headers.cpp]
# and the headers of Table 25: C++ headers for C library facilities [tab:headers.cpp.c]
set(LIBCXX_MODULE_STD_SOURCES
std/algorithm.inc
std/any.inc
std/array.inc
std/atomic.inc
std/barrier.inc
std/bit.inc
std/bitset.inc
std/cassert.inc
std/cctype.inc
std/cerrno.inc
std/cfenv.inc
std/cfloat.inc
std/charconv.inc
std/chrono.inc
std/cinttypes.inc
std/climits.inc
std/clocale.inc
std/cmath.inc
std/codecvt.inc
std/compare.inc
std/complex.inc
std/concepts.inc
std/condition_variable.inc
std/coroutine.inc
std/csetjmp.inc
std/csignal.inc
std/cstdarg.inc
std/cstddef.inc
std/cstdint.inc
std/cstdio.inc
std/cstdlib.inc
std/cstring.inc
std/ctime.inc
std/cuchar.inc
std/cwchar.inc
std/cwctype.inc
std/deque.inc
std/exception.inc
std/execution.inc
std/expected.inc
std/filesystem.inc
std/flat_map.inc
std/flat_set.inc
std/format.inc
std/forward_list.inc
std/fstream.inc
std/functional.inc
std/future.inc
std/generator.inc
std/hazard_pointer.inc
std/initializer_list.inc
std/iomanip.inc
std/ios.inc
std/iosfwd.inc
std/iostream.inc
std/istream.inc
std/iterator.inc
std/latch.inc
std/limits.inc
std/list.inc
std/locale.inc
std/map.inc
std/mdspan.inc
std/memory.inc
std/memory_resource.inc
std/mutex.inc
std/new.inc
std/numbers.inc
std/numeric.inc
std/optional.inc
std/ostream.inc
std/print.inc
std/queue.inc
std/random.inc
std/ranges.inc
std/ratio.inc
std/rcu.inc
std/regex.inc
std/scoped_allocator.inc
std/semaphore.inc
std/set.inc
std/shared_mutex.inc
std/source_location.inc
std/span.inc
std/spanstream.inc
std/sstream.inc
std/stack.inc
std/stacktrace.inc
std/stdexcept.inc
std/stdfloat.inc
std/stop_token.inc
std/streambuf.inc
std/string.inc
std/string_view.inc
std/strstream.inc
std/syncstream.inc
std/system_error.inc
std/text_encoding.inc
std/thread.inc
std/tuple.inc
std/type_traits.inc
std/typeindex.inc
std/typeinfo.inc
std/unordered_map.inc
std/unordered_set.inc
std/utility.inc
std/valarray.inc
std/variant.inc
std/vector.inc
std/version.inc
)

set(LIBCXX_MODULE_STD_COMPAT_SOURCES
std.compat/cassert.inc
std.compat/cctype.inc
std.compat/cerrno.inc
std.compat/cfenv.inc
std.compat/cfloat.inc
std.compat/cinttypes.inc
std.compat/climits.inc
std.compat/clocale.inc
std.compat/cmath.inc
std.compat/csetjmp.inc
std.compat/csignal.inc
std.compat/cstdarg.inc
std.compat/cstddef.inc
std.compat/cstdint.inc
std.compat/cstdio.inc
std.compat/cstdlib.inc
std.compat/cstring.inc
std.compat/ctime.inc
std.compat/cuchar.inc
std.compat/cwchar.inc
std.compat/cwctype.inc
)

# TODO MODULES the CMakeLists.txt in the build directory is only temporary.
# This allows using as available in the build directory. Once build systems
# have proper support for the installed files this will be removed.
if ("${LIBCXX_GENERATED_INCLUDE_DIR}" STREQUAL "${LIBCXX_GENERATED_INCLUDE_TARGET_DIR}")
# This typically happens when the target is not installed.
set(LIBCXX_CONFIGURED_INCLUDE_DIRS "${LIBCXX_GENERATED_INCLUDE_DIR}")
else()
# It's important that the arch directory be included first so that its header files
# which interpose on the default include dir be included instead of the default ones.
set(LIBCXX_CONFIGURED_INCLUDE_DIRS
"${LIBCXX_GENERATED_INCLUDE_TARGET_DIR};${LIBCXX_GENERATED_INCLUDE_DIR}"
)
endif()
configure_file(
"CMakeLists.txt.in"
"${LIBCXX_GENERATED_MODULE_DIR}/CMakeLists.txt"
@ONLY
)

set(LIBCXX_MODULE_STD_INCLUDE_SOURCES)
foreach(file ${LIBCXX_MODULE_STD_SOURCES})
set(
LIBCXX_MODULE_STD_INCLUDE_SOURCES
"${LIBCXX_MODULE_STD_INCLUDE_SOURCES}#include \"${file}\"\n"
)
endforeach()

configure_file(
"std.cppm.in"
"${LIBCXX_GENERATED_MODULE_DIR}/std.cppm"
@ONLY
)

set(LIBCXX_MODULE_STD_COMPAT_INCLUDE_SOURCES)
foreach(file ${LIBCXX_MODULE_STD_COMPAT_SOURCES})
set(
LIBCXX_MODULE_STD_COMPAT_INCLUDE_SOURCES
"${LIBCXX_MODULE_STD_COMPAT_INCLUDE_SOURCES}#include \"${file}\"\n"
)
endforeach()

configure_file(
"std.compat.cppm.in"
"${LIBCXX_GENERATED_MODULE_DIR}/std.compat.cppm"
@ONLY
)

set(_all_modules)
list(APPEND _all_modules "${LIBCXX_GENERATED_MODULE_DIR}/CMakeLists.txt")
list(APPEND _all_modules "${LIBCXX_GENERATED_MODULE_DIR}/std.cppm")
list(APPEND _all_modules "${LIBCXX_GENERATED_MODULE_DIR}/std.compat.cppm")
foreach(file ${LIBCXX_MODULE_STD_SOURCES} ${LIBCXX_MODULE_STD_COMPAT_SOURCES})
set(src "${CMAKE_CURRENT_SOURCE_DIR}/${file}")
set(dst "${LIBCXX_GENERATED_MODULE_DIR}/${file}")
add_custom_command(OUTPUT ${dst}
DEPENDS ${src}
COMMAND ${CMAKE_COMMAND} -E copy_if_different ${src} ${dst}
COMMENT "Copying CXX module ${file}")
list(APPEND _all_modules "${dst}")
endforeach()

add_custom_target(generate-cxx-modules
ALL DEPENDS
${_all_modules}
)

# Configure the modules manifest.
# Use the relative path between the installation and the module in the json
# file. This allows moving the entire installation to a different location.
if("${CMAKE_INSTALL_PREFIX}" STREQUAL "")
set(BASE_DIRECTORY "/")
else()
set(BASE_DIRECTORY ${CMAKE_INSTALL_PREFIX})
endif()
cmake_path(ABSOLUTE_PATH LIBCXX_INSTALL_LIBRARY_DIR
BASE_DIRECTORY ${BASE_DIRECTORY}
OUTPUT_VARIABLE ABS_LIBRARY_DIR)
cmake_path(ABSOLUTE_PATH LIBCXX_INSTALL_MODULES_DIR
BASE_DIRECTORY ${BASE_DIRECTORY}
OUTPUT_VARIABLE ABS_MODULES_DIR)
file(RELATIVE_PATH LIBCXX_MODULE_RELATIVE_PATH
${ABS_LIBRARY_DIR}
${ABS_MODULES_DIR})
configure_file(
"modules.json.in"
"${LIBCXX_LIBRARY_DIR}/libc++.modules.json"
@ONLY
)

# Dummy library to make modules an installation component.
add_library(cxx-modules INTERFACE)
add_dependencies(cxx-modules generate-cxx-modules)

if (LIBCXX_INSTALL_MODULES)
foreach(file ${LIBCXX_MODULE_STD_SOURCES} ${LIBCXX_MODULE_STD_COMPAT_SOURCES})
get_filename_component(dir ${file} DIRECTORY)
install(FILES ${file}
DESTINATION "${LIBCXX_INSTALL_MODULES_DIR}/${dir}"
COMPONENT cxx-modules
PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ
)
endforeach()

# Install the generated module files.
install(FILES
"${LIBCXX_GENERATED_MODULE_DIR}/std.cppm"
"${LIBCXX_GENERATED_MODULE_DIR}/std.compat.cppm"
DESTINATION "${LIBCXX_INSTALL_MODULES_DIR}"
COMPONENT cxx-modules
PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ
)

# Install the module manifest.
install(FILES
"${LIBCXX_LIBRARY_DIR}/libc++.modules.json"
DESTINATION "${LIBCXX_INSTALL_LIBRARY_DIR}"
COMPONENT cxx-modules
PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ
)

if (NOT CMAKE_CONFIGURATION_TYPES)
add_custom_target(install-cxx-modules
DEPENDS cxx-modules
COMMAND "${CMAKE_COMMAND}"
-DCMAKE_INSTALL_COMPONENT=cxx-modules
-P "${CMAKE_BINARY_DIR}/cmake_install.cmake")
# Stripping is a no-op for modules
add_custom_target(install-cxx-modules-stripped DEPENDS install-cxx-modules)
endif()
endif()
Loading
Loading