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 9import importlib 10import lit.util 11import os 12import platform 13import re 14import subprocess 15import sys 16 17from libcxx.util import executeCommand 18 19class DefaultTargetInfo(object): 20 def __init__(self, full_config): 21 self.full_config = full_config 22 self.executor = None 23 24 def is_windows(self): 25 return False 26 27 def is_zos(self): 28 return False 29 30 def is_mingw(self): 31 return False 32 33 def add_cxx_flags(self, flags): pass 34 def add_cxx_compile_flags(self, flags): pass 35 def add_cxx_link_flags(self, flags): pass 36 def allow_cxxabi_link(self): return True 37 38 def add_path(self, dest_env, new_path): 39 if not new_path: 40 return 41 if 'PATH' not in dest_env: 42 dest_env['PATH'] = new_path 43 else: 44 split_char = ';' if self.is_windows() else ':' 45 dest_env['PATH'] = '%s%s%s' % (new_path, split_char, 46 dest_env['PATH']) 47 48 49class DarwinLocalTI(DefaultTargetInfo): 50 def __init__(self, full_config): 51 super(DarwinLocalTI, self).__init__(full_config) 52 53 def add_cxx_flags(self, flags): 54 out, err, exit_code = executeCommand(['xcrun', '--show-sdk-path']) 55 if exit_code != 0: 56 self.full_config.lit_config.warning("Could not determine macOS SDK path! stderr was " + err) 57 if exit_code == 0 and out: 58 sdk_path = out.strip() 59 self.full_config.lit_config.note('using SDKROOT: %r' % sdk_path) 60 assert isinstance(sdk_path, str) 61 flags += ["-isysroot", sdk_path] 62 63 def add_cxx_link_flags(self, flags): 64 flags += ['-lSystem'] 65 66 def allow_cxxabi_link(self): 67 # Don't link libc++abi explicitly on OS X because the symbols 68 # should be available in libc++ directly. 69 return False 70 71 72class FreeBSDLocalTI(DefaultTargetInfo): 73 def __init__(self, full_config): 74 super(FreeBSDLocalTI, self).__init__(full_config) 75 76 def add_cxx_link_flags(self, flags): 77 flags += ['-lc', '-lm', '-lpthread', '-lgcc_s', '-lcxxrt'] 78 79 80class NetBSDLocalTI(DefaultTargetInfo): 81 def __init__(self, full_config): 82 super(NetBSDLocalTI, self).__init__(full_config) 83 84 def add_cxx_link_flags(self, flags): 85 flags += ['-lc', '-lm', '-lpthread', '-lgcc_s', '-lc++abi', 86 '-lunwind'] 87 88 89class LinuxLocalTI(DefaultTargetInfo): 90 def __init__(self, full_config): 91 super(LinuxLocalTI, self).__init__(full_config) 92 93 def add_cxx_compile_flags(self, flags): 94 flags += ['-D__STDC_FORMAT_MACROS', 95 '-D__STDC_LIMIT_MACROS', 96 '-D__STDC_CONSTANT_MACROS'] 97 98 def add_cxx_link_flags(self, flags): 99 enable_threads = ('libcpp-has-no-threads' not in 100 self.full_config.config.available_features) 101 llvm_unwinder = self.full_config.get_lit_bool('llvm_unwinder', False) 102 shared_libcxx = self.full_config.get_lit_bool('enable_shared', True) 103 flags += ['-lm'] 104 if not llvm_unwinder: 105 flags += ['-lgcc_s', '-lgcc'] 106 if enable_threads: 107 flags += ['-lpthread'] 108 if not shared_libcxx: 109 flags += ['-lrt'] 110 flags += ['-lc'] 111 if llvm_unwinder: 112 flags += ['-lunwind', '-ldl'] 113 else: 114 flags += ['-lgcc_s'] 115 builtins_lib = self.full_config.get_lit_conf('builtins_library') 116 if builtins_lib: 117 flags += [builtins_lib] 118 else: 119 flags += ['-lgcc'] 120 has_libatomic = self.full_config.get_lit_bool('has_libatomic', False) 121 if has_libatomic: 122 flags += ['-latomic'] 123 san = self.full_config.get_lit_conf('use_sanitizer', '').strip() 124 if san: 125 # The libraries and their order are taken from the 126 # linkSanitizerRuntimeDeps function in 127 # clang/lib/Driver/Tools.cpp 128 flags += ['-lpthread', '-lrt', '-lm', '-ldl'] 129 130class LinuxRemoteTI(LinuxLocalTI): 131 def __init__(self, full_config): 132 super(LinuxRemoteTI, self).__init__(full_config) 133 134class WindowsLocalTI(DefaultTargetInfo): 135 def __init__(self, full_config): 136 super(WindowsLocalTI, self).__init__(full_config) 137 138 def is_windows(self): 139 return True 140 141class ZOSLocalTI(DefaultTargetInfo): 142 def __init__(self, full_config): 143 super(ZOSLocalTI, self).__init__(full_config) 144 145 def is_zos(self): 146 return True 147 148class MingwLocalTI(WindowsLocalTI): 149 def __init__(self, full_config): 150 super(MingwLocalTI, self).__init__(full_config) 151 152 def is_mingw(self): 153 return True 154 155def make_target_info(full_config): 156 default = "libcxx.test.target_info.LocalTI" 157 info_str = full_config.get_lit_conf('target_info', default) 158 if info_str != default: 159 mod_path, _, info = info_str.rpartition('.') 160 mod = importlib.import_module(mod_path) 161 target_info = getattr(mod, info)(full_config) 162 full_config.lit_config.note("inferred target_info as: %r" % info_str) 163 return target_info 164 target_system = platform.system() 165 if target_system == 'Darwin': return DarwinLocalTI(full_config) 166 if target_system == 'FreeBSD': return FreeBSDLocalTI(full_config) 167 if target_system == 'NetBSD': return NetBSDLocalTI(full_config) 168 if target_system == 'Linux': return LinuxLocalTI(full_config) 169 if target_system == 'Windows': return WindowsLocalTI(full_config) 170 if target_system == 'OS/390': return ZOSLocalTI(full_config) 171 return DefaultTargetInfo(full_config) 172