[libcxx-commits] [libcxx] 41161ae - [libc++][modules] Generates std.cppm.in.

Mark de Wever via libcxx-commits libcxx-commits at lists.llvm.org
Tue Aug 22 11:13:45 PDT 2023


Author: Mark de Wever
Date: 2023-08-22T20:13:39+02:00
New Revision: 41161aeb5460a8fea9f55c185b6cc6a438a491fb

URL: https://github.com/llvm/llvm-project/commit/41161aeb5460a8fea9f55c185b6cc6a438a491fb
DIFF: https://github.com/llvm/llvm-project/commit/41161aeb5460a8fea9f55c185b6cc6a438a491fb.diff

LOG: [libc++][modules] Generates std.cppm.in.

This takes the header restrictions into account instead of manually
duplicating this build information. This is a preparation to properly
support the libc++ disabled parts in the std module.

Reviewed By: #libc, ldionne

Differential Revision: https://reviews.llvm.org/D158192

Added: 
    libcxx/utils/generate_std_cppm_in.py

Modified: 
    libcxx/modules/std.cppm.in
    libcxx/test/libcxx/module_std.gen.py
    libcxx/utils/CMakeLists.txt
    libcxx/utils/libcxx/header_information.py

Removed: 
    


################################################################################
diff  --git a/libcxx/modules/std.cppm.in b/libcxx/modules/std.cppm.in
index dd611d5dbca386..65cec804ff122a 100644
--- a/libcxx/modules/std.cppm.in
+++ b/libcxx/modules/std.cppm.in
@@ -7,19 +7,25 @@
 //
 //===----------------------------------------------------------------------===//
 
+// WARNING, this entire header is generated by
+// utils/generate_std_cppm_in.py
+// DO NOT MODIFY!
+
 module;
 
 #include <__config>
 
-// TODO MODULES This could be generated
-
 // 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]
 #include <algorithm>
 #include <any>
 #include <array>
-#include <atomic>
-#include <barrier>
+#if !defined(_LIBCPP_HAS_NO_ATOMIC_HEADER)
+#  include <atomic>
+#endif
+#if !defined(_LIBCPP_HAS_NO_THREADS)
+#  include <barrier>
+#endif
 #include <bit>
 #include <bitset>
 #include <cassert>
@@ -31,7 +37,13 @@ module;
 #include <chrono>
 #include <cinttypes>
 #include <climits>
+#if !defined(_LIBCPP_HAS_NO_LOCALIZATION)
+#  include <clocale>
+#endif
 #include <cmath>
+#if !defined(_LIBCPP_HAS_NO_LOCALIZATION)
+#  include <codecvt>
+#endif
 #include <compare>
 #include <complex>
 #include <concepts>
@@ -47,6 +59,12 @@ module;
 #include <cstring>
 #include <ctime>
 #include <cuchar>
+#if !defined(_LIBCPP_HAS_NO_WIDE_CHARACTERS)
+#  include <cwchar>
+#endif
+#if !defined(_LIBCPP_HAS_NO_WIDE_CHARACTERS)
+#  include <cwctype>
+#endif
 #include <deque>
 #include <exception>
 #include <execution>
@@ -54,14 +72,36 @@ module;
 #include <filesystem>
 #include <format>
 #include <forward_list>
+#if !defined(_LIBCPP_HAS_NO_LOCALIZATION)
+#  include <fstream>
+#endif
 #include <functional>
-#include <future>
+#if !defined(_LIBCPP_HAS_NO_THREADS)
+#  include <future>
+#endif
 #include <initializer_list>
+#if !defined(_LIBCPP_HAS_NO_LOCALIZATION)
+#  include <iomanip>
+#endif
+#if !defined(_LIBCPP_HAS_NO_LOCALIZATION)
+#  include <ios>
+#endif
 #include <iosfwd>
+#if !defined(_LIBCPP_HAS_NO_LOCALIZATION)
+#  include <iostream>
+#endif
+#if !defined(_LIBCPP_HAS_NO_LOCALIZATION)
+#  include <istream>
+#endif
 #include <iterator>
