1b623f3c0SJonas Devlieghereimport os 244fc987eSVladislav Dzhidzhoevimport pathlib 3b623f3c0SJonas Devlieghereimport platform 4b623f3c0SJonas Devlieghereimport subprocess 5b623f3c0SJonas Devlieghereimport sys 6551d1188SPavel Labathimport itertools 7b623f3c0SJonas Devlieghere 8b623f3c0SJonas Devlieghereimport lldbsuite.test.lldbtest as lldbtest 944fc987eSVladislav Dzhidzhoevimport lldbsuite.test.lldbplatformutil as lldbplatformutil 10b623f3c0SJonas Devlieghereimport lldbsuite.test.lldbutil as lldbutil 11b623f3c0SJonas Devliegherefrom lldbsuite.test import configuration 12b623f3c0SJonas Devliegherefrom lldbsuite.test_event import build_exception 13*058ede06SVladislav Dzhidzhoevfrom lldbsuite.support import seven 14b623f3c0SJonas Devlieghere 15b623f3c0SJonas Devlieghere 16b623f3c0SJonas Devlieghereclass Builder: 17b623f3c0SJonas Devlieghere def getArchitecture(self): 18b623f3c0SJonas Devlieghere """Returns the architecture in effect the test suite is running with.""" 19b623f3c0SJonas Devlieghere return configuration.arch if configuration.arch else "" 20b623f3c0SJonas Devlieghere 21b623f3c0SJonas Devlieghere def getCompiler(self): 22b623f3c0SJonas Devlieghere """Returns the compiler in effect the test suite is running with.""" 23b623f3c0SJonas Devlieghere compiler = configuration.compiler if configuration.compiler else "clang" 24b623f3c0SJonas Devlieghere compiler = lldbutil.which(compiler) 25b623f3c0SJonas Devlieghere return os.path.abspath(compiler) 26b623f3c0SJonas Devlieghere 270f12cf7eSJonas Devlieghere def getTriple(self, arch): 280f12cf7eSJonas Devlieghere """Returns the triple for the given architecture or None.""" 290f12cf7eSJonas Devlieghere return None 300f12cf7eSJonas Devlieghere 31074c591aSJonas Devlieghere def getExtraMakeArgs(self): 32074c591aSJonas Devlieghere """ 33074c591aSJonas Devlieghere Helper function to return extra argumentsfor the make system. This 34074c591aSJonas Devlieghere method is meant to be overridden by platform specific builders. 35074c591aSJonas Devlieghere """ 36551d1188SPavel Labath return [] 37e5d08fcbSJonas Devlieghere 38e5d08fcbSJonas Devlieghere def getArchCFlags(self, architecture): 39e5d08fcbSJonas Devlieghere """Returns the ARCH_CFLAGS for the make system.""" 40551d1188SPavel Labath return [] 41074c591aSJonas Devlieghere 42b623f3c0SJonas Devlieghere def getMake(self, test_subdir, test_name): 43b623f3c0SJonas Devlieghere """Returns the invocation for GNU make. 44b623f3c0SJonas Devlieghere The first argument is a tuple of the relative path to the testcase 45b623f3c0SJonas Devlieghere and its filename stem.""" 46b623f3c0SJonas Devlieghere # Construct the base make invocation. 47b623f3c0SJonas Devlieghere lldb_test = os.environ["LLDB_TEST"] 482238dcc3SJonas Devlieghere if not ( 492238dcc3SJonas Devlieghere lldb_test 502238dcc3SJonas Devlieghere and configuration.test_build_dir 512238dcc3SJonas Devlieghere and test_subdir 522238dcc3SJonas Devlieghere and test_name 532238dcc3SJonas Devlieghere and (not os.path.isabs(test_subdir)) 542238dcc3SJonas Devlieghere ): 55b623f3c0SJonas Devlieghere raise Exception("Could not derive test directories") 562238dcc3SJonas Devlieghere build_dir = os.path.join(configuration.test_build_dir, test_subdir, test_name) 57b623f3c0SJonas Devlieghere src_dir = os.path.join(configuration.test_src_root, test_subdir) 58b623f3c0SJonas Devlieghere # This is a bit of a hack to make inline testcases work. 59b623f3c0SJonas Devlieghere makefile = os.path.join(src_dir, "Makefile") 60b623f3c0SJonas Devlieghere if not os.path.isfile(makefile): 61b623f3c0SJonas Devlieghere makefile = os.path.join(build_dir, "Makefile") 62b623f3c0SJonas Devlieghere return [ 636b7b05b5SVladislav Dzhidzhoev configuration.make_path, 642238dcc3SJonas Devlieghere "VPATH=" + src_dir, 652238dcc3SJonas Devlieghere "-C", 662238dcc3SJonas Devlieghere build_dir, 672238dcc3SJonas Devlieghere "-I", 682238dcc3SJonas Devlieghere src_dir, 692238dcc3SJonas Devlieghere "-I", 702238dcc3SJonas Devlieghere os.path.join(lldb_test, "make"), 712238dcc3SJonas Devlieghere "-f", 722238dcc3SJonas Devlieghere makefile, 73b623f3c0SJonas Devlieghere ] 74b623f3c0SJonas Devlieghere 75b623f3c0SJonas Devlieghere def getCmdLine(self, d): 76b623f3c0SJonas Devlieghere """ 77551d1188SPavel Labath Helper function to return a command line argument string used for the 78551d1188SPavel Labath make system. 79b623f3c0SJonas Devlieghere """ 80b623f3c0SJonas Devlieghere 81551d1188SPavel Labath # If d is None or an empty mapping, just return an empty list. 82b623f3c0SJonas Devlieghere if not d: 83551d1188SPavel Labath return [] 84b623f3c0SJonas Devlieghere 85b623f3c0SJonas Devlieghere def setOrAppendVariable(k, v): 86b623f3c0SJonas Devlieghere append_vars = ["CFLAGS", "CFLAGS_EXTRAS", "LD_EXTRAS"] 87b623f3c0SJonas Devlieghere if k in append_vars and k in os.environ: 88b623f3c0SJonas Devlieghere v = os.environ[k] + " " + v 892238dcc3SJonas Devlieghere return "%s=%s" % (k, v) 90b623f3c0SJonas Devlieghere 91551d1188SPavel Labath cmdline = [setOrAppendVariable(k, v) for k, v in list(d.items())] 92b623f3c0SJonas Devlieghere 93b623f3c0SJonas Devlieghere return cmdline 94b623f3c0SJonas Devlieghere 95b623f3c0SJonas Devlieghere def getArchSpec(self, architecture): 96b623f3c0SJonas Devlieghere """ 97b623f3c0SJonas Devlieghere Helper function to return the key-value string to specify the architecture 98b623f3c0SJonas Devlieghere used for the make system. 99b623f3c0SJonas Devlieghere """ 100551d1188SPavel Labath return ["ARCH=" + architecture] if architecture else [] 101b623f3c0SJonas Devlieghere 10244fc987eSVladislav Dzhidzhoev def getToolchainSpec(self, compiler): 103b623f3c0SJonas Devlieghere """ 10444fc987eSVladislav Dzhidzhoev Helper function to return the key-value strings to specify the toolchain 105b623f3c0SJonas Devlieghere used for the make system. 106b623f3c0SJonas Devlieghere """ 107b623f3c0SJonas Devlieghere cc = compiler if compiler else None 108b623f3c0SJonas Devlieghere if not cc and configuration.compiler: 109b623f3c0SJonas Devlieghere cc = configuration.compiler 11044fc987eSVladislav Dzhidzhoev 11144fc987eSVladislav Dzhidzhoev if not cc: 112551d1188SPavel Labath return [] 113b623f3c0SJonas Devlieghere 114aea06684SVladislav Dzhidzhoev exe_ext = "" 115aea06684SVladislav Dzhidzhoev if lldbplatformutil.getHostPlatform() == "windows": 116aea06684SVladislav Dzhidzhoev exe_ext = ".exe" 117aea06684SVladislav Dzhidzhoev 11844fc987eSVladislav Dzhidzhoev cc = cc.strip() 11944fc987eSVladislav Dzhidzhoev cc_path = pathlib.Path(cc) 12044fc987eSVladislav Dzhidzhoev 12144fc987eSVladislav Dzhidzhoev # We can get CC compiler string in the following formats: 12244fc987eSVladislav Dzhidzhoev # [<tool>] <compiler> - such as 'xrun clang', 'xrun /usr/bin/clang' & etc 12344fc987eSVladislav Dzhidzhoev # 12444fc987eSVladislav Dzhidzhoev # Where <compiler> could contain the following parts: 12544fc987eSVladislav Dzhidzhoev # <simple-name>[.<exe-ext>] - sucn as 'clang', 'clang.exe' ('clang-cl.exe'?) 12644fc987eSVladislav Dzhidzhoev # <target-triple>-<simple-name>[.<exe-ext>] - such as 'armv7-linux-gnueabi-gcc' 12744fc987eSVladislav Dzhidzhoev # <path>/<simple-name>[.<exe-ext>] - such as '/usr/bin/clang', 'c:\path\to\compiler\clang,exe' 12844fc987eSVladislav Dzhidzhoev # <path>/<target-triple>-<simple-name>[.<exe-ext>] - such as '/usr/bin/clang', 'c:\path\to\compiler\clang,exe' 12944fc987eSVladislav Dzhidzhoev 13044fc987eSVladislav Dzhidzhoev cc_ext = cc_path.suffix 13144fc987eSVladislav Dzhidzhoev # Compiler name without extension 13244fc987eSVladislav Dzhidzhoev cc_name = cc_path.stem.split(" ")[-1] 13344fc987eSVladislav Dzhidzhoev 13444fc987eSVladislav Dzhidzhoev # A kind of compiler (canonical name): clang, gcc, cc & etc. 13544fc987eSVladislav Dzhidzhoev cc_type = cc_name 13644fc987eSVladislav Dzhidzhoev # A triple prefix of compiler name: <armv7-none-linux-gnu->gcc 13744fc987eSVladislav Dzhidzhoev cc_prefix = "" 13844fc987eSVladislav Dzhidzhoev if not "clang-cl" in cc_name and not "llvm-gcc" in cc_name: 13944fc987eSVladislav Dzhidzhoev cc_name_parts = cc_name.split("-") 14044fc987eSVladislav Dzhidzhoev cc_type = cc_name_parts[-1] 14144fc987eSVladislav Dzhidzhoev if len(cc_name_parts) > 1: 14244fc987eSVladislav Dzhidzhoev cc_prefix = "-".join(cc_name_parts[:-1]) + "-" 14344fc987eSVladislav Dzhidzhoev 14444fc987eSVladislav Dzhidzhoev # A kind of C++ compiler. 14544fc987eSVladislav Dzhidzhoev cxx_types = { 14644fc987eSVladislav Dzhidzhoev "icc": "icpc", 14744fc987eSVladislav Dzhidzhoev "llvm-gcc": "llvm-g++", 14844fc987eSVladislav Dzhidzhoev "gcc": "g++", 14944fc987eSVladislav Dzhidzhoev "cc": "c++", 15044fc987eSVladislav Dzhidzhoev "clang": "clang++", 15144fc987eSVladislav Dzhidzhoev } 15244fc987eSVladislav Dzhidzhoev cxx_type = cxx_types.get(cc_type, cc_type) 15344fc987eSVladislav Dzhidzhoev 15444fc987eSVladislav Dzhidzhoev cc_dir = cc_path.parent 15544fc987eSVladislav Dzhidzhoev 15644fc987eSVladislav Dzhidzhoev def getToolchainUtil(util_name): 157aea06684SVladislav Dzhidzhoev return os.path.join(configuration.llvm_tools_dir, util_name + exe_ext) 15844fc987eSVladislav Dzhidzhoev 159aea06684SVladislav Dzhidzhoev cxx = cc_dir / (cc_prefix + cxx_type + cc_ext) 16044fc987eSVladislav Dzhidzhoev 16144fc987eSVladislav Dzhidzhoev util_names = { 16244fc987eSVladislav Dzhidzhoev "OBJCOPY": "objcopy", 16344fc987eSVladislav Dzhidzhoev "STRIP": "strip", 16444fc987eSVladislav Dzhidzhoev "ARCHIVER": "ar", 16544fc987eSVladislav Dzhidzhoev "DWP": "dwp", 16644fc987eSVladislav Dzhidzhoev } 16744fc987eSVladislav Dzhidzhoev utils = [] 16844fc987eSVladislav Dzhidzhoev 169aea06684SVladislav Dzhidzhoev # Required by API TestBSDArchives.py tests. 170aea06684SVladislav Dzhidzhoev if not os.getenv("LLVM_AR"): 171aea06684SVladislav Dzhidzhoev utils.extend(["LLVM_AR=%s" % getToolchainUtil("llvm-ar")]) 172aea06684SVladislav Dzhidzhoev 17344fc987eSVladislav Dzhidzhoev if cc_type in ["clang", "cc", "gcc"]: 17444fc987eSVladislav Dzhidzhoev util_paths = {} 17544fc987eSVladislav Dzhidzhoev # Assembly a toolchain side tool cmd based on passed CC. 17644fc987eSVladislav Dzhidzhoev for var, name in util_names.items(): 17744fc987eSVladislav Dzhidzhoev # Do not override explicity specified tool from the cmd line. 17844fc987eSVladislav Dzhidzhoev if not os.getenv(var): 179e7174a83SVladislav Dzhidzhoev util_paths[var] = getToolchainUtil("llvm-" + name) 18044fc987eSVladislav Dzhidzhoev else: 18144fc987eSVladislav Dzhidzhoev util_paths[var] = os.getenv(var) 18244fc987eSVladislav Dzhidzhoev utils.extend(["AR=%s" % util_paths["ARCHIVER"]]) 18344fc987eSVladislav Dzhidzhoev 18444fc987eSVladislav Dzhidzhoev # Look for llvm-dwp or gnu dwp 18544fc987eSVladislav Dzhidzhoev if not lldbutil.which(util_paths["DWP"]): 18644fc987eSVladislav Dzhidzhoev util_paths["DWP"] = getToolchainUtil("llvm-dwp") 18744fc987eSVladislav Dzhidzhoev if not lldbutil.which(util_paths["DWP"]): 18844fc987eSVladislav Dzhidzhoev util_paths["DWP"] = lldbutil.which("llvm-dwp") 18944fc987eSVladislav Dzhidzhoev if not util_paths["DWP"]: 19044fc987eSVladislav Dzhidzhoev util_paths["DWP"] = lldbutil.which("dwp") 19144fc987eSVladislav Dzhidzhoev if not util_paths["DWP"]: 19244fc987eSVladislav Dzhidzhoev del util_paths["DWP"] 19344fc987eSVladislav Dzhidzhoev 194*058ede06SVladislav Dzhidzhoev if lldbplatformutil.platformIsDarwin(): 195*058ede06SVladislav Dzhidzhoev util_paths["STRIP"] = seven.get_command_output("xcrun -f strip") 196*058ede06SVladislav Dzhidzhoev 19744fc987eSVladislav Dzhidzhoev for var, path in util_paths.items(): 19844fc987eSVladislav Dzhidzhoev utils.append("%s=%s" % (var, path)) 199b773da0cSVladislav Dzhidzhoev 200b773da0cSVladislav Dzhidzhoev if lldbplatformutil.platformIsDarwin(): 20144fc987eSVladislav Dzhidzhoev utils.extend(["AR=%slibtool" % os.getenv("CROSS_COMPILE", "")]) 20244fc987eSVladislav Dzhidzhoev 20344fc987eSVladislav Dzhidzhoev return [ 20444fc987eSVladislav Dzhidzhoev "CC=%s" % cc, 20544fc987eSVladislav Dzhidzhoev "CC_TYPE=%s" % cc_type, 20644fc987eSVladislav Dzhidzhoev "CXX=%s" % cxx, 20744fc987eSVladislav Dzhidzhoev ] + utils 20844fc987eSVladislav Dzhidzhoev 209b623f3c0SJonas Devlieghere def getSDKRootSpec(self): 210b623f3c0SJonas Devlieghere """ 211b623f3c0SJonas Devlieghere Helper function to return the key-value string to specify the SDK root 212b623f3c0SJonas Devlieghere used for the make system. 213b623f3c0SJonas Devlieghere """ 214b623f3c0SJonas Devlieghere if configuration.sdkroot: 215551d1188SPavel Labath return ["SDKROOT={}".format(configuration.sdkroot)] 216551d1188SPavel Labath return [] 217b623f3c0SJonas Devlieghere 218b623f3c0SJonas Devlieghere def getModuleCacheSpec(self): 219b623f3c0SJonas Devlieghere """ 220b623f3c0SJonas Devlieghere Helper function to return the key-value string to specify the clang 221b623f3c0SJonas Devlieghere module cache used for the make system. 222b623f3c0SJonas Devlieghere """ 223b623f3c0SJonas Devlieghere if configuration.clang_module_cache_dir: 2242238dcc3SJonas Devlieghere return [ 2252238dcc3SJonas Devlieghere "CLANG_MODULE_CACHE_DIR={}".format(configuration.clang_module_cache_dir) 2262238dcc3SJonas Devlieghere ] 227551d1188SPavel Labath return [] 228b623f3c0SJonas Devlieghere 229ce233e71SJonas Devlieghere def getLibCxxArgs(self): 230cc0b5ebfSJonas Devlieghere if configuration.libcxx_include_dir and configuration.libcxx_library_dir: 2312238dcc3SJonas Devlieghere libcpp_args = [ 2322238dcc3SJonas Devlieghere "LIBCPP_INCLUDE_DIR={}".format(configuration.libcxx_include_dir), 2332238dcc3SJonas Devlieghere "LIBCPP_LIBRARY_DIR={}".format(configuration.libcxx_library_dir), 2342238dcc3SJonas Devlieghere ] 235cb0eb9d8SJordan Rupprecht if configuration.libcxx_include_target_dir: 2362238dcc3SJonas Devlieghere libcpp_args.append( 2372238dcc3SJonas Devlieghere "LIBCPP_INCLUDE_TARGET_DIR={}".format( 2382238dcc3SJonas Devlieghere configuration.libcxx_include_target_dir 2392238dcc3SJonas Devlieghere ) 2402238dcc3SJonas Devlieghere ) 241cb0eb9d8SJordan Rupprecht return libcpp_args 242ce233e71SJonas Devlieghere return [] 243ce233e71SJonas Devlieghere 244b88d2112SAdrian Prantl def getLLDBObjRoot(self): 245b88d2112SAdrian Prantl return ["LLDB_OBJ_ROOT={}".format(configuration.lldb_obj_root)] 246b88d2112SAdrian Prantl 2478bac18beSPavel Labath def _getDebugInfoArgs(self, debug_info): 2488bac18beSPavel Labath if debug_info is None: 2498bac18beSPavel Labath return [] 2508bac18beSPavel Labath if debug_info == "dwarf": 2518bac18beSPavel Labath return ["MAKE_DSYM=NO"] 2528bac18beSPavel Labath if debug_info == "dwo": 2538bac18beSPavel Labath return ["MAKE_DSYM=NO", "MAKE_DWO=YES"] 2548bac18beSPavel Labath if debug_info == "gmodules": 2558bac18beSPavel Labath return ["MAKE_DSYM=NO", "MAKE_GMODULES=YES"] 2568bac18beSPavel Labath return None 2578bac18beSPavel Labath 2582238dcc3SJonas Devlieghere def getBuildCommand( 2592238dcc3SJonas Devlieghere self, 2602238dcc3SJonas Devlieghere debug_info, 2612238dcc3SJonas Devlieghere architecture=None, 2622238dcc3SJonas Devlieghere compiler=None, 2632238dcc3SJonas Devlieghere dictionary=None, 2642238dcc3SJonas Devlieghere testdir=None, 2652238dcc3SJonas Devlieghere testname=None, 2662238dcc3SJonas Devlieghere make_targets=None, 2672238dcc3SJonas Devlieghere ): 2688bac18beSPavel Labath debug_info_args = self._getDebugInfoArgs(debug_info) 2698bac18beSPavel Labath if debug_info_args is None: 270eee887e0SPavel Labath return None 2714763200eSGreg Clayton if make_targets is None: 2724763200eSGreg Clayton make_targets = ["all"] 273551d1188SPavel Labath command_parts = [ 2742238dcc3SJonas Devlieghere self.getMake(testdir, testname), 2752238dcc3SJonas Devlieghere debug_info_args, 2762238dcc3SJonas Devlieghere make_targets, 2772238dcc3SJonas Devlieghere self.getArchCFlags(architecture), 2782238dcc3SJonas Devlieghere self.getArchSpec(architecture), 27944fc987eSVladislav Dzhidzhoev self.getToolchainSpec(compiler), 2802238dcc3SJonas Devlieghere self.getExtraMakeArgs(), 2812238dcc3SJonas Devlieghere self.getSDKRootSpec(), 2822238dcc3SJonas Devlieghere self.getModuleCacheSpec(), 2832238dcc3SJonas Devlieghere self.getLibCxxArgs(), 284b88d2112SAdrian Prantl self.getLLDBObjRoot(), 2852238dcc3SJonas Devlieghere self.getCmdLine(dictionary), 2862238dcc3SJonas Devlieghere ] 287551d1188SPavel Labath command = list(itertools.chain(*command_parts)) 288b623f3c0SJonas Devlieghere 289eee887e0SPavel Labath return command 290b623f3c0SJonas Devlieghere 291551d1188SPavel Labath def cleanup(self, dictionary=None): 292b623f3c0SJonas Devlieghere """Perform a platform-specific cleanup after the test.""" 293b623f3c0SJonas Devlieghere return True 294