1 | """llvm
|
---|
2 |
|
---|
3 | Tool-specific initialization for LLVM
|
---|
4 |
|
---|
5 | """
|
---|
6 |
|
---|
7 | #
|
---|
8 | # Copyright (c) 2009 VMware, Inc.
|
---|
9 | #
|
---|
10 | # Permission is hereby granted, free of charge, to any person obtaining
|
---|
11 | # a copy of this software and associated documentation files (the
|
---|
12 | # "Software"), to deal in the Software without restriction, including
|
---|
13 | # without limitation the rights to use, copy, modify, merge, publish,
|
---|
14 | # distribute, sublicense, and/or sell copies of the Software, and to
|
---|
15 | # permit persons to whom the Software is furnished to do so, subject to
|
---|
16 | # the following conditions:
|
---|
17 | #
|
---|
18 | # The above copyright notice and this permission notice shall be included
|
---|
19 | # in all copies or substantial portions of the Software.
|
---|
20 | #
|
---|
21 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
|
---|
22 | # KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
---|
23 | # WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
---|
24 | # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
---|
25 | # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
---|
26 | # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
---|
27 | # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
---|
28 | #
|
---|
29 |
|
---|
30 | import os
|
---|
31 | import os.path
|
---|
32 | import re
|
---|
33 | import sys
|
---|
34 | import distutils.version
|
---|
35 |
|
---|
36 | import SCons.Errors
|
---|
37 | import SCons.Util
|
---|
38 |
|
---|
39 |
|
---|
40 | required_llvm_version = '3.3'
|
---|
41 |
|
---|
42 |
|
---|
43 | def generate(env):
|
---|
44 | env['llvm'] = False
|
---|
45 |
|
---|
46 | try:
|
---|
47 | llvm_dir = os.environ['LLVM']
|
---|
48 | except KeyError:
|
---|
49 | # Do nothing -- use the system headers/libs
|
---|
50 | llvm_dir = None
|
---|
51 | else:
|
---|
52 | if not os.path.isdir(llvm_dir):
|
---|
53 | raise SCons.Errors.InternalError("Specified LLVM directory not found")
|
---|
54 |
|
---|
55 | if env['debug']:
|
---|
56 | llvm_subdir = 'Debug'
|
---|
57 | else:
|
---|
58 | llvm_subdir = 'Release'
|
---|
59 |
|
---|
60 | llvm_bin_dir = os.path.join(llvm_dir, llvm_subdir, 'bin')
|
---|
61 | if not os.path.isdir(llvm_bin_dir):
|
---|
62 | llvm_bin_dir = os.path.join(llvm_dir, 'bin')
|
---|
63 | if not os.path.isdir(llvm_bin_dir):
|
---|
64 | raise SCons.Errors.InternalError("LLVM binary directory not found")
|
---|
65 |
|
---|
66 | env.PrependENVPath('PATH', llvm_bin_dir)
|
---|
67 |
|
---|
68 | if env['platform'] == 'windows':
|
---|
69 | # XXX: There is no llvm-config on Windows, so assume a standard layout
|
---|
70 | if llvm_dir is None:
|
---|
71 | print('scons: LLVM environment variable must be specified when building for windows')
|
---|
72 | return
|
---|
73 |
|
---|
74 | # Try to determine the LLVM version from llvm/Config/config.h
|
---|
75 | llvm_config = os.path.join(llvm_dir, 'include/llvm/Config/llvm-config.h')
|
---|
76 | if not os.path.exists(llvm_config):
|
---|
77 | print('scons: could not find %s' % llvm_config)
|
---|
78 | return
|
---|
79 | llvm_version_major_re = re.compile(r'^#define LLVM_VERSION_MAJOR ([0-9]+)')
|
---|
80 | llvm_version_minor_re = re.compile(r'^#define LLVM_VERSION_MINOR ([0-9]+)')
|
---|
81 | llvm_version = None
|
---|
82 | llvm_version_major = None
|
---|
83 | llvm_version_minor = None
|
---|
84 | for line in open(llvm_config, 'rt'):
|
---|
85 | mo = llvm_version_major_re.match(line)
|
---|
86 | if mo:
|
---|
87 | llvm_version_major = mo.group(1)
|
---|
88 | mo = llvm_version_minor_re.match(line)
|
---|
89 | if mo:
|
---|
90 | llvm_version_minor = mo.group(1)
|
---|
91 | if llvm_version_major is not None and llvm_version_minor is not None:
|
---|
92 | llvm_version = distutils.version.LooseVersion('%s.%s' % (llvm_version_major, llvm_version_minor))
|
---|
93 |
|
---|
94 | if llvm_version is None:
|
---|
95 | print('scons: could not determine the LLVM version from %s' % llvm_config)
|
---|
96 | return
|
---|
97 | if llvm_version < distutils.version.LooseVersion(required_llvm_version):
|
---|
98 | print('scons: LLVM version %s found, but %s is required' % (llvm_version, required_llvm_version))
|
---|
99 | return
|
---|
100 |
|
---|
101 | env.Prepend(CPPPATH = [os.path.join(llvm_dir, 'include')])
|
---|
102 | env.AppendUnique(CPPDEFINES = [
|
---|
103 | 'HAVE_STDINT_H',
|
---|
104 | ])
|
---|
105 | env.Prepend(LIBPATH = [os.path.join(llvm_dir, 'lib')])
|
---|
106 | # LIBS should match the output of `llvm-config --libs engine mcjit bitwriter x86asmprinter irreader`
|
---|
107 | if llvm_version >= distutils.version.LooseVersion('5.0'):
|
---|
108 | env.Prepend(LIBS = [
|
---|
109 | 'LLVMX86Disassembler', 'LLVMX86AsmParser',
|
---|
110 | 'LLVMX86CodeGen', 'LLVMSelectionDAG', 'LLVMAsmPrinter',
|
---|
111 | 'LLVMDebugInfoCodeView', 'LLVMCodeGen',
|
---|
112 | 'LLVMScalarOpts', 'LLVMInstCombine',
|
---|
113 | 'LLVMTransformUtils',
|
---|
114 | 'LLVMBitWriter', 'LLVMX86Desc',
|
---|
115 | 'LLVMMCDisassembler', 'LLVMX86Info',
|
---|
116 | 'LLVMX86AsmPrinter', 'LLVMX86Utils',
|
---|
117 | 'LLVMMCJIT', 'LLVMExecutionEngine', 'LLVMTarget',
|
---|
118 | 'LLVMAnalysis', 'LLVMProfileData',
|
---|
119 | 'LLVMRuntimeDyld', 'LLVMObject', 'LLVMMCParser',
|
---|
120 | 'LLVMBitReader', 'LLVMMC', 'LLVMCore',
|
---|
121 | 'LLVMSupport',
|
---|
122 | 'LLVMIRReader', 'LLVMAsmParser',
|
---|
123 | 'LLVMDemangle', 'LLVMGlobalISel', 'LLVMDebugInfoMSF',
|
---|
124 | 'LLVMBinaryFormat',
|
---|
125 | ])
|
---|
126 | elif llvm_version >= distutils.version.LooseVersion('4.0'):
|
---|
127 | env.Prepend(LIBS = [
|
---|
128 | 'LLVMX86Disassembler', 'LLVMX86AsmParser',
|
---|
129 | 'LLVMX86CodeGen', 'LLVMSelectionDAG', 'LLVMAsmPrinter',
|
---|
130 | 'LLVMDebugInfoCodeView', 'LLVMCodeGen',
|
---|
131 | 'LLVMScalarOpts', 'LLVMInstCombine',
|
---|
132 | 'LLVMTransformUtils',
|
---|
133 | 'LLVMBitWriter', 'LLVMX86Desc',
|
---|
134 | 'LLVMMCDisassembler', 'LLVMX86Info',
|
---|
135 | 'LLVMX86AsmPrinter', 'LLVMX86Utils',
|
---|
136 | 'LLVMMCJIT', 'LLVMExecutionEngine', 'LLVMTarget',
|
---|
137 | 'LLVMAnalysis', 'LLVMProfileData',
|
---|
138 | 'LLVMRuntimeDyld', 'LLVMObject', 'LLVMMCParser',
|
---|
139 | 'LLVMBitReader', 'LLVMMC', 'LLVMCore',
|
---|
140 | 'LLVMSupport',
|
---|
141 | 'LLVMIRReader', 'LLVMAsmParser',
|
---|
142 | 'LLVMDemangle', 'LLVMGlobalISel', 'LLVMDebugInfoMSF',
|
---|
143 | ])
|
---|
144 | elif llvm_version >= distutils.version.LooseVersion('3.9'):
|
---|
145 | env.Prepend(LIBS = [
|
---|
146 | 'LLVMX86Disassembler', 'LLVMX86AsmParser',
|
---|
147 | 'LLVMX86CodeGen', 'LLVMSelectionDAG', 'LLVMAsmPrinter',
|
---|
148 | 'LLVMDebugInfoCodeView', 'LLVMCodeGen',
|
---|
149 | 'LLVMScalarOpts', 'LLVMInstCombine',
|
---|
150 | 'LLVMInstrumentation', 'LLVMTransformUtils',
|
---|
151 | 'LLVMBitWriter', 'LLVMX86Desc',
|
---|
152 | 'LLVMMCDisassembler', 'LLVMX86Info',
|
---|
153 | 'LLVMX86AsmPrinter', 'LLVMX86Utils',
|
---|
154 | 'LLVMMCJIT', 'LLVMExecutionEngine', 'LLVMTarget',
|
---|
155 | 'LLVMAnalysis', 'LLVMProfileData',
|
---|
156 | 'LLVMRuntimeDyld', 'LLVMObject', 'LLVMMCParser',
|
---|
157 | 'LLVMBitReader', 'LLVMMC', 'LLVMCore',
|
---|
158 | 'LLVMSupport',
|
---|
159 | 'LLVMIRReader', 'LLVMASMParser'
|
---|
160 | ])
|
---|
161 | elif llvm_version >= distutils.version.LooseVersion('3.7'):
|
---|
162 | env.Prepend(LIBS = [
|
---|
163 | 'LLVMBitWriter', 'LLVMX86Disassembler', 'LLVMX86AsmParser',
|
---|
164 | 'LLVMX86CodeGen', 'LLVMSelectionDAG', 'LLVMAsmPrinter',
|
---|
165 | 'LLVMCodeGen', 'LLVMScalarOpts', 'LLVMProfileData',
|
---|
166 | 'LLVMInstCombine', 'LLVMInstrumentation', 'LLVMTransformUtils', 'LLVMipa',
|
---|
167 | 'LLVMAnalysis', 'LLVMX86Desc', 'LLVMMCDisassembler',
|
---|
168 | 'LLVMX86Info', 'LLVMX86AsmPrinter', 'LLVMX86Utils',
|
---|
169 | 'LLVMMCJIT', 'LLVMTarget', 'LLVMExecutionEngine',
|
---|
170 | 'LLVMRuntimeDyld', 'LLVMObject', 'LLVMMCParser',
|
---|
171 | 'LLVMBitReader', 'LLVMMC', 'LLVMCore', 'LLVMSupport'
|
---|
172 | ])
|
---|
173 | elif llvm_version >= distutils.version.LooseVersion('3.6'):
|
---|
174 | env.Prepend(LIBS = [
|
---|
175 | 'LLVMBitWriter', 'LLVMX86Disassembler', 'LLVMX86AsmParser',
|
---|
176 | 'LLVMX86CodeGen', 'LLVMSelectionDAG', 'LLVMAsmPrinter',
|
---|
177 | 'LLVMCodeGen', 'LLVMScalarOpts', 'LLVMProfileData',
|
---|
178 | 'LLVMInstCombine', 'LLVMTransformUtils', 'LLVMipa',
|
---|
179 | 'LLVMAnalysis', 'LLVMX86Desc', 'LLVMMCDisassembler',
|
---|
180 | 'LLVMX86Info', 'LLVMX86AsmPrinter', 'LLVMX86Utils',
|
---|
181 | 'LLVMMCJIT', 'LLVMTarget', 'LLVMExecutionEngine',
|
---|
182 | 'LLVMRuntimeDyld', 'LLVMObject', 'LLVMMCParser',
|
---|
183 | 'LLVMBitReader', 'LLVMMC', 'LLVMCore', 'LLVMSupport'
|
---|
184 | ])
|
---|
185 | elif llvm_version >= distutils.version.LooseVersion('3.5'):
|
---|
186 | env.Prepend(LIBS = [
|
---|
187 | 'LLVMMCDisassembler',
|
---|
188 | 'LLVMBitWriter', 'LLVMMCJIT', 'LLVMRuntimeDyld',
|
---|
189 | 'LLVMX86Disassembler', 'LLVMX86AsmParser', 'LLVMX86CodeGen',
|
---|
190 | 'LLVMSelectionDAG', 'LLVMAsmPrinter', 'LLVMX86Desc',
|
---|
191 | 'LLVMObject', 'LLVMMCParser', 'LLVMBitReader', 'LLVMX86Info',
|
---|
192 | 'LLVMX86AsmPrinter', 'LLVMX86Utils', 'LLVMJIT',
|
---|
193 | 'LLVMExecutionEngine', 'LLVMCodeGen', 'LLVMScalarOpts',
|
---|
194 | 'LLVMInstCombine', 'LLVMTransformUtils', 'LLVMipa',
|
---|
195 | 'LLVMAnalysis', 'LLVMTarget', 'LLVMMC', 'LLVMCore',
|
---|
196 | 'LLVMSupport'
|
---|
197 | ])
|
---|
198 | else:
|
---|
199 | env.Prepend(LIBS = [
|
---|
200 | 'LLVMMCDisassembler',
|
---|
201 | 'LLVMBitWriter', 'LLVMX86Disassembler', 'LLVMX86AsmParser',
|
---|
202 | 'LLVMX86CodeGen', 'LLVMX86Desc', 'LLVMSelectionDAG',
|
---|
203 | 'LLVMAsmPrinter', 'LLVMMCParser', 'LLVMX86AsmPrinter',
|
---|
204 | 'LLVMX86Utils', 'LLVMX86Info', 'LLVMMCJIT', 'LLVMJIT',
|
---|
205 | 'LLVMExecutionEngine', 'LLVMCodeGen', 'LLVMScalarOpts',
|
---|
206 | 'LLVMInstCombine', 'LLVMTransformUtils', 'LLVMipa',
|
---|
207 | 'LLVMAnalysis', 'LLVMTarget', 'LLVMMC', 'LLVMCore',
|
---|
208 | 'LLVMSupport', 'LLVMRuntimeDyld', 'LLVMObject'
|
---|
209 | ])
|
---|
210 | env.Append(LIBS = [
|
---|
211 | 'imagehlp',
|
---|
212 | 'psapi',
|
---|
213 | 'shell32',
|
---|
214 | 'advapi32'
|
---|
215 | ])
|
---|
216 | if env['msvc']:
|
---|
217 | # Some of the LLVM C headers use the inline keyword without
|
---|
218 | # defining it.
|
---|
219 | env.Append(CPPDEFINES = [('inline', '__inline')])
|
---|
220 | # Match some of the warning options from llvm/cmake/modules/HandleLLVMOptions.cmake
|
---|
221 | env.AppendUnique(CXXFLAGS = [
|
---|
222 | '/wd4355', # 'this' : used in base member initializer list
|
---|
223 | '/wd4624', # 'derived class' : destructor could not be generated because a base class destructor is inaccessible
|
---|
224 | ])
|
---|
225 | if env['build'] in ('debug', 'checked'):
|
---|
226 | # LLVM libraries are static, build with /MT, and they
|
---|
227 | # automatically link agains LIBCMT. When we're doing a
|
---|
228 | # debug build we'll be linking against LIBCMTD, so disable
|
---|
229 | # that.
|
---|
230 | env.Append(LINKFLAGS = ['/nodefaultlib:LIBCMT'])
|
---|
231 | else:
|
---|
232 | llvm_config = os.environ.get('LLVM_CONFIG', 'llvm-config')
|
---|
233 | if not env.Detect(llvm_config):
|
---|
234 | print('scons: %s script not found' % llvm_config)
|
---|
235 | return
|
---|
236 |
|
---|
237 | llvm_version = env.backtick('%s --version' % llvm_config).rstrip()
|
---|
238 | llvm_version = distutils.version.LooseVersion(llvm_version)
|
---|
239 |
|
---|
240 | if llvm_version < distutils.version.LooseVersion(required_llvm_version):
|
---|
241 | print('scons: LLVM version %s found, but %s is required' % (llvm_version, required_llvm_version))
|
---|
242 | return
|
---|
243 |
|
---|
244 | try:
|
---|
245 | # Treat --cppflags specially to prevent NDEBUG from disabling
|
---|
246 | # assertion failures in debug builds.
|
---|
247 | cppflags = env.ParseFlags('!%s --cppflags' % llvm_config)
|
---|
248 | try:
|
---|
249 | cppflags['CPPDEFINES'].remove('NDEBUG')
|
---|
250 | except ValueError:
|
---|
251 | pass
|
---|
252 | env.MergeFlags(cppflags)
|
---|
253 |
|
---|
254 | # Match llvm --fno-rtti flag
|
---|
255 | cxxflags = env.backtick('%s --cxxflags' % llvm_config).split()
|
---|
256 | if '-fno-rtti' in cxxflags:
|
---|
257 | env.Append(CXXFLAGS = ['-fno-rtti'])
|
---|
258 |
|
---|
259 | components = ['engine', 'mcjit', 'bitwriter', 'x86asmprinter', 'mcdisassembler', 'irreader']
|
---|
260 |
|
---|
261 | env.ParseConfig('%s --libs ' % llvm_config + ' '.join(components))
|
---|
262 | env.ParseConfig('%s --ldflags' % llvm_config)
|
---|
263 | if llvm_version >= distutils.version.LooseVersion('3.5'):
|
---|
264 | env.ParseConfig('%s --system-libs' % llvm_config)
|
---|
265 | env.Append(CXXFLAGS = ['-std=c++11'])
|
---|
266 | except OSError:
|
---|
267 | print('scons: llvm-config version %s failed' % llvm_version)
|
---|
268 | return
|
---|
269 |
|
---|
270 | assert llvm_version is not None
|
---|
271 | env['llvm'] = True
|
---|
272 |
|
---|
273 | print('scons: Found LLVM version %s' % llvm_version)
|
---|
274 | env['LLVM_VERSION'] = llvm_version
|
---|
275 |
|
---|
276 | # Define HAVE_LLVM macro with the major/minor version number (e.g., 0x0206 for 2.6)
|
---|
277 | llvm_version_major = int(llvm_version.version[0])
|
---|
278 | llvm_version_minor = int(llvm_version.version[1])
|
---|
279 | llvm_version_hex = '0x%02x%02x' % (llvm_version_major, llvm_version_minor)
|
---|
280 | env.Prepend(CPPDEFINES = [('HAVE_LLVM', llvm_version_hex)])
|
---|
281 |
|
---|
282 | def exists(env):
|
---|
283 | return True
|
---|
284 |
|
---|
285 | # vim:set ts=4 sw=4 et:
|
---|