1import re
2import os
3import subprocess
4
5from .builder import Builder
6from lldbsuite.test import configuration
7import lldbsuite.test.lldbutil as lldbutil
8
9REMOTE_PLATFORM_NAME_RE = re.compile(r"^remote-(.+)$")
10SIMULATOR_PLATFORM_RE = re.compile(r"^(.+)-simulator$")
11
12
13def get_os_env_from_platform(platform):
14    match = REMOTE_PLATFORM_NAME_RE.match(platform)
15    if match:
16        return match.group(1), ""
17    match = SIMULATOR_PLATFORM_RE.match(platform)
18    if match:
19        return match.group(1), "simulator"
20    return None, None
21
22
23def get_os_from_sdk(sdk):
24    return sdk[:sdk.find('.')], ""
25
26from lldbsuite.test import configuration
27
28
29class BuilderDarwin(Builder):
30    def getExtraMakeArgs(self):
31        """
32        Helper function to return extra argumentsfor the make system. This
33        method is meant to be overridden by platform specific builders.
34        """
35        args = dict()
36
37        if configuration.dsymutil:
38            args['DSYMUTIL'] = configuration.dsymutil
39
40        operating_system, _ = self.getOsAndEnv()
41        if operating_system and operating_system != "macosx":
42            builder_dir = os.path.dirname(os.path.abspath(__file__))
43            test_dir = os.path.dirname(builder_dir)
44            entitlements = os.path.join(test_dir, 'make', 'entitlements.plist')
45            args['CODESIGN'] = 'codesign --entitlements {}'.format(entitlements)
46
47        # Return extra args as a formatted string.
48        return ' '.join(
49            {'{}="{}"'.format(key, value)
50             for key, value in args.items()})
51    def getOsAndEnv(self):
52        if configuration.lldb_platform_name:
53            return get_os_env_from_platform(configuration.lldb_platform_name)
54        elif configuration.apple_sdk:
55            return get_os_from_sdk(configuration.apple_sdk)
56        return None, None
57
58    def getArchCFlags(self, architecture):
59        """Returns the ARCH_CFLAGS for the make system."""
60
61        # Construct the arch component.
62        arch = architecture if architecture else configuration.arch
63        if not arch:
64            arch = subprocess.check_output(['machine'
65                                            ]).rstrip().decode('utf-8')
66        if not arch:
67            return ""
68
69        # Construct the vendor component.
70        vendor = "apple"
71
72        # Construct the os component.
73        os, env = self.getOsAndEnv()
74        if os is None or env is None:
75            return ""
76
77        # Get the SDK from the os and env.
78        sdk = lldbutil.get_xcode_sdk(os, env)
79        if not sdk:
80            return ""
81
82        version = lldbutil.get_xcode_sdk_version(sdk)
83        if not version:
84            return ""
85
86        # Construct the triple from its components.
87        triple = "{}-{}-{}-{}".format(vendor, os, version, env)
88
89        # Construct min version argument
90        version_min = ""
91        if env == "simulator":
92            version_min = "-m{}-simulator-version-min={}".format(os, version)
93        elif os == "macosx":
94            version_min = "-m{}-version-min={}".format(os, version)
95
96        return "ARCH_CFLAGS=\"-target {} {}\"".format(triple, version_min)
97
98    def buildDsym(self,
99                  sender=None,
100                  architecture=None,
101                  compiler=None,
102                  dictionary=None,
103                  testdir=None,
104                  testname=None):
105        """Build the binaries with dsym debug info."""
106        commands = []
107        commands.append(
108            self.getMake(testdir, testname) + [
109                "MAKE_DSYM=YES",
110                self.getArchCFlags(architecture),
111                self.getArchSpec(architecture),
112                self.getCCSpec(compiler),
113                self.getExtraMakeArgs(),
114                self.getSDKRootSpec(),
115                self.getModuleCacheSpec(), "all",
116                self.getCmdLine(dictionary)
117            ])
118
119        self.runBuildCommands(commands, sender=sender)
120
121        # True signifies that we can handle building dsym.
122        return True
123