[libcxx-commits] [libcxx] f0c5ce0 - [libc++][Modules] Generate the __std_clang_module header

Ian Anderson via libcxx-commits libcxx-commits at lists.llvm.org
Mon Aug 14 12:08:05 PDT 2023


Author: Ian Anderson
Date: 2023-08-14T12:08:00-07:00
New Revision: f0c5ce0800ea018c848158fbce43e8820b22119c

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

LOG: [libc++][Modules] Generate the __std_clang_module header

Use header_information to generate the __std_clang_module header. Instead of using lit_header_restrictions like the manually written header did, make a new header_include_requirements to codify what can be included rather than what can be fully tested.

Reviewed By: Mordante, #libc

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

Added: 
    libcxx/utils/generate_std_clang_module_header.py

Modified: 
    libcxx/include/__std_clang_module
    libcxx/test/libcxx/modules_include.gen.py
    libcxx/utils/CMakeLists.txt
    libcxx/utils/libcxx/header_information.py

Removed: 
    


################################################################################
diff  --git a/libcxx/include/__std_clang_module b/libcxx/include/__std_clang_module
index 61a926eb6307e8..46f50e87515b56 100644
--- a/libcxx/include/__std_clang_module
+++ b/libcxx/include/__std_clang_module
@@ -7,6 +7,10 @@
 //
 //===----------------------------------------------------------------------===//
 
+// WARNING, this entire header is generated by
+// utils/generate_std_clang_module_header.py
+// DO NOT MODIFY!
+
 // This header should not be directly included, it's exclusively to import all
 // of the libc++ public clang modules for the `std` clang module to export. In
 // other words, it's to facilitate `@import std;` in Objective-C++ and `import std`
@@ -17,7 +21,6 @@
 #  error "Do not include this header directly, include individual headers instead"
 #endif
 
-#include <__availability>
 #include <__config>
 
 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
@@ -27,52 +30,109 @@
 #include <algorithm>
 #include <any>
 #include <array>
-#include <atomic>
 #include <bit>
 #include <bitset>
+#include <cassert>
+#include <ccomplex>
+#include <cctype>
+#include <cerrno>
+#include <cfenv>
+#include <cfloat>
 #include <charconv>
 #include <chrono>
+#include <cinttypes>
+#include <ciso646>
+#include <climits>
+#include <cmath>
 #include <compare>
+#include <complex.h>
 #include <complex>
 #include <concepts>
 #include <condition_variable>
+#include <coroutine>
+#include <csetjmp>
+#include <csignal>
+#include <cstdarg>
+#include <cstdbool>
+#include <cstddef>
+#include <cstdint>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+#include <ctgmath>
+#include <ctime>
+#include <ctype.h>
+#include <cuchar>
 #include <deque>
+#include <errno.h>
 #include <exception>
 #include <execution>
 #include <expected>
+#include <experimental/deque>
+#include <experimental/forward_list>
+#include <experimental/iterator>
+#include <experimental/list>
+#include <experimental/map>
+#include <experimental/memory_resource>
+#include <experimental/propagate_const>
+#include <experimental/set>
+#include <experimental/simd>
+#include <experimental/string>
+#include <experimental/type_traits>
+#include <experimental/unordered_map>
+#include <experimental/unordered_set>
+#include <experimental/utility>
+#include <experimental/vector>
+#include <fenv.h>
+#include <filesystem>
+#include <float.h>
 #include <format>
 #include <forward_list>
 #include <functional>
 #include <initializer_list>
+#include <inttypes.h>
 #include <iosfwd>
 #include <iterator>
+#include <limits.h>
 #include <limits>
 #include <list>
 #include <map>
+#include <math.h>
 #include <mdspan>
 #include <memory>
 #include <memory_resource>
+#include <mutex>
 #include <new>
 #include <numbers>
 #include <numeric>
 #include <optional>
