[libcxx-commits] [libcxx] [libc++][doc] Use installed std modules in external projects. (PR #80601)

Runzhong Li via libcxx-commits libcxx-commits at lists.llvm.org
Mon Mar 4 10:45:44 PST 2024


https://github.com/a858438680 updated https://github.com/llvm/llvm-project/pull/80601

>From 1772c7242033f8cab3920acefeb2715c442be08c Mon Sep 17 00:00:00 2001
From: LI Runzhong <858438680 at qq.com>
Date: Sun, 4 Feb 2024 23:51:16 +0800
Subject: [PATCH 1/8] [libc++][doc] Use installed std modules in external
 projects.

---
 libcxx/docs/Modules.rst | 112 ++++++++++++++++++++++++++--------------
 1 file changed, 74 insertions(+), 38 deletions(-)

diff --git a/libcxx/docs/Modules.rst b/libcxx/docs/Modules.rst
index ee2b81d3b9e7ca..caaba20f009dc3 100644
--- a/libcxx/docs/Modules.rst
+++ b/libcxx/docs/Modules.rst
@@ -105,36 +105,36 @@ Users need to be able to build their own BMI files.
    system vendors, with the goal that building the BMI files is done by
    the build system.
 
-Currently this requires a local build of libc++ with modules enabled. Since
-modules are not part of the installation yet, they are used from the build
-directory. First libc++ needs to be build with module support enabled.
+Currently this requires a local build of libc++ with modules installation enabled.
+Since modules are not installed by default. You can build and install the modules
+to ``<install_prefix>`` with the following commands.
 
 .. code-block:: bash
 
-  $ git clone https://github.com/llvm/llvm-project.git
+  $ git clone https://github.com/llvm/llvm-project.git --depth 1
   $ 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.
+  $ cmake -G Ninja -S runtimes -B build -DCMAKE_C_COMPILER=<path-to-compiler> -DCMAKE_CXX_COMPILER=<path-to-compiler> -DLIBCXX_INSTALL_MODULES=ON -DLLVM_ENABLE_RUNTIMES="libcxx;libcxxabi;libunwind"
+  $ cmake --build build -- -j $(nproc)
+  $ cmake --install build --prefix <install_prefix>
 
 This is a small sample program that uses the module ``std``. It consists of a
-``CMakeLists.txt`` and a ``main.cpp`` file.
+``CMakeLists.txt``, an ``std.cmake``, and a ``main.cpp`` file.
 
 .. code-block:: cpp
 
+  // main.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";
+    std::println("Hello modular world");
     ::printf("Hello compat modular world\n");
   }
 
 .. code-block:: cmake
 
