From c0cd106fcc9f35839b991271717dbdb69c4e2a10 Mon Sep 17 00:00:00 2001 From: Louis Dionne Date: Mon, 4 May 2020 17:05:21 -0400 Subject: [PATCH] [libc++] Move parsing of <__config_site> macros to the DSL --- libcxx/test/libcxx/selftest/dsl/dsl.sh.py | 14 +++++++ libcxx/utils/libcxx/test/config.py | 66 ------------------------------- libcxx/utils/libcxx/test/dsl.py | 6 ++- libcxx/utils/libcxx/test/features.py | 47 ++++++++++++++++++++++ 4 files changed, 65 insertions(+), 68 deletions(-) diff --git a/libcxx/test/libcxx/selftest/dsl/dsl.sh.py b/libcxx/test/libcxx/selftest/dsl/dsl.sh.py index abb4d92..c8f9984 100644 --- a/libcxx/test/libcxx/selftest/dsl/dsl.sh.py +++ b/libcxx/test/libcxx/selftest/dsl/dsl.sh.py @@ -185,6 +185,13 @@ class TestFeature(SetupConfigs): self.assertIn('-foo', self.getSubstitution('%{compile_flags}')) self.assertEqual(origLinkFlags, self.getSubstitution('%{link_flags}')) + def test_compile_flag_can_be_a_callable(self): + feature = dsl.Feature(name='name', + compileFlag=lambda cfg: (self.assertIs(self.config, cfg), '-foo')[1]) + assert feature.isSupported(self.config) + feature.enableIn(self.config) + self.assertIn('-foo', self.getSubstitution('%{compile_flags}')) + def test_adding_link_flag(self): feature = dsl.Feature(name='name', linkFlag='-foo') origCompileFlags = copy.deepcopy(self.getSubstitution('%{compile_flags}')) @@ -194,6 +201,13 @@ class TestFeature(SetupConfigs): self.assertIn('-foo', self.getSubstitution('%{link_flags}')) self.assertEqual(origCompileFlags, self.getSubstitution('%{compile_flags}')) + def test_link_flag_can_be_a_callable(self): + feature = dsl.Feature(name='name', + linkFlag=lambda cfg: (self.assertIs(self.config, cfg), '-foo')[1]) + assert feature.isSupported(self.config) + feature.enableIn(self.config) + self.assertIn('-foo', self.getSubstitution('%{link_flags}')) + def test_adding_both_flags(self): feature = dsl.Feature(name='name', compileFlag='-hello', linkFlag='-world') assert feature.isSupported(self.config) diff --git a/libcxx/utils/libcxx/test/config.py b/libcxx/utils/libcxx/test/config.py index 3e9cae4..09a7a5f 100644 --- a/libcxx/utils/libcxx/test/config.py +++ b/libcxx/utils/libcxx/test/config.py @@ -442,7 +442,6 @@ class Configuration(object): # Configure feature flags. self.configure_compile_flags_exceptions() self.configure_compile_flags_rtti() - self.configure_compile_flags_abi_version() enable_32bit = self.get_lit_bool('enable_32bit', False) if enable_32bit: self.cxx.flags += ['-m32'] @@ -531,63 +530,8 @@ class Configuration(object): config_site_header = os.path.join(self.libcxx_obj_root, '__config_site') if not os.path.isfile(config_site_header): return - contained_macros = self.parse_config_site_and_add_features( - config_site_header) - self.lit_config.note('Using __config_site header %s with macros: %r' - % (config_site_header, contained_macros)) - # FIXME: This must come after the call to - # 'parse_config_site_and_add_features(...)' in order for it to work. self.cxx.compile_flags += ['-include', config_site_header] - def parse_config_site_and_add_features(self, header): - """ parse_config_site_and_add_features - Deduce and add the test - features that that are implied by the #define's in the __config_site - header. Return a dictionary containing the macros found in the - '__config_site' header. - """ - # Parse the macro contents of __config_site by dumping the macros - # using 'c++ -dM -E' and filtering the predefines. - predefines = self._dump_macros_verbose() - macros = self._dump_macros_verbose(header) - feature_macros_keys = set(macros.keys()) - set(predefines.keys()) - feature_macros = {} - for k in feature_macros_keys: - feature_macros[k] = macros[k] - # We expect the header guard to be one of the definitions - assert '_LIBCPP_CONFIG_SITE' in feature_macros - del feature_macros['_LIBCPP_CONFIG_SITE'] - # The __config_site header should be non-empty. Otherwise it should - # have never been emitted by CMake. - assert len(feature_macros) > 0 - # FIXME: This is a hack that should be fixed using module maps. - # If modules are enabled then we have to lift all of the definitions - # in __config_site onto the command line. - for m in feature_macros: - define = '-D%s' % m - if feature_macros[m]: - define += '=%s' % (feature_macros[m]) - self.cxx.modules_flags += [define] - self.cxx.compile_flags += ['-Wno-macro-redefined'] - # Transform the following macro names from __config_site into features - # that can be used in the tests. - # Ex. _LIBCPP_HAS_NO_THREADS -> libcpp-has-no-threads - translate = { - '_LIBCPP_HAS_NO_GLOBAL_FILESYSTEM_NAMESPACE', - '_LIBCPP_HAS_NO_MONOTONIC_CLOCK', - '_LIBCPP_HAS_NO_STDIN', - '_LIBCPP_HAS_NO_STDOUT', - '_LIBCPP_HAS_NO_THREAD_UNSAFE_C_FUNCTIONS', - '_LIBCPP_HAS_NO_THREADS', - '_LIBCPP_HAS_THREAD_API_EXTERNAL', - '_LIBCPP_HAS_THREAD_API_PTHREAD', - '_LIBCPP_NO_VCRUNTIME' - } - for m in translate.intersection(feature_macros.keys()): - self.config.available_features.add(m.lower()[1:].replace('_', '-')) - return feature_macros - - - def configure_compile_flags_exceptions(self): enable_exceptions = self.get_lit_bool('enable_exceptions', True) if not enable_exceptions: @@ -600,16 +544,6 @@ class Configuration(object): self.config.available_features.add('-fno-rtti') self.cxx.compile_flags += ['-fno-rtti', '-D_LIBCPP_NO_RTTI'] - def configure_compile_flags_abi_version(self): - abi_version = self.get_lit_conf('abi_version', '').strip() - abi_unstable = self.get_lit_bool('abi_unstable') - # Only add the ABI version when it is non-default. - # FIXME(EricWF): Get the ABI version from the "__config_site". - if abi_version and abi_version != '1': - self.cxx.compile_flags += ['-D_LIBCPP_ABI_VERSION=' + abi_version] - if abi_unstable: - self.cxx.compile_flags += ['-D_LIBCPP_ABI_UNSTABLE'] - def configure_link_flags(self): # Configure library path self.configure_link_flags_cxx_library_path() diff --git a/libcxx/utils/libcxx/test/dsl.py b/libcxx/utils/libcxx/test/dsl.py index 931a0c9..1110ded 100644 --- a/libcxx/utils/libcxx/test/dsl.py +++ b/libcxx/utils/libcxx/test/dsl.py @@ -197,9 +197,11 @@ class Feature(object): addTo = lambda subs, sub, flag: [(s, x + ' ' + flag) if s == sub else (s, x) for (s, x) in subs] if self._compileFlag: - config.substitutions = addTo(config.substitutions, '%{compile_flags}', self._compileFlag) + compileFlag = self._compileFlag(config) if callable(self._compileFlag) else self._compileFlag + config.substitutions = addTo(config.substitutions, '%{compile_flags}', compileFlag) if self._linkFlag: - config.substitutions = addTo(config.substitutions, '%{link_flags}', self._linkFlag) + linkFlag = self._linkFlag(config) if callable(self._linkFlag) else self._linkFlag + config.substitutions = addTo(config.substitutions, '%{link_flags}', linkFlag) name = self._name(config) if callable(self._name) else self._name config.available_features.add(name) diff --git a/libcxx/utils/libcxx/test/features.py b/libcxx/utils/libcxx/test/features.py index 5332d1e..a48bae8 100644 --- a/libcxx/utils/libcxx/test/features.py +++ b/libcxx/utils/libcxx/test/features.py @@ -13,6 +13,13 @@ _isClang = lambda cfg: '__clang__' in compilerMacros(cfg) and '__apple_buil _isAppleClang = lambda cfg: '__apple_build_version__' in compilerMacros(cfg) _isGCC = lambda cfg: '__GNUC__' in compilerMacros(cfg) and '__clang__' not in compilerMacros(cfg) +def _assert(condition, message): + """Function to use an assertion statement as an expression. + Use as `_assert(condition, message) and `. + """ + assert condition, message + return True + features = [ Feature(name='fcoroutines-ts', compileFlag='-fcoroutines-ts', when=lambda cfg: hasCompileFlag(cfg, '-fcoroutines-ts') and @@ -48,3 +55,43 @@ features = [ Feature(name=lambda cfg: 'gcc-{__GNUC__}.{__GNUC_MINOR__}'.format(**compilerMacros(cfg)), when=_isGCC), Feature(name=lambda cfg: 'gcc-{__GNUC__}.{__GNUC_MINOR__}.{__GNUC_PATCHLEVEL__}'.format(**compilerMacros(cfg)), when=_isGCC), ] + +# Deduce and add the test features that that are implied by the #defines in +# the <__config_site> header. +# +# For each macro of the form `_LIBCPP_XXX_YYY_ZZZ` defined below that +# is defined after including <__config_site>, add a Lit feature called +# `libcpp-xxx-yyy-zzz`. When a macro is defined to a specific value +# (e.g. `_LIBCPP_ABI_VERSION=2`), the feature is `libcpp-xxx-yyy-zzz=`. +macros = [ + '_LIBCPP_HAS_NO_GLOBAL_FILESYSTEM_NAMESPACE', + '_LIBCPP_HAS_NO_MONOTONIC_CLOCK', + '_LIBCPP_HAS_NO_STDIN', + '_LIBCPP_HAS_NO_STDOUT', + '_LIBCPP_HAS_NO_THREAD_UNSAFE_C_FUNCTIONS', + '_LIBCPP_HAS_NO_THREADS', + '_LIBCPP_HAS_THREAD_API_EXTERNAL', + '_LIBCPP_HAS_THREAD_API_PTHREAD', + '_LIBCPP_NO_VCRUNTIME', + '_LIBCPP_ABI_VERSION', + '_LIBCPP_ABI_UNSTABLE' +] +for macro in macros: + features += [ + Feature(name=lambda cfg, macro=macro: macro.lower()[1:].replace('_', '-') + ( + '={}'.format(compilerMacros(cfg)[macro]) if compilerMacros(cfg)[macro] else '' + ), + when=lambda cfg, macro=macro: + _assert('_LIBCPP_CONFIG_SITE' in compilerMacros(cfg), + "Trying to determine whether macro {} is defined, but it looks " + "like <__config_site> wasn't included".format(macro)) and + macro in compilerMacros(cfg), + + # FIXME: This is a hack that should be fixed using module maps. + # If modules are enabled then we have to lift all of the definitions + # in <__config_site> onto the command line. + compileFlag=lambda cfg: '-Wno-macro-redefined -D{}'.format(macro) + ( + '={}'.format(compilerMacros(cfg)[macro]) if compilerMacros(cfg)[macro] else '' + ) + ) + ] -- 2.7.4