+#include <print>
 #include <queue>
 #include <random>
 #include <ranges>
 #include <ratio>
 #include <scoped_allocator>
 #include <set>
+#include <setjmp.h>
 #include <source_location>
 #include <span>
 #include <stack>
+#include <stdbool.h>
+#include <stddef.h>
 #include <stdexcept>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
 #include <string>
 #include <string_view>
 #include <system_error>
+#include <tgmath.h>
 #include <tuple>
 #include <type_traits>
 #include <typeindex>
 #include <typeinfo>
+#include <uchar.h>
 #include <unordered_map>
 #include <unordered_set>
 #include <utility>
@@ -81,132 +141,42 @@
 #include <vector>
 #include <version>
 
-#include <cassert>
-#include <ccomplex>
-#include <cctype>
-#include <cerrno>
-#include <cfenv>
-#include <cfloat>
-#include <cinttypes>
-#include <ciso646>
-#include <climits>
-#include <cmath>
-#include <csetjmp>
-#include <csignal>
-#include <cstdarg>
-#include <cstdbool>
-#include <cstddef>
-#include <cstdint>
-#include <cstdio>
-#include <cstdlib>
-#include <cstring>
-#include <ctgmath>
-#include <ctime>
-#include <cuchar>
-
-#include <complex.h>
-#include <ctype.h>
-#include <errno.h>
-#include <fenv.h>
-#include <float.h>
-#include <inttypes.h>
-#include <limits.h>
-#include <math.h>
-#include <setjmp.h>
-#include <stdbool.h>
-#include <stddef.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <tgmath.h>
-#include <uchar.h>
+#ifndef _LIBCPP_HAS_NO_ATOMIC_HEADER
+#  include <atomic>
+#  include <stdatomic.h>
+#endif
 
 #ifndef _LIBCPP_HAS_NO_LOCALIZATION
+#  include <clocale>
 #  include <codecvt>
-#  ifndef _LIBCPP_HAS_NO_FILESYSTEM
-#    include <fstream>
-#  endif
+#  include <experimental/regex>
+#  include <fstream>
 #  include <iomanip>
 #  include <ios>
 #  include <iostream>
 #  include <istream>
+#  include <locale.h>
 #  include <locale>
 #  include <ostream>
 #  include <regex>
 #  include <sstream>
 #  include <streambuf>
 #  include <strstream>
+#endif
 
-#  include <clocale>
-
-#  include <locale.h>
+#ifndef _LIBCPP_HAS_NO_THREADS
+#  include <barrier>
+#  include <future>
+#  include <latch>
+#  include <semaphore>
+#  include <shared_mutex>
+#  include <stop_token>
+#  include <thread>
 #endif
 
 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
 #  include <cwchar>
 #  include <cwctype>
-
 #  include <wchar.h>
 #  include <wctype.h>
 #endif
-
-#ifdef _LIBCPP_AVAILABILITY_TO_CHARS_FLOATING_POINT
-#  include <print>
-#endif
-
-#ifndef _LIBCPP_CXX03_LANG
-#  ifndef _LIBCPP_HAS_NO_THREADS
-#    include <future>
-#    include <mutex>
-#    include <thread>
-#  endif
-
-#  include <experimental/deque>
-#  include <experimental/forward_list>
-#  include <experimental/iterator>
-#  include <experimental/list>
-#  include <experimental/map>
-#  include <experimental/memory_resource>
-#  include <experimental/propagate_const>
-#  ifndef _LIBCPP_HAS_NO_LOCALIZATION
-#    include <experimental/regex>
-#  endif
-#  include <experimental/set>
-#  include <experimental/simd>
-#  include <experimental/string>
-#  include <experimental/type_traits>
-#  include <experimental/unordered_map>
-#  include <experimental/unordered_set>
-#  include <experimental/utility>
-#  include <experimental/vector>
-#endif
-
-#if _LIBCPP_STD_VER >= 14
-#  ifndef _LIBCPP_HAS_NO_THREADS
-#    include <shared_mutex>
-#  endif
-#endif
-
-#if _LIBCPP_STD_VER >= 17
-#  ifndef _LIBCPP_HAS_NO_FILESYSTEM
-#    include <filesystem>
-#  endif
-#endif
-
-#if _LIBCPP_STD_VER >= 20
-#  include <coroutine>
-
-#  ifndef _LIBCPP_HAS_NO_THREADS
-#    include <barrier>
-#    include <latch>
-#    include <semaphore>
-#    include <stop_token>
-#  endif
-#endif
-
-#if _LIBCPP_STD_VER >= 23
-#  ifndef _LIBCPP_HAS_NO_THREADS
-#    include <stdatomic.h>
-#  endif
-#endif