-#include <latch>
+#if !defined(_LIBCPP_HAS_NO_THREADS)
+#  include <latch>
+#endif
 #include <limits>
 #include <list>
+#if !defined(_LIBCPP_HAS_NO_LOCALIZATION)
+#  include <locale>
+#endif
 #include <map>
 #include <mdspan>
 #include <memory>
@@ -71,24 +111,47 @@ module;
 #include <numbers>
 #include <numeric>
 #include <optional>
+#if !defined(_LIBCPP_HAS_NO_LOCALIZATION)
+#  include <ostream>
+#endif
 #include <print>
 #include <queue>
 #include <random>
 #include <ranges>
 #include <ratio>
+#if !defined(_LIBCPP_HAS_NO_LOCALIZATION)
+#  include <regex>
+#endif
 #include <scoped_allocator>
-#include <semaphore>
+#if !defined(_LIBCPP_HAS_NO_THREADS)
+#  include <semaphore>
+#endif
 #include <set>
-#include <shared_mutex>
+#if !defined(_LIBCPP_HAS_NO_THREADS)
+#  include <shared_mutex>
+#endif
 #include <source_location>
 #include <span>
+#if !defined(_LIBCPP_HAS_NO_LOCALIZATION)
+#  include <sstream>
+#endif
 #include <stack>
 #include <stdexcept>
-#include <stop_token>
+#if !defined(_LIBCPP_HAS_NO_THREADS)
+#  include <stop_token>
+#endif
+#if !defined(_LIBCPP_HAS_NO_LOCALIZATION)
+#  include <streambuf>
+#endif
 #include <string>
 #include <string_view>
+#if !defined(_LIBCPP_HAS_NO_LOCALIZATION)
+#  include <strstream>
+#endif
 #include <system_error>
-#include <thread>
+#if !defined(_LIBCPP_HAS_NO_THREADS)
+#  include <thread>
+#endif
 #include <tuple>
 #include <type_traits>
 #include <typeindex>
@@ -101,68 +164,36 @@ module;
 #include <vector>
 #include <version>
 
-// *** Headers disabled by a feature ***
-
-#ifndef _LIBCPP_HAS_NO_LOCALIZATION
-#  include <clocale>
-#  include <codecvt>
-#  include <fstream>
-#  include <iomanip>
-#  include <ios>
-#  include <iostream>
-#  include <istream>
-#  include <locale>
-#  include <ostream>
-#  include <regex>
-#  include <sstream>
-#  include <streambuf>
-#  include <strstream>
-#endif // _LIBCPP_HAS_NO_LOCALIZATION
-#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
-#  include <cwchar>
-#  include <cwctype>
-#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
-
 // *** Headers not yet available ***
+#if __has_include(<flat_map>)
+#  error "update the header information for <flat_map> in libcxx/utils/generate_std_cppm_in.py"
+#endif //   __has_include(<flat_map>)
+#if __has_include(<flat_set>)
+#  error "update the header information for <flat_set> in libcxx/utils/generate_std_cppm_in.py"
+#endif //   __has_include(<flat_set>)
 #if __has_include(<generator>)
-#  error "include <generator> unconditionally"
-#  include <generator>
+#  error "update the header information for <generator> in libcxx/utils/generate_std_cppm_in.py"
 #endif //   __has_include(<generator>)
 #if __has_include(<hazard_pointer>)
-#  error "include <hazard_pointer> unconditionally"
-#  include <hazard_pointer>
+#  error "update the header information for <hazard_pointer> in libcxx/utils/generate_std_cppm_in.py"
 #endif //   __has_include(<hazard_pointer>)
-#if __has_include(<flat_map>)
-#  error "include <flat_map> unconditionally"
-#  include <flat_map>
-#endif // __has_include(<flat_map>)
-#if __has_include(<flat_set>)
-#  error "include <flat_set> unconditionally"
-#  include <flat_set>
-#endif //  __has_include(<flat_set>)
 #if __has_include(<rcu>)
-#  error "include <rcu> unconditionally"
-#  include <rcu>
+#  error "update the header information for <rcu> in libcxx/utils/generate_std_cppm_in.py"
 #endif //   __has_include(<rcu>)
 #if __has_include(<spanstream>)
