1import os 2import platform 3import subprocess 4import sys 5import itertools 6 7import lldbsuite.test.lldbtest as lldbtest 8import lldbsuite.test.lldbutil as lldbutil 9from lldbsuite.test import configuration 10from lldbsuite.test_event import build_exception 11 12 13class Builder: 14 def getArchitecture(self): 15 """Returns the architecture in effect the test suite is running with.""" 16 return configuration.arch if configuration.arch else "" 17 18 def getCompiler(self): 19 """Returns the compiler in effect the test suite is running with.""" 20 compiler = configuration.compiler if configuration.compiler else "clang" 21 compiler = lldbutil.which(compiler) 22 return os.path.abspath(compiler) 23 24 def getTriple(self, arch): 25 """Returns the triple for the given architecture or None.""" 26 return None 27 28 def getExtraMakeArgs(self): 29 """ 30 Helper function to return extra argumentsfor the make system. This 31 method is meant to be overridden by platform specific builders. 32 """ 33 return [] 34 35 def getArchCFlags(self, architecture): 36 """Returns the ARCH_CFLAGS for the make system.""" 37 return [] 38 39 def getMake(self, test_subdir, test_name): 40 """Returns the invocation for GNU make. 41 The first argument is a tuple of the relative path to the testcase 42 and its filename stem.""" 43 if platform.system() == "FreeBSD" or platform.system() == "NetBSD": 44 make = "gmake" 45 else: 46 make = "make" 47 48 # Construct the base make invocation. 49 lldb_test = os.environ["LLDB_TEST"] 50 if not ( 51 lldb_test 52 and configuration.test_build_dir 53 and test_subdir 54 and test_name 55 and (not os.path.isabs(test_subdir)) 56 ): 57 raise Exception("Could not derive test directories") 58 build_dir = os.path.join(configuration.test_build_dir, test_subdir, test_name) 59 src_dir = os.path.join(configuration.test_src_root, test_subdir) 60 # This is a bit of a hack to make inline testcases work. 61 makefile = os.path.join(src_dir, "Makefile") 62 if not os.path.isfile(makefile): 63 makefile = os.path.join(build_dir, "Makefile") 64 return [ 65 make, 66 "VPATH=" + src_dir, 67 "-C", 68 build_dir, 69 "-I", 70 src_dir, 71 "-I", 72 os.path.join(lldb_test, "make"), 73 "-f", 74 makefile, 75 ] 76 77 def getCmdLine(self, d): 78 """ 79 Helper function to return a command line argument string used for the 80 make system. 81 """ 82 83 # If d is None or an empty mapping, just return an empty list. 84 if not d: 85 return [] 86 87 def setOrAppendVariable(k, v): 88 append_vars = ["CFLAGS", "CFLAGS_EXTRAS", "LD_EXTRAS"] 89 if k in append_vars and k in os.environ: 90 v = os.environ[k] + " " + v 91 return "%s=%s" % (k, v) 92 93 cmdline = [setOrAppendVariable(k, v) for k, v in list(d.items())] 94 95 return cmdline 96 97 def getArchSpec(self, architecture): 98 """ 99 Helper function to return the key-value string to specify the architecture 100 used for the make system. 101 """ 102 return ["ARCH=" + architecture] if architecture else [] 103 104 def getCCSpec(self, compiler): 105 """ 106 Helper function to return the key-value string to specify the compiler 107 used for the make system. 108 """ 109 cc = compiler if compiler else None 110 if not cc and configuration.compiler: 111 cc = configuration.compiler 112 if cc: 113 return ['CC="%s"' % cc] 114 return [] 115 116 def getSDKRootSpec(self): 117 """ 118 Helper function to return the key-value string to specify the SDK root 119 used for the make system. 120 """ 121 if configuration.sdkroot: 122 return ["SDKROOT={}".format(configuration.sdkroot)] 123 return [] 124 125 def getModuleCacheSpec(self): 126 """ 127 Helper function to return the key-value string to specify the clang 128 module cache used for the make system. 129 """ 130 if configuration.clang_module_cache_dir: 131 return [ 132 "CLANG_MODULE_CACHE_DIR={}".format(configuration.clang_module_cache_dir) 133 ] 134 return [] 135 136 def getLibCxxArgs(self): 137 if configuration.libcxx_include_dir and configuration.libcxx_library_dir: 138 libcpp_args = [ 139 "LIBCPP_INCLUDE_DIR={}".format(configuration.libcxx_include_dir), 140 "LIBCPP_LIBRARY_DIR={}".format(configuration.libcxx_library_dir), 141 ] 142 if configuration.libcxx_include_target_dir: 143 libcpp_args.append( 144 "LIBCPP_INCLUDE_TARGET_DIR={}".format( 145 configuration.libcxx_include_target_dir 146 ) 147 ) 148 return libcpp_args 149 return [] 150 151 def getLLDBObjRoot(self): 152 return ["LLDB_OBJ_ROOT={}".format(configuration.lldb_obj_root)] 153 154 def _getDebugInfoArgs(self, debug_info): 155 if debug_info is None: 156 return [] 157 if debug_info == "dwarf": 158 return ["MAKE_DSYM=NO"] 159 if debug_info == "dwo": 160 return ["MAKE_DSYM=NO", "MAKE_DWO=YES"] 161 if debug_info == "gmodules": 162 return ["MAKE_DSYM=NO", "MAKE_GMODULES=YES"] 163 return None 164 165 def getBuildCommand( 166 self, 167 debug_info, 168 architecture=None, 169 compiler=None, 170 dictionary=None, 171 testdir=None, 172 testname=None, 173 make_targets=None, 174 ): 175 debug_info_args = self._getDebugInfoArgs(debug_info) 176 if debug_info_args is None: 177 return None 178 if make_targets is None: 179 make_targets = ["all"] 180 command_parts = [ 181 self.getMake(testdir, testname), 182 debug_info_args, 183 make_targets, 184 self.getArchCFlags(architecture), 185 self.getArchSpec(architecture), 186 self.getCCSpec(compiler), 187 self.getExtraMakeArgs(), 188 self.getSDKRootSpec(), 189 self.getModuleCacheSpec(), 190 self.getLibCxxArgs(), 191 self.getLLDBObjRoot(), 192 self.getCmdLine(dictionary), 193 ] 194 command = list(itertools.chain(*command_parts)) 195 196 return command 197 198 def cleanup(self, dictionary=None): 199 """Perform a platform-specific cleanup after the test.""" 200 return True 201