diff  --git a/libcxx/test/libcxx/modules_include.gen.py b/libcxx/test/libcxx/modules_include.gen.py
index 8ca50b0877eeff..2e9fd73421ed20 100644
--- a/libcxx/test/libcxx/modules_include.gen.py
+++ b/libcxx/test/libcxx/modules_include.gen.py
@@ -16,8 +16,9 @@
 sys.path.append(sys.argv[1])
 from libcxx.header_information import lit_header_restrictions, public_headers
 
+BLOCKLIT = '' # block Lit from interpreting a RUN/XFAIL/etc inside the generation script
+
 for header in public_headers:
-  BLOCKLIT = '' # block Lit from interpreting a RUN/XFAIL/etc inside the generation script
   print(f"""\
 //--- {header}.compile.pass.cpp
 // RUN{BLOCKLIT}: %{{cxx}} %s %{{flags}} %{{compile_flags}} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only
@@ -45,7 +46,7 @@
 #include <{header}>
 """)
 
-print(f"""
+print(f"""\
 //--- __std_clang_module.compile.pass.mm
 // RUN{BLOCKLIT}: %{{cxx}} %s %{{flags}} %{{compile_flags}} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only
 
@@ -68,10 +69,6 @@
 // TODO: Investigate this failure
 // UNSUPPORTED{BLOCKLIT}: LIBCXX-FREEBSD-FIXME
 
-// Lit seems to compile this twice: once with the default flags and once with with
-// the flags specified in the RUN directive. Guard the first compile from failing.
-#if __has_feature(modules)
 @import std;
-#endif
 
 """)

diff  --git a/libcxx/utils/CMakeLists.txt b/libcxx/utils/CMakeLists.txt
index 0338432f344a0f..ce4e289290dce6 100644
--- a/libcxx/utils/CMakeLists.txt
+++ b/libcxx/utils/CMakeLists.txt
@@ -2,6 +2,10 @@ add_custom_target(libcxx-generate-feature-test-macros
     COMMAND "${Python3_EXECUTABLE}" "${LIBCXX_SOURCE_DIR}/utils/generate_feature_test_macro_components.py"
     COMMENT "Generate the <version> header and tests for feature test macros.")
 
+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-extended-grapheme-cluster-tables
     COMMAND
         "${Python3_EXECUTABLE}"
@@ -38,6 +42,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-extended-grapheme-cluster-tables
             libcxx-generate-extended-grapheme-cluster-tests
             libcxx-generate-escaped-output-table

diff  --git a/libcxx/utils/generate_std_clang_module_header.py b/libcxx/utils/generate_std_clang_module_header.py
new file mode 100644
index 00000000000000..bcf0c220b7c59d
--- /dev/null
+++ b/libcxx/utils/generate_std_clang_module_header.py
@@ -0,0 +1,82 @@
+# ===----------------------------------------------------------------------===##
+#
+# 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
+
+import libcxx.header_information
+
+public_headers = libcxx.header_information.public_headers
+header_include_requirements = libcxx.header_information.header_include_requirements
+always_available_headers = frozenset(public_headers).
diff erence(
+    *header_include_requirements.values()
+)
+
+libcxx_include_directory = os.path.join(
+    os.path.dirname(os.path.dirname(os.path.realpath(__file__))), "include"
+)
+with open(
+    os.path.join(libcxx_include_directory, "__std_clang_module"), "w"
+) as std_clang_module_header:
+    std_clang_module_header.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_clang_module_header.py
+// DO NOT MODIFY!
+
+// This header should not be directly included, it's exclusively to import all
+// of the libc++ public clang modules for the `std` clang module to export. In
+// other words, it's to facilitate `@import std;` in Objective-C++ and `import std`
+// in Swift to expose all of the libc++ interfaces. This is generally not
+// recommended, however there are some clients that need to import all of libc++
+// without knowing what "all" is.
+#if !__building_module(std)
+#  error "Do not include this header directly, include individual headers instead"
+#endif
+
+#include <__config>
+
+#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
+#  pragma GCC system_header
+#endif
+
+"""
+    )
+    # Include the angle brackets in sorting so that <a.h> sorts before <a>
+    # like check-format wants.
+    for include in sorted([f"<{header}>" for header in always_available_headers]):
+        std_clang_module_header.write(f"#include {include}\n")
+
+    for requirements, headers in sorted(
+        header_include_requirements.items(), key=operator.itemgetter(0)
+    ):
+        std_clang_module_header.write("\n")
+        if len(requirements) == 1:
+            std_clang_module_header.write("#ifndef ")
+            std_clang_module_header.write(requirements[0])
+        else:
+            std_clang_module_header.write("#if")
+            for index, requirement in enumerate(requirements):
+                if index > 0:
+                    std_clang_module_header.write(" &&")
+                std_clang_module_header.write(f" !defined({requirement})")
+        std_clang_module_header.write("\n")
+
+        for include in sorted([f"<{header}>" for header in headers]):
+            std_clang_module_header.write(f"#  include {include}\n")
+
+        std_clang_module_header.write("#endif\n")