+  # CMakeLists.txt
   cmake_minimum_required(VERSION 3.26.0 FATAL_ERROR)
   project("module"
     LANGUAGES CXX
@@ -168,59 +168,95 @@ This is a small sample program that uses the module ``std``. It consists of a
   #
   # Import the modules from libc++
   #
+  include(std.cmake)
+
+  add_executable(main main.cpp)
+
+.. code-block:: cmake
 
+  # std.cmake
   include(FetchContent)
   FetchContent_Declare(
-    std
-    URL "file://${LIBCXX_BUILD}/modules/c++/v1/"
+    std_module
+    URL "file://${LIBCXX_INSTALLED_DIR}/share/libc++/v1"
     DOWNLOAD_EXTRACT_TIMESTAMP TRUE
     SYSTEM
   )
-  FetchContent_MakeAvailable(std)
+
+  if (NOT std_module_POPULATED)
+    FetchContent_Populate(std_module)
+  endif()
 
   #
-  # Adjust project compiler flags
+  # Add std static library
   #
 
-  add_compile_options($<$<COMPILE_LANGUAGE:CXX>:-fprebuilt-module-path=${std_BINARY_DIR}/CMakeFiles/std.dir/>)
-  add_compile_options($<$<COMPILE_LANGUAGE:CXX>:-fprebuilt-module-path=${std_BINARY_DIR}/CMakeFiles/std.compat.dir/>)
-  add_compile_options($<$<COMPILE_LANGUAGE:CXX>:-nostdinc++>)
-  # The include path needs to be set to be able to use macros from headers.
-  # For example from, the headers <cassert> and <version>.
-  add_compile_options($<$<COMPILE_LANGUAGE:CXX>:-isystem>)
-  add_compile_options($<$<COMPILE_LANGUAGE:CXX>:${LIBCXX_BUILD}/include/c++/v1>)
+  add_library(std)
+
+  target_sources(std
+    PUBLIC FILE_SET cxx_modules TYPE CXX_MODULES FILES
+      ${std_module_SOURCE_DIR}/std.cppm
+      ${std_module_SOURCE_DIR}/std.compat.cppm
+  )
 
   #
-  # Adjust project linker flags
+  # Adjust project include directories
   #
 
-  add_link_options($<$<COMPILE_LANGUAGE:CXX>:-nostdlib++>)
-  add_link_options($<$<COMPILE_LANGUAGE:CXX>:-L${LIBCXX_BUILD}/lib>)
-  add_link_options($<$<COMPILE_LANGUAGE:CXX>:-Wl,-rpath,${LIBCXX_BUILD}/lib>)
-  # Linking against the standard c++ library is required for CMake to get the proper dependencies.
-  link_libraries(std c++)
-  link_libraries(std.compat c++)
+  target_include_directories(std SYSTEM PUBLIC ${LIBCXX_INSTALLED_DIR}/include/c++/v1)
 
   #
-  # Add the project
+  # Adjust project compiler flags
   #
 
-  add_executable(main)
-  target_sources(main
+  target_compile_options(std
     PRIVATE
-      main.cpp
+      -Wno-reserved-module-identifier
+      -Wno-reserved-user-defined-literal
+  )
+
+  target_compile_options(std
+    PUBLIC
+      -nostdinc++
+  )
+
+  #
+  # Adjust project linker flags
+  #
+
+  target_link_options(std
+    INTERFACE
+      -nostdlib++
+      -L${LIBCXX_INSTALLED_DIR}/lib
+      -Wl,-rpath,${LIBCXX_INSTALLED_DIR}/lib
+  )
+
+  target_link_libraries(std
+    INTERFACE
+      c++
   )
+  
+  #
+  # Link to the std modules by default
+  #
+
+  link_libraries(std)
 
 Building this project is done with the following steps, assuming the files
-``main.cpp`` and ``CMakeLists.txt`` are copied in the current directory.
+``main.cpp``, ``CMakeLists.txt``, and ``std.cmake`` are copied in the current directory.
 
 .. code-block:: bash
 
   $ mkdir build
-  $ cmake -G Ninja -S . -B build -DCMAKE_CXX_COMPILER=<path-to-compiler> -DLIBCXX_BUILD=<build>
-  $ ninja -j1 std -C build
-  $ ninja -C build
-  $ build/main
+  $ cmake -S . -B build -G Ninja -DCMAKE_CXX_COMPILER=<path-to-compiler> -DLIBCXX_INSTALLED_DIR=<install_prefix>
+  $ cmake --build build
+  $ ./build/main
+
+.. warning:: You need more than clang itself to build a project using modules.
+             Specifically, you will need ``clang-scan-deps``. For example, in Ubuntu, you
+             need to use ``sudo ./llvm.sh 17 all`` rather than ``sudo ./llvm.sh 17`` showed
+             in `LLVM Debian/Ubuntu nightly packages <https://apt.llvm.org>`__ to install
+             essential components to build this project.
 
 .. note:: The ``std`` dependencies of ``std.compat`` is not always resolved when
           building the ``std`` target using multiple jobs.

>From bfdd6c8c6ddef47837bb4fab4a7aef08cd502480 Mon Sep 17 00:00:00 2001
From: LI Runzhong <858438680 at qq.com>
Date: Mon, 4 Mar 2024 01:45:46 +0800
Subject: [PATCH 2/8] [libc++][doc] Use installed std modules with the previous
 version kept.

---
 libcxx/docs/Modules.rst | 122 ++++++++++++++++++++++++++++++++++++----
 1 file changed, 110 insertions(+), 12 deletions(-)

diff --git a/libcxx/docs/Modules.rst b/libcxx/docs/Modules.rst
index caaba20f009dc3..8567e4a6e69a2d 100644
--- a/libcxx/docs/Modules.rst
+++ b/libcxx/docs/Modules.rst
@@ -105,33 +105,131 @@ Users need to be able to build their own BMI files.
    system vendors, with the goal that building the BMI files is done by
    the build system.
 
-Currently this requires a local build of libc++ with modules installation enabled.
-Since modules are not installed by default. You can build and install the modules
-to ``<install_prefix>`` with the following commands.
+Currently this requires a local build of libc++ with modules enabled. Since
+modules are not part of the installation yet, they are used from the build
+directory. First libc++ needs to be build with module support enabled. If
+the libc++ is built with installation of modules enabled, they can also be
+used from the installation directory. The following instructions enable the
+installation of modules and install the modules into ``<install_prefix>``.
 
 .. code-block:: bash
 
-  $ git clone https://github.com/llvm/llvm-project.git --depth 1
+  $ git clone https://github.com/llvm/llvm-project.git
   $ cd llvm-project
   $ mkdir build
-  $ cmake -G Ninja -S runtimes -B build -DCMAKE_C_COMPILER=<path-to-compiler> -DCMAKE_CXX_COMPILER=<path-to-compiler> -DLIBCXX_INSTALL_MODULES=ON -DLLVM_ENABLE_RUNTIMES="libcxx;libcxxabi;libunwind"
-  $ cmake --build build -- -j $(nproc)
-  $ cmake --install build --prefix <install_prefix>
+  $ cmake -G Ninja -S runtimes -B build -DLIBCXX_INSTALL_MODULES=ON -DLLVM_ENABLE_RUNTIMES="libcxx;libcxxabi;libunwind"
+  $ ninja --build build -- -j $(nproc)
+  $ ninja --install build --prefix <install_prefix>
 
-This is a small sample program that uses the module ``std``. It consists of a
-``CMakeLists.txt``, an ``std.cmake``, and a ``main.cpp`` file.
+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`` from build
+directory. It consists of a ``CMakeLists.txt`` and a ``main.cpp`` file.
 
 .. code-block:: cpp
 
-  // main.cpp
   import std; // When importing std.compat it's not needed to import std.
   import std.compat;
 
   int main() {
-    std::println("Hello modular world");
+    std::cout << "Hello modular world\n";
     ::printf("Hello compat modular world\n");
   }
 
+.. code-block:: cmake
+
+  cmake_minimum_required(VERSION 3.26.0 FATAL_ERROR)
+  project("module"
+    LANGUAGES CXX
+  )
+
+  #
+  # Set language version used
+  #
+
+  set(CMAKE_CXX_STANDARD 23)
+  set(CMAKE_CXX_STANDARD_REQUIRED YES)
+  # Libc++ doesn't support compiler extensions for modules.
+  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)
+
+  #
+  # Adjust project compiler flags
+  #
+
+  add_compile_options($<$<COMPILE_LANGUAGE:CXX>:-fprebuilt-module-path=${std_BINARY_DIR}/CMakeFiles/std.dir/>)
+  add_compile_options($<$<COMPILE_LANGUAGE:CXX>:-fprebuilt-module-path=${std_BINARY_DIR}/CMakeFiles/std.compat.dir/>)
+  add_compile_options($<$<COMPILE_LANGUAGE:CXX>:-nostdinc++>)
+  # The include path needs to be set to be able to use macros from headers.
+  # For example from, the headers <cassert> and <version>.
+  add_compile_options($<$<COMPILE_LANGUAGE:CXX>:-isystem>)
+  add_compile_options($<$<COMPILE_LANGUAGE:CXX>:${LIBCXX_BUILD}/include/c++/v1>)
+
+  #
+  # Adjust project linker flags
+  #
+
+  add_link_options($<$<COMPILE_LANGUAGE:CXX>:-nostdlib++>)
+  add_link_options($<$<COMPILE_LANGUAGE:CXX>:-L${LIBCXX_BUILD}/lib>)
+  add_link_options($<$<COMPILE_LANGUAGE:CXX>:-Wl,-rpath,${LIBCXX_BUILD}/lib>)
+  # Linking against the standard c++ library is required for CMake to get the proper dependencies.
+  link_libraries(std c++)
+  link_libraries(std.compat c++)
+
+  #
+  # Add the project
+  #
+
+  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.
+
+.. code-block:: bash
+
+  $ mkdir build
+  $ cmake -G Ninja -S . -B build -DCMAKE_CXX_COMPILER=<path-to-compiler> -DLIBCXX_BUILD=<build>
+  $ ninja -C build
+  $ build/main
+
+This is another small sample program that uses the module ``std`` from
+installation directory. It consists of a ``CMakeLists.txt``, an
+``std.cmake``, and a ``main.cpp`` file. The ``main.cpp`` is the same as
+the previous example.
+
 .. code-block:: cmake
 
   # CMakeLists.txt
@@ -191,7 +289,7 @@ This is a small sample program that uses the module ``std``. It consists of a
   # Add std static library
   #
 
-  add_library(std)
+  add_library(std STATIC)
 
   target_sources(std
     PUBLIC FILE_SET cxx_modules TYPE CXX_MODULES FILES

>From fd231c0e678807f41682bb9f9b174cf56af8fdfb Mon Sep 17 00:00:00 2001
From: Mark de Wever <koraq at xs4all.nl>
Date: Tue, 13 Feb 2024 20:04:34 +0100
Subject: [PATCH 3/8] [libc++][modules] Re-add build dir CMakeLists.txt.
 (#81370)

This CMakeLists.txt is used to build modules without build system
support. This was removed in d06ae33ec32122bb526fb35025c1f0cf979f1090.
This is used in the documentation how to use modules.

Made some minor changes to make it work with the std.compat module using
the std module.

Note the CMakeLists.txt in the build dir should be removed once build
system support is generally available.
---
 libcxx/docs/Modules.rst | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/libcxx/docs/Modules.rst b/libcxx/docs/Modules.rst
index 8567e4a6e69a2d..3372b4ea9f31d3 100644
--- a/libcxx/docs/Modules.rst
+++ b/libcxx/docs/Modules.rst
@@ -222,9 +222,13 @@ Building this project is done with the following steps, assuming the files
 
   $ mkdir build
   $ cmake -G Ninja -S . -B build -DCMAKE_CXX_COMPILER=<path-to-compiler> -DLIBCXX_BUILD=<build>
+  $ ninja -j1 std -C build
   $ ninja -C build
   $ build/main
 
+.. note:: The ``std`` dependencies of ``std.compat`` is not always resolved when
+          building the ``std`` target using multiple jobs.
+
 This is another small sample program that uses the module ``std`` from
 installation directory. It consists of a ``CMakeLists.txt``, an
 ``std.cmake``, and a ``main.cpp`` file. The ``main.cpp`` is the same as

>From 0e90598f2a404c65523ddbf202e342448a56f08d Mon Sep 17 00:00:00 2001
From: LI Runzhong <858438680 at qq.com>
Date: Sun, 4 Feb 2024 23:51:16 +0800
Subject: [PATCH 6/8] [libc++][doc] Use installed std modules in external
 projects.

---
 libcxx/docs/Modules.rst | 83 ++++++++++++++++++++++++++++-------------
 1 file changed, 58 insertions(+), 25 deletions(-)

diff --git a/libcxx/docs/Modules.rst b/libcxx/docs/Modules.rst
index 3372b4ea9f31d3..efbdd78699a55c 100644
--- a/libcxx/docs/Modules.rst
+++ b/libcxx/docs/Modules.rst
@@ -114,7 +114,7 @@ installation of modules and install the modules into ``<install_prefix>``.
 
 .. code-block:: bash
 
-  $ git clone https://github.com/llvm/llvm-project.git
+  $ git clone https://github.com/llvm/llvm-project.git --depth 1
   $ cd llvm-project
   $ mkdir build
   $ cmake -G Ninja -S runtimes -B build -DLIBCXX_INSTALL_MODULES=ON -DLLVM_ENABLE_RUNTIMES="libcxx;libcxxabi;libunwind"
@@ -129,16 +129,18 @@ directory. It consists of a ``CMakeLists.txt`` and a ``main.cpp`` file.
 
 .. code-block:: cpp
 
+  // main.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";
+    std::println("Hello modular world");
     ::printf("Hello compat modular world\n");
   }
 
 .. code-block:: cmake
 
+  # CMakeLists.txt
   cmake_minimum_required(VERSION 3.26.0 FATAL_ERROR)
   project("module"
     LANGUAGES CXX
@@ -172,51 +174,82 @@ directory. It consists of a ``CMakeLists.txt`` and a ``main.cpp`` file.
   #
   # Import the modules from libc++
   #
+  include(std.cmake)
+
+  add_executable(main main.cpp)
 
+.. code-block:: cmake
+
+  # std.cmake
   include(FetchContent)
   FetchContent_Declare(
-    std
-    URL "file://${LIBCXX_BUILD}/modules/c++/v1/"
+    std_module
+    URL "file://${LIBCXX_INSTALLED_DIR}/share/libc++/v1"
     DOWNLOAD_EXTRACT_TIMESTAMP TRUE
     SYSTEM
   )
-  FetchContent_MakeAvailable(std)
+
+  if (NOT std_module_POPULATED)
+    FetchContent_Populate(std_module)
+  endif()
 
   #
-  # Adjust project compiler flags
+  # Add std static library
   #
 
-  add_compile_options($<$<COMPILE_LANGUAGE:CXX>:-fprebuilt-module-path=${std_BINARY_DIR}/CMakeFiles/std.dir/>)
-  add_compile_options($<$<COMPILE_LANGUAGE:CXX>:-fprebuilt-module-path=${std_BINARY_DIR}/CMakeFiles/std.compat.dir/>)
-  add_compile_options($<$<COMPILE_LANGUAGE:CXX>:-nostdinc++>)
-  # The include path needs to be set to be able to use macros from headers.
-  # For example from, the headers <cassert> and <version>.
-  add_compile_options($<$<COMPILE_LANGUAGE:CXX>:-isystem>)
-  add_compile_options($<$<COMPILE_LANGUAGE:CXX>:${LIBCXX_BUILD}/include/c++/v1>)
+  add_library(std)
+
+  target_sources(std
+    PUBLIC FILE_SET cxx_modules TYPE CXX_MODULES FILES
+      ${std_module_SOURCE_DIR}/std.cppm
+      ${std_module_SOURCE_DIR}/std.compat.cppm
+  )
 
   #
-  # Adjust project linker flags
+  # Adjust project include directories
   #
 
-  add_link_options($<$<COMPILE_LANGUAGE:CXX>:-nostdlib++>)
-  add_link_options($<$<COMPILE_LANGUAGE:CXX>:-L${LIBCXX_BUILD}/lib>)
-  add_link_options($<$<COMPILE_LANGUAGE:CXX>:-Wl,-rpath,${LIBCXX_BUILD}/lib>)
-  # Linking against the standard c++ library is required for CMake to get the proper dependencies.
-  link_libraries(std c++)
-  link_libraries(std.compat c++)
+  target_include_directories(std SYSTEM PUBLIC ${LIBCXX_INSTALLED_DIR}/include/c++/v1)
 
   #
-  # Add the project
+  # Adjust project compiler flags
   #
 
-  add_executable(main)
-  target_sources(main
+  target_compile_options(std
     PRIVATE
-      main.cpp
+      -Wno-reserved-module-identifier
+      -Wno-reserved-user-defined-literal
   )
 
+  target_compile_options(std
+    PUBLIC
+      -nostdinc++
+  )
+
+  #
+  # Adjust project linker flags
+  #
+
+  target_link_options(std
+    INTERFACE
+      -nostdlib++
+      -L${LIBCXX_INSTALLED_DIR}/lib
+      -Wl,-rpath,${LIBCXX_INSTALLED_DIR}/lib
+  )
+
+  target_link_libraries(std
+    INTERFACE
+      c++
+  )
+  
+  #
+  # Link to the std modules by default
+  #
+
+  link_libraries(std)
+
 Building this project is done with the following steps, assuming the files
-``main.cpp`` and ``CMakeLists.txt`` are copied in the current directory.
+``main.cpp``, ``CMakeLists.txt``, and ``std.cmake`` are copied in the current directory.
 
 .. code-block:: bash
 

>From 2392e8b20c4ed205fcae80b7576e28e9996ed2f5 Mon Sep 17 00:00:00 2001
From: LI Runzhong <858438680 at qq.com>
Date: Tue, 5 Mar 2024 02:43:28 +0800
Subject: [PATCH 7/8] [libc++][doc] Fix libc++ build script

---
 libcxx/docs/Modules.rst | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/libcxx/docs/Modules.rst b/libcxx/docs/Modules.rst
index efbdd78699a55c..8a961ffbf129a6 100644
--- a/libcxx/docs/Modules.rst
+++ b/libcxx/docs/Modules.rst
@@ -118,8 +118,8 @@ installation of modules and install the modules into ``<install_prefix>``.
   $ cd llvm-project
   $ mkdir build
   $ cmake -G Ninja -S runtimes -B build -DLIBCXX_INSTALL_MODULES=ON -DLLVM_ENABLE_RUNTIMES="libcxx;libcxxabi;libunwind"
-  $ ninja --build build -- -j $(nproc)
-  $ ninja --install build --prefix <install_prefix>
+  $ cmake --build build -- -j $(nproc)
+  $ cmake --install build --prefix <install_prefix>
 
 The above ``build`` directory will be referred to as ``<build>`` in the
 rest of these instructions.

>From 24770c909f5aba4903256a6f2e5ed8cd5c00456d Mon Sep 17 00:00:00 2001
From: LI Runzhong <858438680 at qq.com>
Date: Tue, 5 Mar 2024 02:45:17 +0800
Subject: [PATCH 8/8] [libc++][doc] Remove the redundant note.

---
 libcxx/docs/Modules.rst | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/libcxx/docs/Modules.rst b/libcxx/docs/Modules.rst
index 8a961ffbf129a6..b354600855b207 100644
--- a/libcxx/docs/Modules.rst
+++ b/libcxx/docs/Modules.rst
@@ -393,9 +393,6 @@ Building this project is done with the following steps, assuming the files
              in `LLVM Debian/Ubuntu nightly packages <https://apt.llvm.org>`__ to install
              essential components to build this project.
 
-.. note:: The ``std`` dependencies of ``std.compat`` is not always resolved when
-          building the ``std`` target using multiple jobs.
-
 .. warning:: ``<path-to-compiler>`` should point point to the real binary and
              not to a symlink.
 



More information about the libcxx-commits mailing list