1# -*- Python -*- 2 3import os 4import platform 5import shlex 6import subprocess 7 8import lit.formats 9 10# Choose between lit's internal shell pipeline runner and a real shell. If 11# LIT_USE_INTERNAL_SHELL is in the environment, we use that as an override. 12use_lit_shell = os.environ.get("LIT_USE_INTERNAL_SHELL") 13if use_lit_shell: 14 # 0 is external, "" is default, and everything else is internal. 15 execute_external = use_lit_shell == "0" 16else: 17 # Otherwise we default to internal on Windows and external elsewhere, as 18 # bash on Windows is usually very slow. 19 execute_external = not sys.platform in ["win32"] 20 21 22def get_required_attr(config, attr_name): 23 attr_value = getattr(config, attr_name, None) 24 if attr_value is None: 25 lit_config.fatal( 26 "No attribute %r in test configuration! You may need to run " 27 "tests from your build directory or add this attribute " 28 "to lit.site.cfg.py " % attr_name 29 ) 30 return attr_value 31 32 33def get_library_path(file): 34 cmd = subprocess.Popen( 35 [config.clang.strip(), "-print-file-name=%s" % file] 36 + shlex.split(config.target_cflags), 37 stdout=subprocess.PIPE, 38 env=config.environment, 39 universal_newlines=True, 40 ) 41 if not cmd.stdout: 42 lit_config.fatal("Couldn't find the library path for '%s'" % file) 43 dir = cmd.stdout.read().strip() 44 if sys.platform in ["win32"] and execute_external: 45 # Don't pass dosish path separator to msys bash.exe. 46 dir = dir.replace("\\", "/") 47 return dir 48 49 50def get_libgcc_file_name(): 51 cmd = subprocess.Popen( 52 [config.clang.strip(), "-print-libgcc-file-name"] 53 + shlex.split(config.target_cflags), 54 stdout=subprocess.PIPE, 55 env=config.environment, 56 universal_newlines=True, 57 ) 58 if not cmd.stdout: 59 lit_config.fatal("Couldn't find the library path for '%s'" % file) 60 dir = cmd.stdout.read().strip() 61 if sys.platform in ["win32"] and execute_external: 62 # Don't pass dosish path separator to msys bash.exe. 63 dir = dir.replace("\\", "/") 64 return dir 65 66 67# Setup config name. 68config.name = "Builtins" + config.name_suffix 69 70# Platform-specific default Builtins_OPTIONS for lit tests. 71default_builtins_opts = "" 72 73# Setup source root. 74config.test_source_root = os.path.dirname(__file__) 75 76# Path to the static library 77is_msvc = get_required_attr(config, "is_msvc") 78if is_msvc: 79 base_lib = os.path.join( 80 config.compiler_rt_libdir, "clang_rt.builtins%s.lib " % config.target_suffix 81 ) 82 config.substitutions.append(("%librt ", base_lib)) 83elif config.host_os == "Darwin": 84 base_lib = os.path.join(config.compiler_rt_libdir, "libclang_rt.osx.a ") 85 config.substitutions.append(("%librt ", base_lib + " -lSystem ")) 86elif config.host_os == "Windows": 87 base_lib = os.path.join( 88 config.compiler_rt_libdir, "libclang_rt.builtins%s.a" % config.target_suffix 89 ) 90 if sys.platform in ["win32"] and execute_external: 91 # Don't pass dosish path separator to msys bash.exe. 92 base_lib = base_lib.replace("\\", "/") 93 config.substitutions.append( 94 ( 95 "%librt ", 96 base_lib 97 + " -lmingw32 -lmoldname -lmingwex -lmsvcrt -ladvapi32 -lshell32 -luser32 -lkernel32 ", 98 ) 99 ) 100else: 101 base_lib = os.path.join( 102 config.compiler_rt_libdir, "libclang_rt.builtins%s.a" % config.target_suffix 103 ) 104 if sys.platform in ["win32"] and execute_external: 105 # Don't pass dosish path separator to msys bash.exe. 106 base_lib = base_lib.replace("\\", "/") 107 if config.host_os == "Haiku": 108 config.substitutions.append(("%librt ", base_lib + " -lroot ")) 109 else: 110 config.substitutions.append(("%librt ", base_lib + " -lc -lm ")) 111 112builtins_build_crt = get_required_attr(config, "builtins_build_crt") 113if builtins_build_crt: 114 base_obj = os.path.join( 115 config.compiler_rt_libdir, "clang_rt.%%s%s.o" % config.target_suffix 116 ) 117 if sys.platform in ["win32"] and execute_external: 118 # Don't pass dosish path separator to msys bash.exe. 119 base_obj = base_obj.replace("\\", "/") 120 121 config.substitutions.append(("%crtbegin", base_obj % "crtbegin")) 122 config.substitutions.append(("%crtend", base_obj % "crtend")) 123 124 config.substitutions.append(("%crt1", get_library_path("crt1.o"))) 125 config.substitutions.append(("%crti", get_library_path("crti.o"))) 126 config.substitutions.append(("%crtn", get_library_path("crtn.o"))) 127 128 config.substitutions.append(("%libgcc", get_libgcc_file_name())) 129 config.substitutions.append( 130 ("%libc", "-lroot" if sys.platform.startswith("haiku") else "-lc") 131 ) 132 133 config.substitutions.append( 134 ("%libstdcxx", "-l" + config.sanitizer_cxx_lib.lstrip("lib")) 135 ) 136 137 config.available_features.add("crt") 138 139builtins_source_dir = os.path.join( 140 get_required_attr(config, "compiler_rt_src_root"), "lib", "builtins" 141) 142if sys.platform in ["win32"] and execute_external: 143 # Don't pass dosish path separator to msys bash.exe. 144 builtins_source_dir = builtins_source_dir.replace("\\", "/") 145builtins_lit_source_dir = get_required_attr(config, "builtins_lit_source_dir") 146 147extra_link_flags = ["-nodefaultlibs"] 148 149target_cflags = [get_required_attr(config, "target_cflags")] 150target_cflags += ["-fno-builtin", "-I", builtins_source_dir] 151target_cflags += extra_link_flags 152target_cxxflags = config.cxx_mode_flags + target_cflags 153clang_builtins_static_cflags = [""] + config.debug_info_flags + target_cflags 154clang_builtins_static_cxxflags = config.cxx_mode_flags + clang_builtins_static_cflags 155 156clang_builtins_cflags = clang_builtins_static_cflags 157clang_builtins_cxxflags = clang_builtins_static_cxxflags 158 159# FIXME: Right now we don't compile the C99 complex builtins when using 160# clang-cl. Fix that. 161if not is_msvc: 162 config.available_features.add("c99-complex") 163 164builtins_is_msvc = get_required_attr(config, "builtins_is_msvc") 165if not builtins_is_msvc: 166 config.available_features.add("int128") 167 168clang_wrapper = "" 169 170 171def build_invocation(compile_flags): 172 return " " + " ".join([clang_wrapper, config.clang] + compile_flags) + " " 173 174 175config.substitutions.append(("%clang ", build_invocation(target_cflags))) 176config.substitutions.append(("%clangxx ", build_invocation(target_cxxflags))) 177config.substitutions.append( 178 ("%clang_builtins ", build_invocation(clang_builtins_cflags)) 179) 180config.substitutions.append( 181 ("%clangxx_builtins ", build_invocation(clang_builtins_cxxflags)) 182) 183 184# Default test suffixes. 185config.suffixes = [".c", ".cpp"] 186 187if not config.emulator: 188 config.available_features.add("native-run") 189 190# Add features for available sources 191builtins_source_features = config.builtins_lit_source_features.split(";") 192# Sanity checks 193if not builtins_source_features: 194 lit_config.fatal("builtins_source_features cannot be empty") 195builtins_source_features_set = set() 196builtins_source_feature_duplicates = [] 197for builtin_source_feature in builtins_source_features: 198 if len(builtin_source_feature) == 0: 199 lit_config.fatal("builtins_source_feature cannot contain empty features") 200 if builtin_source_feature not in builtins_source_features_set: 201 builtins_source_features_set.add(builtin_source_feature) 202 else: 203 builtins_source_feature_duplicates.append(builtin_source_feature) 204 205if len(builtins_source_feature_duplicates) > 0: 206 lit_config.fatal( 207 "builtins_source_features contains duplicates: {}".format( 208 builtins_source_feature_duplicates 209 ) 210 ) 211config.available_features.update(builtins_source_features) 212