xref: /llvm-project/lldb/packages/Python/lldbsuite/test/builders/builder.py (revision 327146639c049f3cff13c94ec44c12aa718b9fe4)
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 (lldb_test and configuration.test_build_dir and test_subdir
51                and test_name and (not os.path.isabs(test_subdir))):
52            raise Exception("Could not derive test directories")
53        build_dir = os.path.join(configuration.test_build_dir, test_subdir,
54                                 test_name)
55        src_dir = os.path.join(configuration.test_src_root, test_subdir)
56        # This is a bit of a hack to make inline testcases work.
57        makefile = os.path.join(src_dir, "Makefile")
58        if not os.path.isfile(makefile):
59            makefile = os.path.join(build_dir, "Makefile")
60        return [
61            make, "VPATH=" + src_dir, "-C", build_dir, "-I", src_dir, "-I",
62            os.path.join(lldb_test, "make"), "-f", makefile
63        ]
64
65    def getCmdLine(self, d):
66        """
67        Helper function to return a command line argument string used for the
68        make system.
69        """
70
71        # If d is None or an empty mapping, just return an empty list.
72        if not d:
73            return []
74
75        def setOrAppendVariable(k, v):
76            append_vars = ["CFLAGS", "CFLAGS_EXTRAS", "LD_EXTRAS"]
77            if k in append_vars and k in os.environ:
78                v = os.environ[k] + " " + v
79            return '%s=%s' % (k, v)
80
81        cmdline = [setOrAppendVariable(k, v) for k, v in list(d.items())]
82
83        return cmdline
84
85    def getArchSpec(self, architecture):
86        """
87        Helper function to return the key-value string to specify the architecture
88        used for the make system.
89        """
90        return ["ARCH=" + architecture] if architecture else []
91
92    def getCCSpec(self, compiler):
93        """
94        Helper function to return the key-value string to specify the compiler
95        used for the make system.
96        """
97        cc = compiler if compiler else None
98        if not cc and configuration.compiler:
99            cc = configuration.compiler
100        if cc:
101            return ["CC=\"%s\"" % cc]
102        return []
103
104    def getSDKRootSpec(self):
105        """
106        Helper function to return the key-value string to specify the SDK root
107        used for the make system.
108        """
109        if configuration.sdkroot:
110            return ["SDKROOT={}".format(configuration.sdkroot)]
111        return []
112
113    def getModuleCacheSpec(self):
114        """
115        Helper function to return the key-value string to specify the clang
116        module cache used for the make system.
117        """
118        if configuration.clang_module_cache_dir:
119            return ["CLANG_MODULE_CACHE_DIR={}".format(
120                configuration.clang_module_cache_dir)]
121        return []
122
123    def getLibCxxArgs(self):
124        if configuration.libcxx_include_dir and configuration.libcxx_library_dir:
125            return ["LIBCPP_INCLUDE_DIR={}".format(configuration.libcxx_include_dir),
126                    "LIBCPP_LIBRARY_DIR={}".format(configuration.libcxx_library_dir)]
127        return []
128
129    def _getDebugInfoArgs(self, debug_info):
130        if debug_info is None:
131            return []
132        if debug_info == "dwarf":
133            return ["MAKE_DSYM=NO"]
134        if debug_info == "dwo":
135            return ["MAKE_DSYM=NO", "MAKE_DWO=YES"]
136        if debug_info == "gmodules":
137            return ["MAKE_DSYM=NO", "MAKE_GMODULES=YES"]
138        return None
139
140    def getBuildCommand(self, debug_info, architecture=None, compiler=None,
141            dictionary=None, testdir=None, testname=None):
142        debug_info_args = self._getDebugInfoArgs(debug_info)
143        if debug_info_args is None:
144            return None
145
146        command_parts = [
147            self.getMake(testdir, testname), debug_info_args, ["all"],
148            self.getArchCFlags(architecture), self.getArchSpec(architecture),
149            self.getCCSpec(compiler), self.getExtraMakeArgs(),
150            self.getSDKRootSpec(), self.getModuleCacheSpec(),
151            self.getLibCxxArgs(), self.getCmdLine(dictionary)]
152        command = list(itertools.chain(*command_parts))
153
154        return command
155
156    def cleanup(self, dictionary=None):
157        """Perform a platform-specific cleanup after the test."""
158        return True
159