1import os
2import itertools
3import platform
4import subprocess
5import sys
6
7import lit.util
8from lit.llvm import llvm_config
9from lit.llvm.subst import FindTool
10from lit.llvm.subst import ToolSubst
11
12
13def _get_lldb_init_path(config):
14    return os.path.join(config.test_exec_root, 'Shell', 'lit-lldb-init')
15
16
17def _disallow(config, execName):
18  warning = '''
19    echo '*** Do not use \'{0}\' in tests; use \'%''{0}\'. ***' &&
20    exit 1 && echo
21  '''
22  config.substitutions.append((' {0} '.format(execName),
23                               warning.format(execName)))
24
25
26def use_lldb_substitutions(config):
27    # Set up substitutions for primary tools.  These tools must come from config.lldb_tools_dir
28    # which is basically the build output directory.  We do not want to find these in path or
29    # anywhere else, since they are specifically the programs which are actually being tested.
30
31    dsname = 'debugserver' if platform.system() in ['Darwin'] else 'lldb-server'
32    dsargs = [] if platform.system() in ['Darwin'] else ['gdbserver']
33
34    build_script = os.path.dirname(__file__)
35    build_script = os.path.join(build_script, 'build.py')
36    build_script_args = [build_script,
37                        '--compiler=any', # Default to best compiler
38                        '--arch=' + str(config.lldb_bitness)]
39    if config.lldb_lit_tools_dir:
40        build_script_args.append('--tools-dir={0}'.format(config.lldb_lit_tools_dir))
41    if config.lldb_tools_dir:
42        build_script_args.append('--tools-dir={0}'.format(config.lldb_tools_dir))
43    if config.llvm_libs_dir:
44        build_script_args.append('--libs-dir={0}'.format(config.llvm_libs_dir))
45
46    lldb_init = _get_lldb_init_path(config)
47
48    primary_tools = [
49        ToolSubst('%lldb',
50                  command=FindTool('lldb'),
51                  extra_args=['--no-lldbinit', '-S', lldb_init]),
52        ToolSubst('%lldb-init',
53                  command=FindTool('lldb'),
54                  extra_args=['-S', lldb_init]),
55        ToolSubst('%debugserver',
56                  command=FindTool(dsname),
57                  extra_args=dsargs,
58                  unresolved='ignore'),
59        ToolSubst('%platformserver',
60                  command=FindTool('lldb-server'),
61                  extra_args=['platform'],
62                  unresolved='ignore'),
63        'lldb-test',
64        'lldb-instr',
65        ToolSubst('%build',
66                  command="'" + sys.executable + "'",
67                  extra_args=build_script_args)
68        ]
69
70    _disallow(config, 'lldb')
71    _disallow(config, 'debugserver')
72    _disallow(config, 'platformserver')
73
74    llvm_config.add_tool_substitutions(primary_tools,
75                                       [config.lldb_tools_dir])
76
77def _use_msvc_substitutions(config):
78    # If running from a Visual Studio Command prompt (e.g. vcvars), this will
79    # detect the include and lib paths, and find cl.exe and link.exe and create
80    # substitutions for each of them that explicitly specify /I and /L paths
81    cl = lit.util.which('cl')
82    link = lit.util.which('link')
83
84    if not cl or not link:
85        return
86
87    cl = '"' + cl + '"'
88    link = '"' + link + '"'
89    includes = os.getenv('INCLUDE', '').split(';')
90    libs = os.getenv('LIB', '').split(';')
91
92    config.available_features.add('msvc')
93    compiler_flags = ['"/I{}"'.format(x) for x in includes if os.path.exists(x)]
94    linker_flags = ['"/LIBPATH:{}"'.format(x) for x in libs if os.path.exists(x)]
95
96    tools = [
97        ToolSubst('%msvc_cl', command=cl, extra_args=compiler_flags),
98        ToolSubst('%msvc_link', command=link, extra_args=linker_flags)]
99    llvm_config.add_tool_substitutions(tools)
100    return
101
102def use_support_substitutions(config):
103    # Set up substitutions for support tools.  These tools can be overridden at the CMake
104    # level (by specifying -DLLDB_LIT_TOOLS_DIR), installed, or as a last resort, we can use
105    # the just-built version.
106    host_flags = ['--target=' + config.host_triple]
107    if platform.system() in ['Darwin']:
108        try:
109            out = subprocess.check_output(['xcrun', '--show-sdk-path']).strip()
110            res = 0
111        except OSError:
112            res = -1
113        if res == 0 and out:
114            sdk_path = lit.util.to_string(out)
115            llvm_config.lit_config.note('using SDKROOT: %r' % sdk_path)
116            host_flags += ['-isysroot', sdk_path]
117    elif platform.system() in ['NetBSD', 'OpenBSD', 'Linux']:
118        host_flags += ['-pthread']
119
120    if sys.platform.startswith('netbsd'):
121        # needed e.g. to use freshly built libc++
122        host_flags += ['-L' + config.llvm_libs_dir,
123                  '-Wl,-rpath,' + config.llvm_libs_dir]
124
125    # The clang module cache is used for building inferiors.
126    host_flags += ['-fmodules-cache-path={}'.format(config.clang_module_cache)]
127
128    host_flags = ' '.join(host_flags)
129    config.substitutions.append(('%clang_host', '%clang ' + host_flags))
130    config.substitutions.append(('%clangxx_host', '%clangxx ' + host_flags))
131    config.substitutions.append(('%clang_cl_host', '%clang_cl --target='+config.host_triple))
132
133    additional_tool_dirs=[]
134    if config.lldb_lit_tools_dir:
135        additional_tool_dirs.append(config.lldb_lit_tools_dir)
136
137    llvm_config.use_clang(additional_flags=['--target=specify-a-target-or-use-a-_host-substitution'],
138                          additional_tool_dirs=additional_tool_dirs,
139                          required=True)
140
141
142    if sys.platform == 'win32':
143        _use_msvc_substitutions(config)
144
145    have_lld = llvm_config.use_lld(additional_tool_dirs=additional_tool_dirs,
146                                   required=False)
147    if have_lld:
148        config.available_features.add('lld')
149
150
151    support_tools = ['yaml2obj', 'obj2yaml', 'llvm-pdbutil',
152                     'llvm-mc', 'llvm-readobj', 'llvm-objdump',
153                     'llvm-objcopy', 'lli']
154    additional_tool_dirs += [config.lldb_tools_dir, config.llvm_tools_dir]
155    llvm_config.add_tool_substitutions(support_tools, additional_tool_dirs)
156
157    _disallow(config, 'clang')
158
159def use_lldb_repro_substitutions(config, mode):
160    lldb_init = _get_lldb_init_path(config)
161    substitutions = [
162        ToolSubst(
163            '%lldb',
164            command=FindTool('lldb-repro'),
165            extra_args=[mode, '--no-lldbinit', '-S', lldb_init]),
166        ToolSubst(
167            '%lldb-init',
168            command=FindTool('lldb-repro'),
169            extra_args=[mode, '-S', lldb_init]),
170    ]
171    llvm_config.add_tool_substitutions(substitutions)
172