llvm.py revision b8e80941
1848b8605Smrg"""llvm
2848b8605Smrg
3848b8605SmrgTool-specific initialization for LLVM
4848b8605Smrg
5848b8605Smrg"""
6848b8605Smrg
7848b8605Smrg#
8848b8605Smrg# Copyright (c) 2009 VMware, Inc.
9848b8605Smrg#
10848b8605Smrg# Permission is hereby granted, free of charge, to any person obtaining
11848b8605Smrg# a copy of this software and associated documentation files (the
12848b8605Smrg# "Software"), to deal in the Software without restriction, including
13848b8605Smrg# without limitation the rights to use, copy, modify, merge, publish,
14848b8605Smrg# distribute, sublicense, and/or sell copies of the Software, and to
15848b8605Smrg# permit persons to whom the Software is furnished to do so, subject to
16848b8605Smrg# the following conditions:
17848b8605Smrg#
18848b8605Smrg# The above copyright notice and this permission notice shall be included
19848b8605Smrg# in all copies or substantial portions of the Software.
20848b8605Smrg#
21848b8605Smrg# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
22848b8605Smrg# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
23848b8605Smrg# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24848b8605Smrg# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
25848b8605Smrg# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
26848b8605Smrg# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
27848b8605Smrg# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28848b8605Smrg#
29848b8605Smrg
30848b8605Smrgimport os
31848b8605Smrgimport os.path
32848b8605Smrgimport re
33848b8605Smrgimport sys
34848b8605Smrgimport distutils.version
35848b8605Smrg
36848b8605Smrgimport SCons.Errors
37848b8605Smrgimport SCons.Util
38848b8605Smrg
39848b8605Smrg
40b8e80941Smrgrequired_llvm_version = '3.3'
41848b8605Smrg
42848b8605Smrg
43848b8605Smrgdef generate(env):
44848b8605Smrg    env['llvm'] = False
45848b8605Smrg
46848b8605Smrg    try:
47848b8605Smrg        llvm_dir = os.environ['LLVM']
48848b8605Smrg    except KeyError:
49848b8605Smrg        # Do nothing -- use the system headers/libs
50848b8605Smrg        llvm_dir = None
51848b8605Smrg    else:
52848b8605Smrg        if not os.path.isdir(llvm_dir):
53b8e80941Smrg            raise SCons.Errors.InternalError("Specified LLVM directory not found")
54848b8605Smrg
55848b8605Smrg        if env['debug']:
56848b8605Smrg            llvm_subdir = 'Debug'
57848b8605Smrg        else:
58848b8605Smrg            llvm_subdir = 'Release'
59848b8605Smrg
60848b8605Smrg        llvm_bin_dir = os.path.join(llvm_dir, llvm_subdir, 'bin')
61848b8605Smrg        if not os.path.isdir(llvm_bin_dir):
62848b8605Smrg            llvm_bin_dir = os.path.join(llvm_dir, 'bin')
63848b8605Smrg            if not os.path.isdir(llvm_bin_dir):
64b8e80941Smrg                raise SCons.Errors.InternalError("LLVM binary directory not found")
65848b8605Smrg
66848b8605Smrg        env.PrependENVPath('PATH', llvm_bin_dir)
67848b8605Smrg
68848b8605Smrg    if env['platform'] == 'windows':
69848b8605Smrg        # XXX: There is no llvm-config on Windows, so assume a standard layout
70848b8605Smrg        if llvm_dir is None:
71b8e80941Smrg            print('scons: LLVM environment variable must be specified when building for windows')
72848b8605Smrg            return
73848b8605Smrg
74848b8605Smrg        # Try to determine the LLVM version from llvm/Config/config.h
75b8e80941Smrg        llvm_config = os.path.join(llvm_dir, 'include/llvm/Config/llvm-config.h')
76848b8605Smrg        if not os.path.exists(llvm_config):
77b8e80941Smrg            print('scons: could not find %s' % llvm_config)
78848b8605Smrg            return
79b8e80941Smrg        llvm_version_major_re = re.compile(r'^#define LLVM_VERSION_MAJOR ([0-9]+)')
80b8e80941Smrg        llvm_version_minor_re = re.compile(r'^#define LLVM_VERSION_MINOR ([0-9]+)')
81848b8605Smrg        llvm_version = None
82b8e80941Smrg        llvm_version_major = None
83b8e80941Smrg        llvm_version_minor = None
84848b8605Smrg        for line in open(llvm_config, 'rt'):
85b8e80941Smrg            mo = llvm_version_major_re.match(line)
86848b8605Smrg            if mo:
87b8e80941Smrg                llvm_version_major = mo.group(1)
88b8e80941Smrg            mo = llvm_version_minor_re.match(line)
89b8e80941Smrg            if mo:
90b8e80941Smrg                llvm_version_minor = mo.group(1)
91b8e80941Smrg        if llvm_version_major is not None and llvm_version_minor is not None:
92b8e80941Smrg            llvm_version = distutils.version.LooseVersion('%s.%s' % (llvm_version_major, llvm_version_minor))
93b8e80941Smrg
94848b8605Smrg        if llvm_version is None:
95b8e80941Smrg            print('scons: could not determine the LLVM version from %s' % llvm_config)
96848b8605Smrg            return
97848b8605Smrg        if llvm_version < distutils.version.LooseVersion(required_llvm_version):
98b8e80941Smrg            print('scons: LLVM version %s found, but %s is required' % (llvm_version, required_llvm_version))
99848b8605Smrg            return
100848b8605Smrg
101848b8605Smrg        env.Prepend(CPPPATH = [os.path.join(llvm_dir, 'include')])
102848b8605Smrg        env.Prepend(LIBPATH = [os.path.join(llvm_dir, 'lib')])
103b8e80941Smrg        # LIBS should match the output of `llvm-config --libs engine mcjit bitwriter x86asmprinter irreader`
104b8e80941Smrg        if llvm_version >= distutils.version.LooseVersion('5.0'):
105b8e80941Smrg            env.Prepend(LIBS = [
106b8e80941Smrg                'LLVMX86Disassembler', 'LLVMX86AsmParser',
107b8e80941Smrg                'LLVMX86CodeGen', 'LLVMSelectionDAG', 'LLVMAsmPrinter',
108b8e80941Smrg                'LLVMDebugInfoCodeView', 'LLVMCodeGen',
109b8e80941Smrg                'LLVMScalarOpts', 'LLVMInstCombine',
110b8e80941Smrg                'LLVMTransformUtils',
111b8e80941Smrg                'LLVMBitWriter', 'LLVMX86Desc',
112b8e80941Smrg                'LLVMMCDisassembler', 'LLVMX86Info',
113b8e80941Smrg                'LLVMX86AsmPrinter', 'LLVMX86Utils',
114b8e80941Smrg                'LLVMMCJIT', 'LLVMExecutionEngine', 'LLVMTarget',
115b8e80941Smrg                'LLVMAnalysis', 'LLVMProfileData',
116b8e80941Smrg                'LLVMRuntimeDyld', 'LLVMObject', 'LLVMMCParser',
117b8e80941Smrg                'LLVMBitReader', 'LLVMMC', 'LLVMCore',
118b8e80941Smrg                'LLVMSupport',
119b8e80941Smrg                'LLVMIRReader', 'LLVMAsmParser',
120b8e80941Smrg                'LLVMDemangle', 'LLVMGlobalISel', 'LLVMDebugInfoMSF',
121b8e80941Smrg                'LLVMBinaryFormat',
122b8e80941Smrg            ])
123b8e80941Smrg            if env['platform'] == 'windows' and env['crosscompile']:
124b8e80941Smrg                # LLVM 5.0 requires MinGW w/ pthreads due to use of std::thread and friends.
125b8e80941Smrg                assert env['gcc']
126b8e80941Smrg                env['CXX'] = env['CXX'] + '-posix'
127b8e80941Smrg        elif llvm_version >= distutils.version.LooseVersion('4.0'):
128b8e80941Smrg            env.Prepend(LIBS = [
129b8e80941Smrg                'LLVMX86Disassembler', 'LLVMX86AsmParser',
130b8e80941Smrg                'LLVMX86CodeGen', 'LLVMSelectionDAG', 'LLVMAsmPrinter',
131b8e80941Smrg                'LLVMDebugInfoCodeView', 'LLVMCodeGen',
132b8e80941Smrg                'LLVMScalarOpts', 'LLVMInstCombine',
133b8e80941Smrg                'LLVMTransformUtils',
134b8e80941Smrg                'LLVMBitWriter', 'LLVMX86Desc',
135b8e80941Smrg                'LLVMMCDisassembler', 'LLVMX86Info',
136b8e80941Smrg                'LLVMX86AsmPrinter', 'LLVMX86Utils',
137b8e80941Smrg                'LLVMMCJIT', 'LLVMExecutionEngine', 'LLVMTarget',
138b8e80941Smrg                'LLVMAnalysis', 'LLVMProfileData',
139b8e80941Smrg                'LLVMRuntimeDyld', 'LLVMObject', 'LLVMMCParser',
140b8e80941Smrg                'LLVMBitReader', 'LLVMMC', 'LLVMCore',
141b8e80941Smrg                'LLVMSupport',
142b8e80941Smrg                'LLVMIRReader', 'LLVMAsmParser',
143b8e80941Smrg                'LLVMDemangle', 'LLVMGlobalISel', 'LLVMDebugInfoMSF',
144b8e80941Smrg            ])
145b8e80941Smrg        elif llvm_version >= distutils.version.LooseVersion('3.9'):
146b8e80941Smrg            env.Prepend(LIBS = [
147b8e80941Smrg                'LLVMX86Disassembler', 'LLVMX86AsmParser',
148b8e80941Smrg                'LLVMX86CodeGen', 'LLVMSelectionDAG', 'LLVMAsmPrinter',
149b8e80941Smrg                'LLVMDebugInfoCodeView', 'LLVMCodeGen',
150b8e80941Smrg                'LLVMScalarOpts', 'LLVMInstCombine',
151b8e80941Smrg                'LLVMInstrumentation', 'LLVMTransformUtils',
152b8e80941Smrg                'LLVMBitWriter', 'LLVMX86Desc',
153b8e80941Smrg                'LLVMMCDisassembler', 'LLVMX86Info',
154b8e80941Smrg                'LLVMX86AsmPrinter', 'LLVMX86Utils',
155b8e80941Smrg                'LLVMMCJIT', 'LLVMExecutionEngine', 'LLVMTarget',
156b8e80941Smrg                'LLVMAnalysis', 'LLVMProfileData',
157b8e80941Smrg                'LLVMRuntimeDyld', 'LLVMObject', 'LLVMMCParser',
158b8e80941Smrg                'LLVMBitReader', 'LLVMMC', 'LLVMCore',
159b8e80941Smrg                'LLVMSupport',
160b8e80941Smrg                'LLVMIRReader', 'LLVMASMParser'
161b8e80941Smrg            ])
162b8e80941Smrg        elif llvm_version >= distutils.version.LooseVersion('3.7'):
163848b8605Smrg            env.Prepend(LIBS = [
164848b8605Smrg                'LLVMBitWriter', 'LLVMX86Disassembler', 'LLVMX86AsmParser',
165b8e80941Smrg                'LLVMX86CodeGen', 'LLVMSelectionDAG', 'LLVMAsmPrinter',
166b8e80941Smrg                'LLVMCodeGen', 'LLVMScalarOpts', 'LLVMProfileData',
167b8e80941Smrg                'LLVMInstCombine', 'LLVMInstrumentation', 'LLVMTransformUtils', 'LLVMipa',
168b8e80941Smrg                'LLVMAnalysis', 'LLVMX86Desc', 'LLVMMCDisassembler',
169b8e80941Smrg                'LLVMX86Info', 'LLVMX86AsmPrinter', 'LLVMX86Utils',
170b8e80941Smrg                'LLVMMCJIT', 'LLVMTarget', 'LLVMExecutionEngine',
171b8e80941Smrg                'LLVMRuntimeDyld', 'LLVMObject', 'LLVMMCParser',
172b8e80941Smrg                'LLVMBitReader', 'LLVMMC', 'LLVMCore', 'LLVMSupport'
173b8e80941Smrg            ])
174b8e80941Smrg        elif llvm_version >= distutils.version.LooseVersion('3.6'):
175b8e80941Smrg            env.Prepend(LIBS = [
176b8e80941Smrg                'LLVMBitWriter', 'LLVMX86Disassembler', 'LLVMX86AsmParser',
177b8e80941Smrg                'LLVMX86CodeGen', 'LLVMSelectionDAG', 'LLVMAsmPrinter',
178b8e80941Smrg                'LLVMCodeGen', 'LLVMScalarOpts', 'LLVMProfileData',
179b8e80941Smrg                'LLVMInstCombine', 'LLVMTransformUtils', 'LLVMipa',
180b8e80941Smrg                'LLVMAnalysis', 'LLVMX86Desc', 'LLVMMCDisassembler',
181b8e80941Smrg                'LLVMX86Info', 'LLVMX86AsmPrinter', 'LLVMX86Utils',
182b8e80941Smrg                'LLVMMCJIT', 'LLVMTarget', 'LLVMExecutionEngine',
183b8e80941Smrg                'LLVMRuntimeDyld', 'LLVMObject', 'LLVMMCParser',
184b8e80941Smrg                'LLVMBitReader', 'LLVMMC', 'LLVMCore', 'LLVMSupport'
185b8e80941Smrg            ])
186b8e80941Smrg        elif llvm_version >= distutils.version.LooseVersion('3.5'):
187b8e80941Smrg            env.Prepend(LIBS = [
188b8e80941Smrg                'LLVMMCDisassembler',
189b8e80941Smrg                'LLVMBitWriter', 'LLVMMCJIT', 'LLVMRuntimeDyld',
190b8e80941Smrg                'LLVMX86Disassembler', 'LLVMX86AsmParser', 'LLVMX86CodeGen',
191b8e80941Smrg                'LLVMSelectionDAG', 'LLVMAsmPrinter', 'LLVMX86Desc',
192b8e80941Smrg                'LLVMObject', 'LLVMMCParser', 'LLVMBitReader', 'LLVMX86Info',
193b8e80941Smrg                'LLVMX86AsmPrinter', 'LLVMX86Utils', 'LLVMJIT',
194848b8605Smrg                'LLVMExecutionEngine', 'LLVMCodeGen', 'LLVMScalarOpts',
195848b8605Smrg                'LLVMInstCombine', 'LLVMTransformUtils', 'LLVMipa',
196848b8605Smrg                'LLVMAnalysis', 'LLVMTarget', 'LLVMMC', 'LLVMCore',
197b8e80941Smrg                'LLVMSupport'
198848b8605Smrg            ])
199848b8605Smrg        else:
200848b8605Smrg            env.Prepend(LIBS = [
201b8e80941Smrg                'LLVMMCDisassembler',
202848b8605Smrg                'LLVMBitWriter', 'LLVMX86Disassembler', 'LLVMX86AsmParser',
203848b8605Smrg                'LLVMX86CodeGen', 'LLVMX86Desc', 'LLVMSelectionDAG',
204848b8605Smrg                'LLVMAsmPrinter', 'LLVMMCParser', 'LLVMX86AsmPrinter',
205848b8605Smrg                'LLVMX86Utils', 'LLVMX86Info', 'LLVMMCJIT', 'LLVMJIT',
206848b8605Smrg                'LLVMExecutionEngine', 'LLVMCodeGen', 'LLVMScalarOpts',
207848b8605Smrg                'LLVMInstCombine', 'LLVMTransformUtils', 'LLVMipa',
208848b8605Smrg                'LLVMAnalysis', 'LLVMTarget', 'LLVMMC', 'LLVMCore',
209b8e80941Smrg                'LLVMSupport', 'LLVMRuntimeDyld', 'LLVMObject'
210848b8605Smrg            ])
211848b8605Smrg        env.Append(LIBS = [
212848b8605Smrg            'imagehlp',
213848b8605Smrg            'psapi',
214848b8605Smrg            'shell32',
215b8e80941Smrg            'advapi32',
216b8e80941Smrg            'ole32',
217b8e80941Smrg            'uuid',
218848b8605Smrg        ])
219b8e80941Smrg
220848b8605Smrg        if env['msvc']:
221848b8605Smrg            # Some of the LLVM C headers use the inline keyword without
222848b8605Smrg            # defining it.
223848b8605Smrg            env.Append(CPPDEFINES = [('inline', '__inline')])
224b8e80941Smrg            # Match some of the warning options from llvm/cmake/modules/HandleLLVMOptions.cmake
225b8e80941Smrg            env.AppendUnique(CXXFLAGS = [
226b8e80941Smrg                '/wd4355', # 'this' : used in base member initializer list
227b8e80941Smrg                '/wd4624', # 'derived class' : destructor could not be generated because a base class destructor is inaccessible
228b8e80941Smrg            ])
229848b8605Smrg            if env['build'] in ('debug', 'checked'):
230848b8605Smrg                # LLVM libraries are static, build with /MT, and they
231848b8605Smrg                # automatically link agains LIBCMT. When we're doing a
232848b8605Smrg                # debug build we'll be linking against LIBCMTD, so disable
233848b8605Smrg                # that.
234848b8605Smrg                env.Append(LINKFLAGS = ['/nodefaultlib:LIBCMT'])
235848b8605Smrg    else:
236b8e80941Smrg        llvm_config = os.environ.get('LLVM_CONFIG', 'llvm-config')
237b8e80941Smrg        if not env.Detect(llvm_config):
238b8e80941Smrg            print('scons: %s script not found' % llvm_config)
239848b8605Smrg            return
240848b8605Smrg
241b8e80941Smrg        llvm_version = env.backtick('%s --version' % llvm_config).rstrip()
242848b8605Smrg        llvm_version = distutils.version.LooseVersion(llvm_version)
243848b8605Smrg
244848b8605Smrg        if llvm_version < distutils.version.LooseVersion(required_llvm_version):
245b8e80941Smrg            print('scons: LLVM version %s found, but %s is required' % (llvm_version, required_llvm_version))
246848b8605Smrg            return
247848b8605Smrg
248848b8605Smrg        try:
249848b8605Smrg            # Treat --cppflags specially to prevent NDEBUG from disabling
250848b8605Smrg            # assertion failures in debug builds.
251b8e80941Smrg            cppflags = env.ParseFlags('!%s --cppflags' % llvm_config)
252848b8605Smrg            try:
253848b8605Smrg                cppflags['CPPDEFINES'].remove('NDEBUG')
254848b8605Smrg            except ValueError:
255848b8605Smrg                pass
256848b8605Smrg            env.MergeFlags(cppflags)
257848b8605Smrg
258848b8605Smrg            # Match llvm --fno-rtti flag
259b8e80941Smrg            cxxflags = env.backtick('%s --cxxflags' % llvm_config).split()
260848b8605Smrg            if '-fno-rtti' in cxxflags:
261848b8605Smrg                env.Append(CXXFLAGS = ['-fno-rtti'])
262848b8605Smrg
263b8e80941Smrg            components = ['engine', 'mcjit', 'bitwriter', 'x86asmprinter', 'mcdisassembler', 'irreader']
264848b8605Smrg
265b8e80941Smrg            env.ParseConfig('%s --libs ' % llvm_config + ' '.join(components))
266b8e80941Smrg            env.ParseConfig('%s --ldflags' % llvm_config)
267848b8605Smrg            if llvm_version >= distutils.version.LooseVersion('3.5'):
268b8e80941Smrg                env.ParseConfig('%s --system-libs' % llvm_config)
269848b8605Smrg                env.Append(CXXFLAGS = ['-std=c++11'])
270848b8605Smrg        except OSError:
271b8e80941Smrg            print('scons: llvm-config version %s failed' % llvm_version)
272848b8605Smrg            return
273848b8605Smrg
274848b8605Smrg    assert llvm_version is not None
275848b8605Smrg    env['llvm'] = True
276848b8605Smrg
277b8e80941Smrg    print('scons: Found LLVM version %s' % llvm_version)
278848b8605Smrg    env['LLVM_VERSION'] = llvm_version
279848b8605Smrg
280848b8605Smrg    # Define HAVE_LLVM macro with the major/minor version number (e.g., 0x0206 for 2.6)
281848b8605Smrg    llvm_version_major = int(llvm_version.version[0])
282848b8605Smrg    llvm_version_minor = int(llvm_version.version[1])
283848b8605Smrg    llvm_version_hex = '0x%02x%02x' % (llvm_version_major, llvm_version_minor)
284848b8605Smrg    env.Prepend(CPPDEFINES = [('HAVE_LLVM', llvm_version_hex)])
285848b8605Smrg
286848b8605Smrgdef exists(env):
287848b8605Smrg    return True
288848b8605Smrg
289848b8605Smrg# vim:set ts=4 sw=4 et:
290