1#===----------------------------------------------------------------------===## 2# 3# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4# See https://llvm.org/LICENSE.txt for license information. 5# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6# 7#===----------------------------------------------------------------------===## 8 9from libcxx.test.dsl import * 10import re 11import shutil 12import sys 13 14_isClang = lambda cfg: '__clang__' in compilerMacros(cfg) and '__apple_build_version__' not in compilerMacros(cfg) 15_isAppleClang = lambda cfg: '__apple_build_version__' in compilerMacros(cfg) 16_isGCC = lambda cfg: '__GNUC__' in compilerMacros(cfg) and '__clang__' not in compilerMacros(cfg) 17_isMSVC = lambda cfg: '_MSC_VER' in compilerMacros(cfg) 18_msvcVersion = lambda cfg: (int(compilerMacros(cfg)['_MSC_VER']) // 100, int(compilerMacros(cfg)['_MSC_VER']) % 100) 19 20DEFAULT_FEATURES = [ 21 Feature(name='fcoroutines-ts', 22 when=lambda cfg: hasCompileFlag(cfg, '-fcoroutines-ts') and 23 featureTestMacros(cfg, flags='-fcoroutines-ts').get('__cpp_coroutines', 0) >= 201703, 24 actions=[AddCompileFlag('-fcoroutines-ts')]), 25 26 Feature(name='thread-safety', 27 when=lambda cfg: hasCompileFlag(cfg, '-Werror=thread-safety'), 28 actions=[AddCompileFlag('-Werror=thread-safety')]), 29 30 Feature(name='diagnose-if-support', 31 when=lambda cfg: hasCompileFlag(cfg, '-Wuser-defined-warnings'), 32 actions=[AddCompileFlag('-Wuser-defined-warnings')]), 33 34 Feature(name='has-fblocks', when=lambda cfg: hasCompileFlag(cfg, '-fblocks')), 35 Feature(name='-fsized-deallocation', when=lambda cfg: hasCompileFlag(cfg, '-fsized-deallocation')), 36 Feature(name='-faligned-allocation', when=lambda cfg: hasCompileFlag(cfg, '-faligned-allocation')), 37 Feature(name='fdelayed-template-parsing', when=lambda cfg: hasCompileFlag(cfg, '-fdelayed-template-parsing')), 38 Feature(name='libcpp-no-if-constexpr', when=lambda cfg: '__cpp_if_constexpr' not in featureTestMacros(cfg)), 39 Feature(name='libcpp-no-structured-bindings', when=lambda cfg: '__cpp_structured_bindings' not in featureTestMacros(cfg)), 40 Feature(name='libcpp-no-deduction-guides', when=lambda cfg: featureTestMacros(cfg).get('__cpp_deduction_guides', 0) < 201611), 41 Feature(name='libcpp-no-concepts', when=lambda cfg: featureTestMacros(cfg).get('__cpp_concepts', 0) < 201907), 42 Feature(name='has-fobjc-arc', when=lambda cfg: hasCompileFlag(cfg, '-xobjective-c++ -fobjc-arc') and 43 sys.platform.lower().strip() == 'darwin'), # TODO: this doesn't handle cross-compiling to Apple platforms. 44 Feature(name='objective-c++', when=lambda cfg: hasCompileFlag(cfg, '-xobjective-c++ -fobjc-arc')), 45 46 # Note: We use a custom modules cache path to make sure that we don't reuse 47 # the default one, which can be shared across builds. This is important 48 # because we define macros in headers files, and a change in these macros 49 # doesn't seem to invalidate modules cache entries, which means we could 50 # build against now-invalid cached headers from a previous build. 51 Feature(name='modules-support', 52 when=lambda cfg: hasCompileFlag(cfg, '-fmodules'), 53 actions=lambda cfg: [AddCompileFlag('-fmodules-cache-path=%t/ModuleCache')]), 54 55 Feature(name='non-lockfree-atomics', 56 when=lambda cfg: sourceBuilds(cfg, """ 57 #include <atomic> 58 struct Large { int storage[100]; }; 59 std::atomic<Large> x; 60 int main(int, char**) { (void)x.load(); return 0; } 61 """)), 62 # TODO: Remove this feature once compiler-rt includes __atomic_is_lockfree() 63 # on all supported platforms. 64 Feature(name='is-lockfree-runtime-function', 65 when=lambda cfg: sourceBuilds(cfg, """ 66 #include <atomic> 67 struct Large { int storage[100]; }; 68 std::atomic<Large> x; 69 int main(int, char**) { return x.is_lock_free(); } 70 """)), 71 72 Feature(name='apple-clang', when=_isAppleClang), 73 Feature(name=lambda cfg: 'apple-clang-{__clang_major__}'.format(**compilerMacros(cfg)), when=_isAppleClang), 74 Feature(name=lambda cfg: 'apple-clang-{__clang_major__}.{__clang_minor__}'.format(**compilerMacros(cfg)), when=_isAppleClang), 75 Feature(name=lambda cfg: 'apple-clang-{__clang_major__}.{__clang_minor__}.{__clang_patchlevel__}'.format(**compilerMacros(cfg)), when=_isAppleClang), 76 77 Feature(name='clang', when=_isClang), 78 Feature(name=lambda cfg: 'clang-{__clang_major__}'.format(**compilerMacros(cfg)), when=_isClang), 79 Feature(name=lambda cfg: 'clang-{__clang_major__}.{__clang_minor__}'.format(**compilerMacros(cfg)), when=_isClang), 80 Feature(name=lambda cfg: 'clang-{__clang_major__}.{__clang_minor__}.{__clang_patchlevel__}'.format(**compilerMacros(cfg)), when=_isClang), 81 82 Feature(name='gcc', when=_isGCC), 83 Feature(name=lambda cfg: 'gcc-{__GNUC__}'.format(**compilerMacros(cfg)), when=_isGCC), 84 Feature(name=lambda cfg: 'gcc-{__GNUC__}.{__GNUC_MINOR__}'.format(**compilerMacros(cfg)), when=_isGCC), 85 Feature(name=lambda cfg: 'gcc-{__GNUC__}.{__GNUC_MINOR__}.{__GNUC_PATCHLEVEL__}'.format(**compilerMacros(cfg)), when=_isGCC), 86 87 Feature(name='msvc', when=_isMSVC), 88 Feature(name=lambda cfg: 'msvc-{}'.format(*_msvcVersion(cfg)), when=_isMSVC), 89 Feature(name=lambda cfg: 'msvc-{}.{}'.format(*_msvcVersion(cfg)), when=_isMSVC), 90] 91 92# Deduce and add the test features that that are implied by the #defines in 93# the <__config_site> header. 94# 95# For each macro of the form `_LIBCPP_XXX_YYY_ZZZ` defined below that 96# is defined after including <__config_site>, add a Lit feature called 97# `libcpp-xxx-yyy-zzz`. When a macro is defined to a specific value 98# (e.g. `_LIBCPP_ABI_VERSION=2`), the feature is `libcpp-xxx-yyy-zzz=<value>`. 99macros = { 100 '_LIBCPP_HAS_NO_GLOBAL_FILESYSTEM_NAMESPACE': 'libcpp-has-no-global-filesystem-namespace', 101 '_LIBCPP_HAS_NO_MONOTONIC_CLOCK': 'libcpp-has-no-monotonic-clock', 102 '_LIBCPP_HAS_NO_STDIN': 'libcpp-has-no-stdin', 103 '_LIBCPP_HAS_NO_STDOUT': 'libcpp-has-no-stdout', 104 '_LIBCPP_HAS_NO_THREAD_UNSAFE_C_FUNCTIONS': 'libcpp-has-no-thread-unsafe-c-functions', 105 '_LIBCPP_HAS_NO_THREADS': 'libcpp-has-no-threads', 106 '_LIBCPP_HAS_THREAD_API_EXTERNAL': 'libcpp-has-thread-api-external', 107 '_LIBCPP_HAS_THREAD_API_PTHREAD': 'libcpp-has-thread-api-pthread', 108 '_LIBCPP_NO_VCRUNTIME': 'libcpp-no-vcruntime', 109 '_LIBCPP_ABI_VERSION': 'libcpp-abi-version', 110 '_LIBCPP_ABI_UNSTABLE': 'libcpp-abi-unstable', 111 '_LIBCPP_HAS_NO_FILESYSTEM_LIBRARY': 'libcpp-has-no-filesystem-library', 112 '_LIBCPP_HAS_NO_RANDOM_DEVICE': 'libcpp-has-no-random-device', 113 '_LIBCPP_HAS_NO_LOCALIZATION': 'libcpp-has-no-localization', 114} 115for macro, feature in macros.items(): 116 DEFAULT_FEATURES += [ 117 Feature(name=lambda cfg, m=macro, f=feature: f + ( 118 '={}'.format(compilerMacros(cfg)[m]) if compilerMacros(cfg)[m] else '' 119 ), 120 when=lambda cfg, m=macro: m in compilerMacros(cfg), 121 122 # FIXME: This is a hack that should be fixed using module maps. 123 # If modules are enabled then we have to lift all of the definitions 124 # in <__config_site> onto the command line. 125 actions=lambda cfg, m=macro: [ 126 AddCompileFlag('-Wno-macro-redefined -D{}'.format(m) + ( 127 '={}'.format(compilerMacros(cfg)[m]) if compilerMacros(cfg)[m] else '' 128 )) 129 ] 130 ) 131 ] 132 133 134# Mapping from canonical locale names (used in the tests) to possible locale 135# names on various systems. Each locale is considered supported if any of the 136# alternative names is supported. 137locales = { 138 'en_US.UTF-8': ['en_US.UTF-8', 'en_US.utf8', 'English_United States.1252'], 139 'fr_FR.UTF-8': ['fr_FR.UTF-8', 'fr_FR.utf8', 'French_France.1252'], 140 'ru_RU.UTF-8': ['ru_RU.UTF-8', 'ru_RU.utf8', 'Russian_Russia.1251'], 141 'zh_CN.UTF-8': ['zh_CN.UTF-8', 'zh_CN.utf8', 'Chinese_China.936'], 142 'fr_CA.ISO8859-1': ['fr_CA.ISO8859-1', 'French_Canada.1252'], 143 'cs_CZ.ISO8859-2': ['cs_CZ.ISO8859-2', 'Czech_Czech Republic.1250'] 144} 145for locale, alts in locales.items(): 146 # Note: Using alts directly in the lambda body here will bind it to the value at the 147 # end of the loop. Assigning it to a default argument works around this issue. 148 DEFAULT_FEATURES.append(Feature(name='locale.{}'.format(locale), 149 when=lambda cfg, alts=alts: hasAnyLocale(cfg, alts))) 150 151 152# Add features representing the platform name: darwin, linux, windows, etc... 153DEFAULT_FEATURES += [ 154 Feature(name='darwin', when=lambda cfg: '__APPLE__' in compilerMacros(cfg)), 155 Feature(name='windows', when=lambda cfg: '_WIN32' in compilerMacros(cfg)), 156 Feature(name='windows-dll', when=lambda cfg: '_WIN32' in compilerMacros(cfg) and not '_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS' in compilerMacros(cfg)), 157 Feature(name='linux', when=lambda cfg: '__linux__' in compilerMacros(cfg)), 158 Feature(name='netbsd', when=lambda cfg: '__NetBSD__' in compilerMacros(cfg)), 159 Feature(name='freebsd', when=lambda cfg: '__FreeBSD__' in compilerMacros(cfg)) 160] 161 162 163# Detect whether GDB is on the system, and if so add a substitution to access it. 164DEFAULT_FEATURES += [ 165 Feature(name='host-has-gdb', 166 when=lambda cfg: shutil.which('gdb') is not None, 167 actions=[AddSubstitution('%{gdb}', lambda cfg: shutil.which('gdb'))] 168 ) 169] 170