| (modulesinlibcxx)= | |
| # Modules in libc++ | |
| :::{warning} | |
| Modules are an experimental feature. It has additional build | |
| requirements and not all libc++ configurations are supported yet. | |
| The work is still in an early development state and not | |
| considered stable nor complete | |
| ::: | |
| This page contains information regarding C++23 module support in libc++. | |
| There are two kinds of modules available in Clang | |
| - [Clang specific modules](https://clang.llvm.org/docs/Modules.html) | |
| - [C++ modules](https://clang.llvm.org/docs/StandardCPlusPlusModules.html) | |
| This page mainly discusses the C++ modules. In C++20 there are also header units, | |
| these are not part of this document. | |
| ## Overview | |
| The module sources are stored in `.cppm` files. Modules need to be available | |
| as BMIs, which are `.pcm` files for Clang. BMIs are not portable, they depend | |
| on the compiler and the compilation flags used. Therefore there needs to be a | |
| way to distribute the `.cppm` files to the user and offer a way for them to | |
| build and use the `.pcm` files. It is expected this will be done by build | |
| systems in the future. To aid early adaptor and build system vendors libc++ | |
| currently ships a CMake project to aid building modules. | |
| :::{note} | |
| This CMake file is intended to be a temporary solution and will | |
| be removed in the future. The timeline for the removal depends | |
| on the availability of build systems with proper module support. | |
| ::: | |
| ### What works | |
| - Building BMIs | |
| - Running tests using the `std` and `std.compat` module | |
| - Using the `std` and `std.compat` module in external projects | |
| - The following "parts disabled" configuration options are supported | |
| - `LIBCXX_ENABLE_LOCALIZATION` | |
| - `LIBCXX_ENABLE_WIDE_CHARACTERS` | |
| - `LIBCXX_ENABLE_THREADS` | |
| - `LIBCXX_ENABLE_FILESYSTEM` | |
| - `LIBCXX_ENABLE_RANDOM_DEVICE` | |
| - `LIBCXX_ENABLE_UNICODE` | |
| - `LIBCXX_ENABLE_EXCEPTIONS` [^note-no-windows] | |
| - A C++20 based extension | |
| [^note-no-windows]: | |
| This configuration will probably not work on Windows | |
| due to hard-coded compilation flags. | |
| ### Some of the current limitations | |
| - There is no official build system support, libc++ has experimental CMake support | |
| - Requires CMake 3.26 for C++20 support | |
| - Requires CMake 3.26 for C++23 support | |
| - Requires CMake 3.27 for C++26 support | |
| - Requires Ninja 1.11 | |
| - Requires Clang 17 | |
| - The path to the compiler may not be a symlink, `clang-scan-deps` does | |
| not handle that case properly | |
| - Libc++ is not tested with modules instead of headers | |
| - Clang: | |
| - Including headers after importing the `std` module may fail. This is | |
| hard to solve and there is a work-around by first including all headers | |
| [bug report](https://llvm.org/PR61465). | |
| ### Blockers | |
| - libc++ | |
| - Currently the tests only test with modules enabled, but do not import | |
| modules instead of headers. When converting tests to using modules there | |
| are still failures. These are under investigation. | |
| - It has not been determined how to fully test libc++ with modules instead | |
| of headers. | |
| - Clang | |
| - Some concepts do not work properly [bug report](https://llvm.org/PR61465). | |
| ## Using in external projects | |
| Users need to be able to build their own BMI files. | |
| :::{note} | |
| The requirements for users to build their own BMI files will remain | |
| true for the foreseeable future. For now this needs to be done manually. | |
| Once libc++'s implementation is more mature we will reach out to build | |
| system vendors, with the goal that building the BMI files is done by | |
| the build system. | |
| ::: | |
| Currently there are two ways to build modules | |
| - Use a local build of modules from the build directory. This requires | |
| Clang 17 or later and CMake 3.26 or later. | |
| - Use the installed modules. This requires Clang 18.1.2 or later and | |
| a recent build of CMake. The CMake changes will be part of CMake 3.30. This | |
| method requires you or your distribution to enable module installation. | |
| ### Using the local build | |
| ```bash | |
| $ git clone https://github.com/llvm/llvm-project.git | |
| $ cd llvm-project | |
| $ mkdir build | |
| $ cmake -G Ninja -S runtimes -B build -DLLVM_ENABLE_RUNTIMES="libcxx;libcxxabi;libunwind" | |
| $ ninja -C build | |
| ``` | |
| The above `build` directory will be referred to as `<build>` in the | |
| rest of these instructions. | |
| This is a small sample program that uses the module `std`. It consists of a | |
| `CMakeLists.txt` and a `main.cpp` file. | |
| ```cpp | |
| import std; // When importing std.compat it's not needed to import std. | |
| import std.compat; | |
| int main() { | |
| std::cout << "Hello modular world\n"; | |
| ::printf("Hello compat modular world\n"); | |
| } | |
| ``` | |
| ```cmake | |
| cmake_minimum_required(VERSION 3.26.0 FATAL_ERROR) | |
| project("example" | |
| LANGUAGES CXX | |
| ) | |
| # | |
| # Set language version used | |
| # | |
| set(CMAKE_CXX_STANDARD 23) | |
| set(CMAKE_CXX_STANDARD_REQUIRED YES) | |
| set(CMAKE_CXX_EXTENSIONS OFF) | |
| # | |
| # Enable modules in CMake | |
| # | |
| # This is required to write your own modules in your project. | |
| if(CMAKE_VERSION VERSION_LESS "3.28.0") | |
| if(CMAKE_VERSION VERSION_LESS "3.27.0") | |
| set(CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API "2182bf5c-ef0d-489a-91da-49dbc3090d2a") | |
| else() | |
| set(CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API "aa1f7df0-828a-4fcd-9afc-2dc80491aca7") | |
| endif() | |
| set(CMAKE_EXPERIMENTAL_CXX_MODULE_DYNDEP 1) | |
| else() | |
| cmake_policy(VERSION 3.28) | |
| endif() | |
| # | |
| # Import the modules from libc++ | |
| # | |
| include(FetchContent) | |
| FetchContent_Declare( | |
| std | |
| URL "file://${LIBCXX_BUILD}/modules/c++/v1/" | |
| DOWNLOAD_EXTRACT_TIMESTAMP TRUE | |
| SYSTEM | |
| ) | |
| FetchContent_MakeAvailable(std) | |
| # | |
| # Add the project | |
| # | |
| add_executable(main) | |
| add_dependencies(main std.compat) | |
| target_link_libraries(main std.compat) | |
| target_sources(main | |
| PRIVATE | |
| main.cpp | |
| ) | |
| ``` | |
| Building this project is done with the following steps, assuming the files | |
| `main.cpp` and `CMakeLists.txt` are copied in the current directory. | |
| ```bash | |
| $ mkdir build | |
| $ cmake -G Ninja -S . -B build -DCMAKE_CXX_COMPILER=<path-to-compiler> -DLIBCXX_BUILD=<build> | |
| $ ninja -C build | |
| $ build/main | |
| ``` | |
| :::{warning} | |
| `<path-to-compiler>` should point point to the real binary and | |
| not to a symlink. | |
| ::: | |
| :::{warning} | |
| When using these examples in your own projects make sure the | |
| compilation flags are the same for the `std` module and your | |
| project. Some flags will affect the generated code, when these | |
| are different the module cannot be used. For example using | |
| `-pthread` in your project and not in the module will give | |
| errors like | |
| `error: POSIX thread support was disabled in PCH file but is currently enabled` | |
| `error: module file _deps/std-build/CMakeFiles/std.dir/std.pcm cannot be loaded due to a configuration mismatch with the current compilation [-Wmodule-file-config-mismatch]` | |
| ::: | |
| ### Using the installed modules | |
| CMake has added experimental support for importing the Standard modules. This | |
| is available in the current nightly builds and will be part of the 3.30 | |
| release. Currently CMake only supports importing the Standard modules in C++23 | |
| and later. Enabling this for C++20 is on the TODO list of the CMake | |
| developers. | |
| The example uses the same `main.cpp` as above. It uses the following | |
| `CMakeLists.txt`: | |
| ```cmake | |
| # This requires a recent nightly build. | |
| # This will be part of CMake 3.30.0. | |
| cmake_minimum_required(VERSION 3.29.0 FATAL_ERROR) | |
| # Enables the Standard module support. This needs to be done | |
| # before selecting the languages. | |
| set(CMAKE_EXPERIMENTAL_CXX_IMPORT_STD "0e5b6991-d74f-4b3d-a41c-cf096e0b2508") | |
| set(CMAKE_CXX_MODULE_STD ON) | |
| project("example" | |
| LANGUAGES CXX | |
| ) | |
| # | |
| # Set language version used | |
| # | |
| set(CMAKE_CXX_STANDARD 23) | |
| set(CMAKE_CXX_STANDARD_REQUIRED YES) | |
| # Currently CMake requires extensions enabled when using import std. | |
| # https://gitlab.kitware.com/cmake/cmake/-/issues/25916 | |
| # https://gitlab.kitware.com/cmake/cmake/-/issues/25539 | |
| set(CMAKE_CXX_EXTENSIONS ON) | |
| add_executable(main) | |
| target_sources(main | |
| PRIVATE | |
| main.cpp | |
| ) | |
| ``` | |
| Building this project is done with the following steps, assuming the files | |
| `main.cpp` and `CMakeLists.txt` are copied in the current directory. | |
| ```bash | |
| $ mkdir build | |
| $ cmake -G Ninja -S . -B build -DCMAKE_CXX_COMPILER=<path-to-compiler> -DCMAKE_CXX_FLAGS=-stdlib=libc++ | |
| $ ninja -C build | |
| $ build/main | |
| ``` | |
| :::{warning} | |
| `<path-to-compiler>` should point point to the real binary and | |
| not to a symlink. | |
| ::: | |
| If you have questions about modules feel free to ask them in the `#libcxx` | |
| channel on [LLVM's Discord server](https://discord.gg/jzUbyP26tQ). | |
| If you think you've found a bug please it using the [LLVM bug tracker](https://github.com/llvm/llvm-project/issues). Please make sure the issue | |
| you found is not one of the known bugs or limitations on this page. |