diff  --git a/libcxx/utils/libcxx/header_information.py b/libcxx/utils/libcxx/header_information.py
index e32996f92c9c69..cfeadc90eb4c4e 100644
--- a/libcxx/utils/libcxx/header_information.py
+++ b/libcxx/utils/libcxx/header_information.py
@@ -57,6 +57,52 @@
     "wctype.h": "// UNSUPPORTED: no-wide-characters",
 }
 
+header_include_requirements = {
+    ("_LIBCPP_HAS_NO_ATOMIC_HEADER",): (
+        # headers with #error directives
+        "atomic",
+        # transitive includers of the above headers
+        "stdatomic.h",
+    ),
+    ("_LIBCPP_HAS_NO_LOCALIZATION",): (
+        # headers with #error directives
+        "ios",
+        "locale.h",
+        # transitive includers of the above headers
+        "clocale",
+        "codecvt",
+        "experimental/regex",
+        "fstream",
+        "iomanip",
+        "iostream",
+        "istream",
+        "locale",
+        "ostream",
+        "regex",
+        "sstream",
+        "streambuf",
+        "strstream",
+    ),
+    ("_LIBCPP_HAS_NO_THREADS",): (
+        # headers with #error directives
+        "barrier",
+        "future",
+        "latch",
+        "semaphore",
+        "shared_mutex",
+        "stop_token",
+        "thread",
+    ),
+    ("_LIBCPP_HAS_NO_WIDE_CHARACTERS",): (
+        # headers with #error directives
+        "wchar.h",
+        "wctype.h",
+        # transitive includers of the above headers
+        "cwchar",
+        "cwctype",
+    ),
+}
+
 # This table was produced manually, by grepping the TeX source of the Standard's
 # library clauses for the string "#include". Each header's synopsis contains
 # explicit "#include" directives for its mandatory inclusions.


        


More information about the libcxx-commits mailing list