-#  error "include <spanstream> unconditionally"
-#  include <spanstream>
+#  error "update the header information for <spanstream> in libcxx/utils/generate_std_cppm_in.py"
 #endif //   __has_include(<spanstream>)
 #if __has_include(<stacktrace>)
-#  error "include <stacktrace> unconditionally"
-#  include <stacktrace>
+#  error "update the header information for <stacktrace> in libcxx/utils/generate_std_cppm_in.py"
 #endif //   __has_include(<stacktrace>)
 #if __has_include(<stdfloat>)
-#  error "include <stdfloat> unconditionally"
-#  include <stdfloat>
+#  error "update the header information for <stdfloat> in libcxx/utils/generate_std_cppm_in.py"
 #endif //   __has_include(<stdfloat>)
 #if __has_include(<syncstream>)
-#  error "include <syncstream> unconditionally"
-#  include <syncstream>
+#  error "update the header information for <syncstream> in libcxx/utils/generate_std_cppm_in.py"
 #endif //   __has_include(<syncstream>)
 #if __has_include(<text_encoding>)
-#  error "include <text_encoding> unconditionally"
-#  include <text_encoding>
+#  error "update the header information for <text_encoding> in libcxx/utils/generate_std_cppm_in.py"
 #endif //   __has_include(<text_encoding>)
 
 export module std;

diff  --git a/libcxx/test/libcxx/module_std.gen.py b/libcxx/test/libcxx/module_std.gen.py
index af9b652911bdcb..6d146252754900 100644
--- a/libcxx/test/libcxx/module_std.gen.py
+++ b/libcxx/test/libcxx/module_std.gen.py
@@ -21,22 +21,12 @@
 import sys
 
 sys.path.append(sys.argv[1])
-from libcxx.header_information import toplevel_headers
+from libcxx.header_information import module_headers
 
 BLOCKLIT = (
     ""  # block Lit from interpreting a RUN/XFAIL/etc inside the generation script
 )
 
-### Remove the headers that have no module associated with them
-
-# Note all C-headers using .h are filtered in the loop.
-
-# These headers are not available in C++23, but in older language Standards.
-toplevel_headers.remove("ccomplex")
-toplevel_headers.remove("ciso646")
-toplevel_headers.remove("cstdbool")
-toplevel_headers.remove("ctgmath")
-
 # Ignore several declarations found in the includes.
 #
 # Part of these items are bugs other are not yet implemented features.
@@ -140,10 +130,7 @@
 )
 
 # Validate all module parts.
-for header in toplevel_headers:
-    if header.endswith(".h"):  # Skip C compatibility headers
-        continue
-
+for header in module_headers:
     # Generate a module partition for the header module includes. This
     # makes it possible to verify that all headers export all their
     # named declarations.

diff  --git a/libcxx/utils/CMakeLists.txt b/libcxx/utils/CMakeLists.txt
index ce4e289290dce6..7e597f632b6c46 100644
--- a/libcxx/utils/CMakeLists.txt
+++ b/libcxx/utils/CMakeLists.txt
@@ -6,6 +6,10 @@ add_custom_target(libcxx-generate-std-clang-module-header
   COMMAND "${Python3_EXECUTABLE}" "${CMAKE_CURRENT_SOURCE_DIR}/generate_std_clang_module_header.py"
   COMMENT "Generate the <__std_clang_module> header")
 
