diff --git a/libcxx/test/libcxx/selftest/dsl/dsl.sh.py b/libcxx/test/libcxx/selftest/dsl/dsl.sh.py index ff4ac2147bf68b..7086c69cdd1167 100644 --- a/libcxx/test/libcxx/selftest/dsl/dsl.sh.py +++ b/libcxx/test/libcxx/selftest/dsl/dsl.sh.py @@ -244,21 +244,29 @@ def test_trivial(self): self.assertIn('name', self.config.available_features) def test_name_can_be_a_callable(self): - feature = dsl.Feature(name=lambda cfg: (self.assertIs(self.config, cfg), 'name')[1]) + feature = dsl.Feature(name=lambda cfg: 'name') assert feature.isSupported(self.config) + self.assertEqual('name', feature.getName(self.config)) feature.enableIn(self.config) self.assertIn('name', self.config.available_features) def test_name_is_not_a_string_1(self): feature = dsl.Feature(name=None) assert feature.isSupported(self.config) + self.assertRaises(ValueError, lambda: feature.getName(self.config)) self.assertRaises(ValueError, lambda: feature.enableIn(self.config)) def test_name_is_not_a_string_2(self): feature = dsl.Feature(name=lambda cfg: None) assert feature.isSupported(self.config) + self.assertRaises(ValueError, lambda: feature.getName(self.config)) self.assertRaises(ValueError, lambda: feature.enableIn(self.config)) + def test_getName_when_unsupported(self): + feature = dsl.Feature(name='name', when=lambda _: False) + assert not feature.isSupported(self.config) + self.assertRaises(AssertionError, lambda: feature.getName(self.config)) + def test_adding_compile_flag(self): feature = dsl.Feature(name='name', compileFlag='-foo') origLinkFlags = copy.deepcopy(self.getSubstitution('%{link_flags}')) diff --git a/libcxx/utils/libcxx/test/config.py b/libcxx/utils/libcxx/test/config.py index 50973e3fe47a0c..985dc808cb559c 100644 --- a/libcxx/utils/libcxx/test/config.py +++ b/libcxx/utils/libcxx/test/config.py @@ -20,6 +20,7 @@ from libcxx.test.target_info import make_target_info import libcxx.util import libcxx.test.features +import libcxx.test.newconfig import libcxx.test.params def loadSiteConfig(lit_config, config, param_name, env_name): @@ -118,8 +119,8 @@ def make_static_lib_name(self, name): return 'lib' + name + '.a' def configure(self): - self.configure_target_info() - self.configure_executor() + self.target_info = make_target_info(self) + self.executor = self.get_lit_conf('executor') self.configure_cxx() self.configure_triple() self.configure_deployment() @@ -139,35 +140,20 @@ def configure(self): self.configure_modules() self.configure_substitutions() self.configure_features() - self.configure_new_params() - self.configure_new_features() - def configure_new_features(self): - supportedFeatures = [f for f in libcxx.test.features.features if f.isSupported(self.config)] - for feature in supportedFeatures: - feature.enableIn(self.config) - - def configure_new_params(self): - for param in libcxx.test.params.parameters: - feature = param.getFeature(self.config, self.lit_config.params) - if feature: - feature.enableIn(self.config) + libcxx.test.newconfig.configure( + libcxx.test.params.DEFAULT_PARAMETERS, + libcxx.test.features.DEFAULT_FEATURES, + self.config, + self.lit_config + ) def print_config_info(self): - # Print the final compile and link flags. - self.lit_config.note('Using compiler: %s' % self.cxx.path) - self.lit_config.note('Using flags: %s' % self.cxx.flags) if self.cxx.use_modules: self.lit_config.note('Using modules flags: %s' % self.cxx.modules_flags) - self.lit_config.note('Using compile flags: %s' - % self.cxx.compile_flags) if len(self.cxx.warning_flags): self.lit_config.note('Using warnings: %s' % self.cxx.warning_flags) - self.lit_config.note('Using link flags: %s' % self.cxx.link_flags) - # Print as list to prevent "set([...])" from being printed. - self.lit_config.note('Using available_features: %s' % - list(sorted(self.config.available_features))) show_env_vars = {} for k,v in self.exec_env.items(): if k not in os.environ or os.environ[k] != v: @@ -185,13 +171,6 @@ def get_test_format(self): self.executor, exec_env=self.exec_env) - def configure_executor(self): - self.executor = self.get_lit_conf('executor') - self.lit_config.note("Using executor: {}".format(self.executor)) - - def configure_target_info(self): - self.target_info = make_target_info(self) - def configure_cxx(self): # Gather various compiler parameters. cxx = self.get_lit_conf('cxx_under_test') @@ -730,11 +709,8 @@ def configure_deployment(self): arch = self.get_lit_conf('arch') if not arch: arch = self.cxx.getTriple().split('-', 1)[0] - self.lit_config.note("inferred arch as: %r" % arch) - inferred_platform, name, version = self.target_info.get_platform() - if inferred_platform: - self.lit_config.note("inferred platform as: %r" % (name + version)) + _, name, version = self.target_info.get_platform() self.config.deployment = (arch, name, version) # Set the target triple for use by lit. diff --git a/libcxx/utils/libcxx/test/dsl.py b/libcxx/utils/libcxx/test/dsl.py index e0e09e6bcac47a..2c54921844b2a4 100644 --- a/libcxx/utils/libcxx/test/dsl.py +++ b/libcxx/utils/libcxx/test/dsl.py @@ -227,6 +227,19 @@ def isSupported(self, config): """ return self._isSupported(config) + def getName(self, config): + """ + Return the name of the feature. + + It is an error to call `f.getName(cfg)` if the feature `f` is not supported. + """ + assert self.isSupported(config), \ + "Trying to get the name of a feature that is not supported in the given configuration" + name = self._name(config) if callable(self._name) else self._name + if not isinstance(name, str): + raise ValueError("Feature did not resolve to a name that's a string, got {}".format(name)) + return name + def enableIn(self, config): """ Enable a feature in a TestingConfig. @@ -249,11 +262,7 @@ def enableIn(self, config): if 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 - if not isinstance(name, str): - raise ValueError("Feature did not resolve to a name that's a string, got {}".format(name)) - config.available_features.add(name) + config.available_features.add(self.getName(config)) def _str_to_bool(s): diff --git a/libcxx/utils/libcxx/test/features.py b/libcxx/utils/libcxx/test/features.py index f3d8e782be8e19..6a16ca851d3f99 100644 --- a/libcxx/utils/libcxx/test/features.py +++ b/libcxx/utils/libcxx/test/features.py @@ -13,7 +13,7 @@ _isAppleClang = lambda cfg: '__apple_build_version__' in compilerMacros(cfg) _isGCC = lambda cfg: '__GNUC__' in compilerMacros(cfg) and '__clang__' not in compilerMacros(cfg) -features = [ +DEFAULT_FEATURES = [ Feature(name='fcoroutines-ts', compileFlag='-fcoroutines-ts', when=lambda cfg: hasCompileFlag(cfg, '-fcoroutines-ts') and featureTestMacros(cfg, flags='-fcoroutines-ts').get('__cpp_coroutines', 0) >= 201703), @@ -76,7 +76,7 @@ '_LIBCPP_ABI_UNSTABLE': 'libcpp-abi-unstable' } for macro, feature in macros.items(): - features += [ + DEFAULT_FEATURES += [ Feature(name=lambda cfg, m=macro, f=feature: f + ( '={}'.format(compilerMacros(cfg)[m]) if compilerMacros(cfg)[m] else '' ), @@ -104,14 +104,14 @@ 'cs_CZ.ISO8859-2': ['cs_CZ.ISO8859-2', 'Czech_Czech Republic.1250'] } for locale, alts in locales.items(): - features += [ + DEFAULT_FEATURES += [ Feature(name='locale.{}'.format(locale), when=lambda cfg: any(hasLocale(cfg, alt) for alt in alts)) ] # Add features representing the platform name: darwin, linux, windows, etc... -features += [ +DEFAULT_FEATURES += [ Feature(name='darwin', when=lambda cfg: '__APPLE__' in compilerMacros(cfg)), Feature(name='windows', when=lambda cfg: '_WIN32' in compilerMacros(cfg)), Feature(name='linux', when=lambda cfg: '__linux__' in compilerMacros(cfg)), diff --git a/libcxx/utils/libcxx/test/newconfig.py b/libcxx/utils/libcxx/test/newconfig.py new file mode 100644 index 00000000000000..8996484ba20ba0 --- /dev/null +++ b/libcxx/utils/libcxx/test/newconfig.py @@ -0,0 +1,36 @@ +#===----------------------------------------------------------------------===## +# +# 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 +# +#===----------------------------------------------------------------------===## + +def _getSubstitution(substitution, config): + for (orig, replacement) in config.substitutions: + if orig == substitution: + return replacement + raise ValueError('Substitution {} is not in the config.'.format(substitution)) + +def configure(parameters, features, config, lit_config): + # Apply parameters to the configuration first, since parameters are things + # that we request explicitly and which might influence what features are + # implicitly made available next. + for param in parameters: + feature = param.getFeature(config, lit_config.params) + if feature: + feature.enableIn(config) + lit_config.note("Enabling Lit feature '{}' as a result of parameter '{}'".format(feature.getName(config), param.name)) + + # Then, apply the automatically-detected features. + printFeatures = [] + for feature in features: + if feature.isSupported(config): + feature.enableIn(config) + printFeatures.append(feature.getName(config)) + printFeatures = ["'{}'".format(f) for f in sorted(printFeatures)] + lit_config.note("Enabling implicitly detected Lit features {}".format(', '.join(printFeatures))) + + # Print the basic substitutions + for sub in ('%{cxx}', '%{flags}', '%{compile_flags}', '%{link_flags}', '%{exec}'): + lit_config.note("Using {} substitution: '{}'".format(sub, _getSubstitution(sub, config))) diff --git a/libcxx/utils/libcxx/test/params.py b/libcxx/utils/libcxx/test/params.py index f541ed6bf3cf24..a9431ec073f8d6 100644 --- a/libcxx/utils/libcxx/test/params.py +++ b/libcxx/utils/libcxx/test/params.py @@ -10,7 +10,7 @@ _allStandards = ['c++98', 'c++03', 'c++11', 'c++14', 'c++17', 'c++2a'] -parameters = [ +DEFAULT_PARAMETERS = [ # Core parameters of the test suite Parameter(name='std', choices=_allStandards, type=str, help="The version of the standard to compile the test suite with.",