From 0e9a01dcac99ccf599738cef394b840b126d5cc9 Mon Sep 17 00:00:00 2001 From: Louis Dionne Date: Mon, 23 May 2022 16:48:47 -0400 Subject: [PATCH] [libc++] Fix modules builds when features are removed When some headers are not available because we removed features like localization or threads, the compiler should not try to include these headers when building modules. To avoid that from happening, add a requires-declaration that is never satisfied when the configuration in use doesn't support a header. rdar://93777687 Differential Revision: https://reviews.llvm.org/D127127 --- libcxx/docs/Contributing.rst | 2 +- libcxx/include/CMakeLists.txt | 11 +++++- libcxx/include/csignal | 5 ++- .../{module.modulemap => module.modulemap.in} | 45 ++++++++++++++++++++-- libcxx/test/libcxx/lint/lint_headers.sh.py | 2 +- libcxx/test/libcxx/lint/lint_modulemap.sh.py | 8 ++-- libcxx/test/libcxx/modules_include.sh.cpp | 4 -- libcxx/utils/generate_header_tests.py | 2 +- libcxx/utils/libcxx/test/dsl.py | 8 ++-- libcxx/utils/libcxx/test/features.py | 4 +- 10 files changed, 68 insertions(+), 23 deletions(-) rename libcxx/include/{module.modulemap => module.modulemap.in} (97%) diff --git a/libcxx/docs/Contributing.rst b/libcxx/docs/Contributing.rst index b812b95..9806f9b 100644 --- a/libcxx/docs/Contributing.rst +++ b/libcxx/docs/Contributing.rst @@ -37,7 +37,7 @@ sure you don't forget anything: - Did you mark all functions and type declarations with the :ref:`proper visibility macro `? - If you added a header: - - Did you add it to ``include/module.modulemap``? + - Did you add it to ``include/module.modulemap.in``? - Did you add it to ``include/CMakeLists.txt``? - If it's a public header, did you add a test under ``test/libcxx`` that the new header defines ``_LIBCPP_VERSION``? See ``test/libcxx/algorithms/version.pass.cpp`` for an example. NOTE: This should be automated. - If it's a public header, did you update ``utils/generate_header_inclusion_tests.py``? diff --git a/libcxx/include/CMakeLists.txt b/libcxx/include/CMakeLists.txt index 8f2a66f..3f89fee 100644 --- a/libcxx/include/CMakeLists.txt +++ b/libcxx/include/CMakeLists.txt @@ -618,7 +618,6 @@ set(files map math.h memory - module.modulemap mutex new numbers @@ -669,9 +668,17 @@ set(files wctype.h ) +foreach(feature LIBCXX_ENABLE_FILESYSTEM LIBCXX_ENABLE_LOCALIZATION LIBCXX_ENABLE_THREADS LIBCXX_ENABLE_WIDE_CHARACTERS) + if (NOT ${${feature}}) + set(requires_${feature} "requires LIBCXX_CONFIGURED_WITHOUT_SUPPORT_FOR_THIS_HEADER") + endif() +endforeach() + configure_file("__config_site.in" "${LIBCXX_GENERATED_INCLUDE_TARGET_DIR}/__config_site" @ONLY) +configure_file("module.modulemap.in" "${LIBCXX_GENERATED_INCLUDE_DIR}/module.modulemap" @ONLY) -set(_all_includes "${LIBCXX_GENERATED_INCLUDE_TARGET_DIR}/__config_site") +set(_all_includes "${LIBCXX_GENERATED_INCLUDE_TARGET_DIR}/__config_site" + "${LIBCXX_GENERATED_INCLUDE_DIR}/module.modulemap") foreach(f ${files}) set(src "${CMAKE_CURRENT_SOURCE_DIR}/${f}") set(dst "${LIBCXX_GENERATED_INCLUDE_DIR}/${f}") diff --git a/libcxx/include/csignal b/libcxx/include/csignal index 81ca890..c1b58f8 100644 --- a/libcxx/include/csignal +++ b/libcxx/include/csignal @@ -41,7 +41,10 @@ int raise(int sig); #include <__assert> // all public C++ headers provide the assertion handler #include <__config> -#include + +#if __has_include() +# include +#endif #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header diff --git a/libcxx/include/module.modulemap b/libcxx/include/module.modulemap.in similarity index 97% rename from libcxx/include/module.modulemap rename to libcxx/include/module.modulemap.in index 0194612..b89983b 100644 --- a/libcxx/include/module.modulemap +++ b/libcxx/include/module.modulemap.in @@ -38,6 +38,7 @@ module std [system] { // provided by compiler. // provided by compiler or C library. module locale_h { + @requires_LIBCXX_ENABLE_LOCALIZATION@ header "locale.h" export * } @@ -50,6 +51,7 @@ module std [system] { export * } module stdatomic_h { + @requires_LIBCXX_ENABLE_THREADS@ requires cplusplus23 header "stdatomic.h" export * @@ -90,11 +92,13 @@ module std [system] { } // provided by C library. module wchar_h { + @requires_LIBCXX_ENABLE_WIDE_CHARACTERS@ // 's __need_* macros require textual inclusion. textual header "wchar.h" export * } module wctype_h { + @requires_LIBCXX_ENABLE_WIDE_CHARACTERS@ header "wctype.h" export * } @@ -155,6 +159,7 @@ module std [system] { export * } module clocale { + @requires_LIBCXX_ENABLE_LOCALIZATION@ header "clocale" export * } @@ -215,11 +220,13 @@ module std [system] { export * } module cwchar { + @requires_LIBCXX_ENABLE_WIDE_CHARACTERS@ header "cwchar" export depr.stdio_h export * } module cwctype { + @requires_LIBCXX_ENABLE_WIDE_CHARACTERS@ header "cwctype" export * } @@ -382,6 +389,7 @@ module std [system] { export * } module barrier { + @requires_LIBCXX_ENABLE_THREADS@ header "barrier" export * } @@ -425,7 +433,11 @@ module std [system] { module duration { private header "__chrono/duration.h" } module file_clock { private header "__chrono/file_clock.h" } module hh_mm_ss { private header "__chrono/hh_mm_ss.h" } - module high_resolution_clock { private header "__chrono/high_resolution_clock.h" } + module high_resolution_clock { + private header "__chrono/high_resolution_clock.h" + export steady_clock + export system_clock + } module literals { private header "__chrono/literals.h" } module month { private header "__chrono/month.h" } module month_weekday { private header "__chrono/month_weekday.h" } @@ -441,6 +453,7 @@ module std [system] { } } module codecvt { + @requires_LIBCXX_ENABLE_LOCALIZATION@ header "codecvt" export * } @@ -528,6 +541,7 @@ module std [system] { export * } module filesystem { + @requires_LIBCXX_ENABLE_FILESYSTEM@ header "filesystem" export * @@ -588,6 +602,7 @@ module std [system] { export * } module fstream { + @requires_LIBCXX_ENABLE_LOCALIZATION@ header "fstream" export * } @@ -626,6 +641,7 @@ module std [system] { } } module future { + @requires_LIBCXX_ENABLE_THREADS@ header "future" export * } @@ -634,10 +650,12 @@ module std [system] { export * } module iomanip { + @requires_LIBCXX_ENABLE_LOCALIZATION@ header "iomanip" export * } module ios { + @requires_LIBCXX_ENABLE_LOCALIZATION@ header "ios" export iosfwd export * @@ -651,6 +669,7 @@ module std [system] { export * } module iostream { + @requires_LIBCXX_ENABLE_LOCALIZATION@ header "iostream" export ios export streambuf @@ -659,6 +678,7 @@ module std [system] { export * } module istream { + @requires_LIBCXX_ENABLE_LOCALIZATION@ header "istream" // FIXME: should re-export ios, streambuf? export * @@ -711,6 +731,7 @@ module std [system] { } } module latch { + @requires_LIBCXX_ENABLE_THREADS@ header "latch" export * } @@ -724,6 +745,7 @@ module std [system] { export * } module locale { + @requires_LIBCXX_ENABLE_LOCALIZATION@ header "locale" export * } @@ -761,6 +783,7 @@ module std [system] { } } module mutex { + @requires_LIBCXX_ENABLE_THREADS@ header "mutex" export * } @@ -797,6 +820,7 @@ module std [system] { export * } module ostream { + @requires_LIBCXX_ENABLE_LOCALIZATION@ header "ostream" // FIXME: should re-export ios, streambuf? export * @@ -909,6 +933,7 @@ module std [system] { export * } module regex { + @requires_LIBCXX_ENABLE_LOCALIZATION@ header "regex" export initializer_list export * @@ -918,6 +943,7 @@ module std [system] { export * } module semaphore { + @requires_LIBCXX_ENABLE_THREADS@ header "semaphore" export * } @@ -927,6 +953,7 @@ module std [system] { export * } module shared_mutex { + @requires_LIBCXX_ENABLE_THREADS@ header "shared_mutex" export version } @@ -937,6 +964,7 @@ module std [system] { module span_fwd { private header "__fwd/span.h" } } module sstream { + @requires_LIBCXX_ENABLE_LOCALIZATION@ header "sstream" // FIXME: should re-export istream, ostream, ios, streambuf, string? export * @@ -951,6 +979,7 @@ module std [system] { export * } module streambuf { + @requires_LIBCXX_ENABLE_LOCALIZATION@ header "streambuf" export * } @@ -969,6 +998,7 @@ module std [system] { module string_view_fwd { private header "__fwd/string_view.h" } } module strstream { + @requires_LIBCXX_ENABLE_LOCALIZATION@ header "strstream" export * } @@ -977,6 +1007,7 @@ module std [system] { export * } module thread { + @requires_LIBCXX_ENABLE_THREADS@ header "thread" export * @@ -1118,7 +1149,6 @@ module std [system] { export * } - // __config not modularised due to a bug in Clang // FIXME: These should be private. module __assert { header "__assert" export * } module __availability { private header "__availability" export * } @@ -1127,12 +1157,18 @@ module std [system] { module __debug { header "__debug" export * } module __errc { private header "__errc" export * } module __hash_table { header "__hash_table" export * } - module __locale { private header "__locale" export * } + module __locale { + @requires_LIBCXX_ENABLE_LOCALIZATION@ + private header "__locale" export * + } module __mbstate_t { private header "__mbstate_t.h" export * } module __mutex_base { private header "__mutex_base" export * } module __node_handle { private header "__node_handle" export * } module __split_buffer { private header "__split_buffer" export * } - module __std_stream { private header "__std_stream" export * } + module __std_stream { + @requires_LIBCXX_ENABLE_LOCALIZATION@ + private header "__std_stream" export * + } module __string { private header "__string" export * } module __threading_support { header "__threading_support" export * } module __tree { header "__tree" export * } @@ -1184,6 +1220,7 @@ module std [system] { export * } module regex { + @requires_LIBCXX_ENABLE_LOCALIZATION@ header "experimental/regex" export * } diff --git a/libcxx/test/libcxx/lint/lint_headers.sh.py b/libcxx/test/libcxx/lint/lint_headers.sh.py index 9075044..9113b1a 100644 --- a/libcxx/test/libcxx/lint/lint_headers.sh.py +++ b/libcxx/test/libcxx/lint/lint_headers.sh.py @@ -11,7 +11,7 @@ import re def exclude_from_consideration(path): return ( path.endswith('.txt') or - path.endswith('.modulemap') or + path.endswith('.modulemap.in') or os.path.basename(path) == '__config' or os.path.basename(path) == '__config_site.in' or not os.path.isfile(path) diff --git a/libcxx/test/libcxx/lint/lint_modulemap.sh.py b/libcxx/test/libcxx/lint/lint_modulemap.sh.py index e167813..bbb5885 100755 --- a/libcxx/test/libcxx/lint/lint_modulemap.sh.py +++ b/libcxx/test/libcxx/lint/lint_modulemap.sh.py @@ -1,6 +1,6 @@ # RUN: %{python} %s -# Verify that each list of private submodules in libcxx/include/module.modulemap +# Verify that each list of private submodules in libcxx/include/module.modulemap.in # is maintained in alphabetical order. import os @@ -10,7 +10,7 @@ import re if __name__ == '__main__': libcxx_test_libcxx_lint = os.path.dirname(os.path.abspath(__file__)) libcxx = os.path.abspath(os.path.join(libcxx_test_libcxx_lint, '../../..')) - modulemap_name = os.path.join(libcxx, 'include/module.modulemap') + modulemap_name = os.path.join(libcxx, 'include/module.modulemap.in') assert os.path.isfile(modulemap_name) okay = True @@ -31,12 +31,12 @@ if __name__ == '__main__': pass else: okay = False - print("LINE DOESN'T MATCH REGEX in libcxx/include/module.modulemap!") + print("LINE DOESN'T MATCH REGEX in libcxx/include/module.modulemap.in!") print(line) # Check that these lines are alphabetized. if (prevline is not None) and (line < prevline): okay = False - print('LINES OUT OF ORDER in libcxx/include/module.modulemap!') + print('LINES OUT OF ORDER in libcxx/include/module.modulemap.in!') print(prevline) print(line) prevline = line diff --git a/libcxx/test/libcxx/modules_include.sh.cpp b/libcxx/test/libcxx/modules_include.sh.cpp index 4dd8a8f..4ab1259 100644 --- a/libcxx/test/libcxx/modules_include.sh.cpp +++ b/libcxx/test/libcxx/modules_include.sh.cpp @@ -19,10 +19,6 @@ // The Windows headers don't appear to be compatible with modules // UNSUPPORTED: windows -// TODO: Some headers produce errors when we include them and the library has been -// configured without support for them, which breaks the modules build. -// UNSUPPORTED: no-localization, no-filesystem, no-threads, no-wide-characters - // Prevent from generating deprecated warnings for this test. #if defined(__DEPRECATED) # undef __DEPRECATED diff --git a/libcxx/utils/generate_header_tests.py b/libcxx/utils/generate_header_tests.py index fa9ab3c..59b9048 100755 --- a/libcxx/utils/generate_header_tests.py +++ b/libcxx/utils/generate_header_tests.py @@ -113,7 +113,7 @@ def produce(test_file, variables): def is_header(file): """Returns whether the given file is a header (i.e. not a directory or the modulemap file).""" - return not file.is_dir() and not file.name == 'module.modulemap' + return not file.is_dir() and not file.name == 'module.modulemap.in' def main(): monorepo_root = pathlib.Path(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))) diff --git a/libcxx/utils/libcxx/test/dsl.py b/libcxx/utils/libcxx/test/dsl.py index f43937a..e77ea8f 100644 --- a/libcxx/utils/libcxx/test/dsl.py +++ b/libcxx/utils/libcxx/test/dsl.py @@ -276,9 +276,11 @@ def compilerMacros(config, flags=''): """ with _makeConfigTest(config) as test: with open(test.getSourcePath(), 'w') as sourceFile: - # Make sure files like <__config> are included, since they can define - # additional macros. - sourceFile.write("#include ") + sourceFile.write(""" + #if __has_include(<__config_site>) + # include <__config_site> + #endif + """) unparsedOutput, err, exitCode, _ = _executeScriptInternal(test, [ "%{{cxx}} %s -dM -E %{{flags}} %{{compile_flags}} {}".format(flags) ]) diff --git a/libcxx/utils/libcxx/test/features.py b/libcxx/utils/libcxx/test/features.py index d7e4c84..d805ae6 100644 --- a/libcxx/utils/libcxx/test/features.py +++ b/libcxx/utils/libcxx/test/features.py @@ -82,7 +82,7 @@ DEFAULT_FEATURES = [ # Check for a Windows UCRT bug (fixed in UCRT/Windows 10.0.20348.0): # https://developercommunity.visualstudio.com/t/utf-8-locales-break-ctype-functions-for-wchar-type/1653678 Feature(name='win32-broken-utf8-wchar-ctype', - when=lambda cfg: '_WIN32' in compilerMacros(cfg) and not programSucceeds(cfg, """ + when=lambda cfg: not '_LIBCPP_HAS_NO_LOCALIZATION' in compilerMacros(cfg) and '_WIN32' in compilerMacros(cfg) and not programSucceeds(cfg, """ #include #include int main(int, char**) { @@ -94,7 +94,7 @@ DEFAULT_FEATURES = [ # Check for a Windows UCRT bug (fixed in UCRT/Windows 10.0.19041.0). # https://developercommunity.visualstudio.com/t/printf-formatting-with-g-outputs-too/1660837 Feature(name='win32-broken-printf-g-precision', - when=lambda cfg: '_WIN32' in compilerMacros(cfg) and not programSucceeds(cfg, """ + when=lambda cfg: not '_LIBCPP_HAS_NO_LOCALIZATION' in compilerMacros(cfg) and '_WIN32' in compilerMacros(cfg) and not programSucceeds(cfg, """ #include #include int main(int, char**) { -- 2.7.4