+add_custom_target(libcxx-generate-std-cppm-in-file
+  COMMAND "${Python3_EXECUTABLE}" "${CMAKE_CURRENT_SOURCE_DIR}/generate_std_cppm_in.py"
+  COMMENT "Generate the std.cppm.in file")
+
 add_custom_target(libcxx-generate-extended-grapheme-cluster-tables
     COMMAND
         "${Python3_EXECUTABLE}"
@@ -43,6 +47,7 @@ add_custom_target(libcxx-generate-iwyu-mapping
 add_custom_target(libcxx-generate-files
     DEPENDS libcxx-generate-feature-test-macros
             libcxx-generate-std-clang-module-header
+            libcxx-generate-std-cppm-in-file
             libcxx-generate-extended-grapheme-cluster-tables
             libcxx-generate-extended-grapheme-cluster-tests
             libcxx-generate-escaped-output-table

diff  --git a/libcxx/utils/generate_std_cppm_in.py b/libcxx/utils/generate_std_cppm_in.py
new file mode 100644
index 00000000000000..522f1dd8161aea
--- /dev/null
+++ b/libcxx/utils/generate_std_cppm_in.py
@@ -0,0 +1,74 @@
+# ===----------------------------------------------------------------------===##
+#
+# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+# See https://llvm.org/LICENSE.txt for license information.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+#
+# ===----------------------------------------------------------------------===##
+
+import operator
+import os.path
+
+from libcxx.header_information import module_headers
+from libcxx.header_information import header_restrictions
+from libcxx.header_information import headers_not_available
+
+
+libcxx_module_directory = os.path.join(
+    os.path.dirname(os.path.dirname(os.path.realpath(__file__))), "modules"
+)
+with open(
+    os.path.join(libcxx_module_directory, "std.cppm.in"), "w"
+) as std_module_cpp_in:
+    std_module_cpp_in.write(
+        """\
+// -*- C++ -*-
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// WARNING, this entire header is generated by
+// utils/generate_std_cppm_in.py
+// DO NOT MODIFY!
+
+module;
+
+#include <__config>
+
+// 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]
+"""
+    )
+    for header in module_headers:
+        if header in header_restrictions:
+            std_module_cpp_in.write(
+                f"""\
+#if {header_restrictions[header]}
+#  include <{header}>
+#endif
+"""
+            )
+        else:
+            std_module_cpp_in.write(f"#include <{header}>\n")
+
+    std_module_cpp_in.write("\n// *** Headers not yet available ***\n")
+    for header in sorted(headers_not_available):
+        std_module_cpp_in.write(
+            f"""\
+#if __has_include(<{header}>)
+#  error "update the header information for <{header}> in libcxx/utils/generate_std_cppm_in.py"
+#endif //   __has_include(<{header}>)
+"""
+        )
+
+    std_module_cpp_in.write(
+        """
+export module std;
+
+ at LIBCXX_MODULE_STD_INCLUDE_SOURCES@
+"""
+    )

diff  --git a/libcxx/utils/libcxx/header_information.py b/libcxx/utils/libcxx/header_information.py
index 683fe23638e17c..db6f3246f6ba71 100644
--- a/libcxx/utils/libcxx/header_information.py
+++ b/libcxx/utils/libcxx/header_information.py
@@ -141,6 +141,26 @@
     "vector": ["compare", "initializer_list"],
 }
 
+
+# These headers are not yet implemented in libc++
+#
+# These headers are required by the latest (draft) Standard but have not been
+# implemented yet. They are used in the generated module input. The C++23 standard
+# modules will fail to build if a header is added but this list is not updated.
+headers_not_available = [
+    "flat_map",
+    "flat_set",
+    "generator",
+    "hazard_pointer",
+    "rcu",
+    "spanstream",
+    "stacktrace",
+    "stdfloat",
+    "syncstream",
+    "text_encoding",
+]
+
+
 def is_header(file):
     """Returns whether the given file is a header (i.e. not a directory or the modulemap file)."""
     return (
@@ -159,6 +179,19 @@ def is_header(file):
     p.relative_to(include).as_posix() for p in include.glob("[a-z]*") if is_header(p)
 )
 experimental_headers = sorted(
-    p.relative_to(include).as_posix() for p in include.glob("experimental/[a-z]*") if is_header(p)
+    p.relative_to(include).as_posix()
+    for p in include.glob("experimental/[a-z]*")
+    if is_header(p)
 )
 public_headers = toplevel_headers + experimental_headers
+
+# The headers used in the std and std.compat modules.
+#
+# This is the set of all C++23-and-later headers, excluding C compatibility headers.
+module_headers = [
+    header
+    for header in toplevel_headers
+    if not header.endswith(".h")
+    # These headers have been removed in C++20 so are never part of a module.
+    and not header in ["ccomplex", "ciso646", "cstdbool", "ctgmath"]
+]


        


More information about the libcxx-commits mailing list