brintos

brintos / llvm-project-archived public Read only

0
0
Text · 10.7 KiB · 024c9f1 Raw
310 lines · python
1import os2import pathlib3import platform4import subprocess5import sys6import itertools7 8import lldbsuite.test.lldbtest as lldbtest9import lldbsuite.test.lldbplatformutil as lldbplatformutil10import lldbsuite.test.lldbutil as lldbutil11from lldbsuite.test import configuration12from lldbsuite.test_event import build_exception13from lldbsuite.support import seven14 15 16class Builder:17    def getArchitecture(self):18        """Returns the architecture in effect the test suite is running with."""19        return configuration.arch if configuration.arch else ""20 21    def getCompiler(self):22        """Returns the compiler in effect the test suite is running with."""23        compiler = configuration.compiler if configuration.compiler else "clang"24        compiler = lldbutil.which(compiler)25        return os.path.abspath(compiler)26 27    def getTriple(self, arch):28        """Returns the triple for the given architecture or None."""29        return configuration.triple30 31    def getExtraMakeArgs(self):32        """33        Helper function to return extra argumentsfor the make system. This34        method is meant to be overridden by platform specific builders.35        """36        return []37 38    def getArchCFlags(self, architecture):39        """Returns the ARCH_CFLAGS for the make system."""40        triple = self.getTriple(architecture)41        if triple:42            return ["ARCH_CFLAGS=-target {}".format(triple)]43        return []44 45    def getMake(self, test_subdir, test_name):46        """Returns the invocation for GNU make.47        The first argument is a tuple of the relative path to the testcase48        and its filename stem."""49        # Construct the base make invocation.50        lldb_test = os.environ["LLDB_TEST"]51        if not (52            lldb_test53            and configuration.test_build_dir54            and test_subdir55            and test_name56            and (not os.path.isabs(test_subdir))57        ):58            raise Exception("Could not derive test directories")59        build_dir = os.path.join(configuration.test_build_dir, test_subdir, test_name)60        src_dir = os.path.join(configuration.test_src_root, test_subdir)61        # This is a bit of a hack to make inline testcases work.62        makefile = os.path.join(src_dir, "Makefile")63        if not os.path.isfile(makefile):64            makefile = os.path.join(build_dir, "Makefile")65        return [66            configuration.make_path,67            "VPATH=" + src_dir,68            "-C",69            build_dir,70            "-I",71            src_dir,72            "-I",73            os.path.join(lldb_test, "make"),74            "-f",75            makefile,76        ]77 78    def getCmdLine(self, d):79        """80        Helper function to return a command line argument string used for the81        make system.82        """83 84        # If d is None or an empty mapping, just return an empty list.85        if not d:86            return []87 88        def setOrAppendVariable(k, v):89            append_vars = ["CFLAGS", "CFLAGS_EXTRAS", "LD_EXTRAS"]90            if k in append_vars and k in os.environ:91                v = os.environ[k] + " " + v92            return "%s=%s" % (k, v)93 94        cmdline = [setOrAppendVariable(k, v) for k, v in list(d.items())]95 96        return cmdline97 98    def getArchSpec(self, architecture):99        """100        Helper function to return the key-value string to specify the architecture101        used for the make system.102        """103        return ["ARCH=" + architecture] if architecture else []104 105    def getToolchainSpec(self, compiler):106        """107        Helper function to return the key-value strings to specify the toolchain108        used for the make system.109        """110        cc = compiler if compiler else None111        if not cc and configuration.compiler:112            cc = configuration.compiler113 114        if not cc:115            return []116 117        exe_ext = ""118        if lldbplatformutil.getHostPlatform() == "windows":119            exe_ext = ".exe"120 121        cc = cc.strip()122        cc_path = pathlib.Path(cc)123 124        # We can get CC compiler string in the following formats:125        #  [<tool>] <compiler>    - such as 'xrun clang', 'xrun /usr/bin/clang' & etc126        #127        # Where <compiler> could contain the following parts:128        #   <simple-name>[.<exe-ext>]                           - sucn as 'clang', 'clang.exe' ('clang-cl.exe'?)129        #   <target-triple>-<simple-name>[.<exe-ext>]           - such as 'armv7-linux-gnueabi-gcc'130        #   <path>/<simple-name>[.<exe-ext>]                    - such as '/usr/bin/clang', 'c:\path\to\compiler\clang,exe'131        #   <path>/<target-triple>-<simple-name>[.<exe-ext>]    - such as '/usr/bin/clang', 'c:\path\to\compiler\clang,exe'132 133        cc_ext = cc_path.suffix134        # Compiler name without extension135        cc_name = cc_path.stem.split(" ")[-1]136 137        # A kind of compiler (canonical name): clang, gcc, cc & etc.138        cc_type = cc_name139        # A triple prefix of compiler name: <armv7-none-linux-gnu->gcc140        cc_prefix = ""141        if not "clang-cl" in cc_name and not "llvm-gcc" in cc_name:142            cc_name_parts = cc_name.split("-")143            cc_type = cc_name_parts[-1]144            if len(cc_name_parts) > 1:145                cc_prefix = "-".join(cc_name_parts[:-1]) + "-"146 147        # A kind of C++ compiler.148        cxx_types = {149            "icc": "icpc",150            "llvm-gcc": "llvm-g++",151            "gcc": "g++",152            "cc": "c++",153            "clang": "clang++",154        }155        cxx_type = cxx_types.get(cc_type, cc_type)156 157        cc_dir = cc_path.parent158 159        def getToolchainUtil(util_name):160            return os.path.join(configuration.llvm_tools_dir, util_name + exe_ext)161 162        cxx = cc_dir / (cc_prefix + cxx_type + cc_ext)163 164        util_names = {165            "OBJCOPY": "objcopy",166            "STRIP": "strip",167            "ARCHIVER": "ar",168            "DWP": "dwp",169        }170        utils = []171 172        # Required by API TestBSDArchives.py tests.173        if not os.getenv("LLVM_AR"):174            utils.extend(["LLVM_AR=%s" % getToolchainUtil("llvm-ar")])175 176        if cc_type in ["clang", "cc", "gcc"]:177            util_paths = {}178            # Assembly a toolchain side tool cmd based on passed CC.179            for var, name in util_names.items():180                # Do not override explicity specified tool from the cmd line.181                if not os.getenv(var):182                    util_paths[var] = getToolchainUtil("llvm-" + name)183                else:184                    util_paths[var] = os.getenv(var)185            utils.extend(["AR=%s" % util_paths["ARCHIVER"]])186 187            # Look for llvm-dwp or gnu dwp188            if not lldbutil.which(util_paths["DWP"]):189                util_paths["DWP"] = getToolchainUtil("llvm-dwp")190            if not lldbutil.which(util_paths["DWP"]):191                util_paths["DWP"] = lldbutil.which("llvm-dwp")192            if not util_paths["DWP"]:193                util_paths["DWP"] = lldbutil.which("dwp")194                if not util_paths["DWP"]:195                    del util_paths["DWP"]196 197            if lldbplatformutil.platformIsDarwin():198                util_paths["STRIP"] = seven.get_command_output("xcrun -f strip")199 200            for var, path in util_paths.items():201                utils.append("%s=%s" % (var, path))202 203        if lldbplatformutil.platformIsDarwin():204            utils.extend(["AR=%slibtool" % os.getenv("CROSS_COMPILE", "")])205 206        return [207            "CC=%s" % cc,208            "CC_TYPE=%s" % cc_type,209            "CXX=%s" % cxx,210        ] + utils211 212    def getSDKRootSpec(self):213        """214        Helper function to return the key-value string to specify the SDK root215        used for the make system.216        """217        if configuration.sdkroot:218            return ["SDKROOT={}".format(configuration.sdkroot)]219        return []220 221    def getModuleCacheSpec(self):222        """223        Helper function to return the key-value string to specify the clang224        module cache used for the make system.225        """226        if configuration.clang_module_cache_dir:227            return [228                "CLANG_MODULE_CACHE_DIR={}".format(configuration.clang_module_cache_dir)229            ]230        return []231 232    def getLibCxxArgs(self):233        if configuration.libcxx_include_dir and configuration.libcxx_library_dir:234            libcpp_args = [235                "LIBCPP_INCLUDE_DIR={}".format(configuration.libcxx_include_dir),236                "LIBCPP_LIBRARY_DIR={}".format(configuration.libcxx_library_dir),237            ]238            if configuration.libcxx_include_target_dir:239                libcpp_args.append(240                    "LIBCPP_INCLUDE_TARGET_DIR={}".format(241                        configuration.libcxx_include_target_dir242                    )243                )244            return libcpp_args245        return []246 247    def getLLDBObjRoot(self):248        return ["LLDB_OBJ_ROOT={}".format(configuration.lldb_obj_root)]249 250    def _getDebugInfoArgs(self, debug_info):251        if debug_info is None:252            return []253 254        debug_options = debug_info if isinstance(debug_info, list) else [debug_info]255        option_flags = {256            "dwarf": {"MAKE_DSYM": "NO"},257            "dwo": {"MAKE_DSYM": "NO", "MAKE_DWO": "YES"},258            "gmodules": {"MAKE_DSYM": "NO", "MAKE_GMODULES": "YES"},259            "debug_names": {"MAKE_DEBUG_NAMES": "YES"},260            "dwp": {"MAKE_DSYM": "NO", "MAKE_DWP": "YES"},261            "pdb": {"MAKE_PDB": "YES"},262        }263 264        # Collect all flags, with later options overriding earlier ones265        flags = {}266 267        for option in debug_options:268            if not option or option not in option_flags:269                return None  # Invalid options270            flags.update(option_flags[option])271 272        return [f"{key}={value}" for key, value in flags.items()]273 274    def getBuildCommand(275        self,276        debug_info,277        architecture=None,278        compiler=None,279        dictionary=None,280        testdir=None,281        testname=None,282        make_targets=None,283    ):284        debug_info_args = self._getDebugInfoArgs(debug_info)285        if debug_info_args is None:286            return None287        if make_targets is None:288            make_targets = ["all"]289        command_parts = [290            self.getMake(testdir, testname),291            debug_info_args,292            make_targets,293            self.getArchCFlags(architecture),294            self.getArchSpec(architecture),295            self.getToolchainSpec(compiler),296            self.getExtraMakeArgs(),297            self.getSDKRootSpec(),298            self.getModuleCacheSpec(),299            self.getLibCxxArgs(),300            self.getLLDBObjRoot(),301            self.getCmdLine(dictionary),302        ]303        command = list(itertools.chain(*command_parts))304 305        return command306 307    def cleanup(self, dictionary=None):308        """Perform a platform-specific cleanup after the test."""309        return True310