llvm.py revision 848b8605
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
40848b8605Smrgrequired_llvm_version = '3.1'
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):
53848b8605Smrg            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):
64848b8605Smrg                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:
71848b8605Smrg            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
75848b8605Smrg        llvm_config = os.path.join(llvm_dir, 'include/llvm/Config/config.h')
76848b8605Smrg        if not os.path.exists(llvm_config):
77848b8605Smrg            print 'scons: could not find %s' % llvm_config
78848b8605Smrg            return
79848b8605Smrg        llvm_version_re = re.compile(r'^#define PACKAGE_VERSION "([^"]*)"')
80848b8605Smrg        llvm_version = None
81848b8605Smrg        for line in open(llvm_config, 'rt'):
82848b8605Smrg            mo = llvm_version_re.match(line)
83848b8605Smrg            if mo:
84848b8605Smrg                llvm_version = mo.group(1)
85848b8605Smrg                llvm_version = distutils.version.LooseVersion(llvm_version)
86848b8605Smrg                break
87848b8605Smrg        if llvm_version is None:
88848b8605Smrg            print 'scons: could not determine the LLVM version from %s' % llvm_config
89848b8605Smrg            return
90848b8605Smrg        if llvm_version < distutils.version.LooseVersion(required_llvm_version):
91848b8605Smrg            print 'scons: LLVM version %s found, but %s is required' % (llvm_version, required_llvm_version)
92848b8605Smrg            return
93848b8605Smrg
94848b8605Smrg        env.Prepend(CPPPATH = [os.path.join(llvm_dir, 'include')])
95848b8605Smrg        env.AppendUnique(CPPDEFINES = [
96848b8605Smrg            '__STDC_LIMIT_MACROS',
97848b8605Smrg            '__STDC_CONSTANT_MACROS',
98848b8605Smrg            'HAVE_STDINT_H',
99848b8605Smrg        ])
100848b8605Smrg        env.Prepend(LIBPATH = [os.path.join(llvm_dir, 'lib')])
101848b8605Smrg        if llvm_version >= distutils.version.LooseVersion('3.2'):
102848b8605Smrg            # 3.2
103848b8605Smrg            env.Prepend(LIBS = [
104848b8605Smrg                'LLVMBitWriter', 'LLVMX86Disassembler', 'LLVMX86AsmParser',
105848b8605Smrg                'LLVMX86CodeGen', 'LLVMX86Desc', 'LLVMSelectionDAG',
106848b8605Smrg                'LLVMAsmPrinter', 'LLVMMCParser', 'LLVMX86AsmPrinter',
107848b8605Smrg                'LLVMX86Utils', 'LLVMX86Info', 'LLVMMCJIT', 'LLVMJIT',
108848b8605Smrg                'LLVMExecutionEngine', 'LLVMCodeGen', 'LLVMScalarOpts',
109848b8605Smrg                'LLVMInstCombine', 'LLVMTransformUtils', 'LLVMipa',
110848b8605Smrg                'LLVMAnalysis', 'LLVMTarget', 'LLVMMC', 'LLVMCore',
111848b8605Smrg                'LLVMSupport', 'LLVMRuntimeDyld', 'LLVMObject'
112848b8605Smrg            ])
113848b8605Smrg        else:
114848b8605Smrg            # 3.1
115848b8605Smrg            env.Prepend(LIBS = [
116848b8605Smrg                'LLVMBitWriter', 'LLVMX86Disassembler', 'LLVMX86AsmParser',
117848b8605Smrg                'LLVMX86CodeGen', 'LLVMX86Desc', 'LLVMSelectionDAG',
118848b8605Smrg                'LLVMAsmPrinter', 'LLVMMCParser', 'LLVMX86AsmPrinter',
119848b8605Smrg                'LLVMX86Utils', 'LLVMX86Info', 'LLVMMCJIT', 'LLVMJIT',
120848b8605Smrg                'LLVMExecutionEngine', 'LLVMCodeGen', 'LLVMScalarOpts',
121848b8605Smrg                'LLVMInstCombine', 'LLVMTransformUtils', 'LLVMipa',
122848b8605Smrg                'LLVMAnalysis', 'LLVMTarget', 'LLVMMC', 'LLVMCore',
123848b8605Smrg                'LLVMSupport'
124848b8605Smrg            ])
125848b8605Smrg        env.Append(LIBS = [
126848b8605Smrg            'imagehlp',
127848b8605Smrg            'psapi',
128848b8605Smrg            'shell32',
129848b8605Smrg            'advapi32'
130848b8605Smrg        ])
131848b8605Smrg        if env['msvc']:
132848b8605Smrg            # Some of the LLVM C headers use the inline keyword without
133848b8605Smrg            # defining it.
134848b8605Smrg            env.Append(CPPDEFINES = [('inline', '__inline')])
135848b8605Smrg            if env['build'] in ('debug', 'checked'):
136848b8605Smrg                # LLVM libraries are static, build with /MT, and they
137848b8605Smrg                # automatically link agains LIBCMT. When we're doing a
138848b8605Smrg                # debug build we'll be linking against LIBCMTD, so disable
139848b8605Smrg                # that.
140848b8605Smrg                env.Append(LINKFLAGS = ['/nodefaultlib:LIBCMT'])
141848b8605Smrg    else:
142848b8605Smrg        if not env.Detect('llvm-config'):
143848b8605Smrg            print 'scons: llvm-config script not found'
144848b8605Smrg            return
145848b8605Smrg
146848b8605Smrg        llvm_version = env.backtick('llvm-config --version').rstrip()
147848b8605Smrg        llvm_version = distutils.version.LooseVersion(llvm_version)
148848b8605Smrg
149848b8605Smrg        if llvm_version < distutils.version.LooseVersion(required_llvm_version):
150848b8605Smrg            print 'scons: LLVM version %s found, but %s is required' % (llvm_version, required_llvm_version)
151848b8605Smrg            return
152848b8605Smrg
153848b8605Smrg        try:
154848b8605Smrg            # Treat --cppflags specially to prevent NDEBUG from disabling
155848b8605Smrg            # assertion failures in debug builds.
156848b8605Smrg            cppflags = env.ParseFlags('!llvm-config --cppflags')
157848b8605Smrg            try:
158848b8605Smrg                cppflags['CPPDEFINES'].remove('NDEBUG')
159848b8605Smrg            except ValueError:
160848b8605Smrg                pass
161848b8605Smrg            env.MergeFlags(cppflags)
162848b8605Smrg
163848b8605Smrg            # Match llvm --fno-rtti flag
164848b8605Smrg            cxxflags = env.backtick('llvm-config --cxxflags').split()
165848b8605Smrg            if '-fno-rtti' in cxxflags:
166848b8605Smrg                env.Append(CXXFLAGS = ['-fno-rtti'])
167848b8605Smrg
168848b8605Smrg            components = ['engine', 'mcjit', 'bitwriter', 'x86asmprinter']
169848b8605Smrg
170848b8605Smrg            env.ParseConfig('llvm-config --libs ' + ' '.join(components))
171848b8605Smrg            env.ParseConfig('llvm-config --ldflags')
172848b8605Smrg            if llvm_version >= distutils.version.LooseVersion('3.5'):
173848b8605Smrg                env.ParseConfig('llvm-config --system-libs')
174848b8605Smrg                env.Append(CXXFLAGS = ['-std=c++11'])
175848b8605Smrg        except OSError:
176848b8605Smrg            print 'scons: llvm-config version %s failed' % llvm_version
177848b8605Smrg            return
178848b8605Smrg
179848b8605Smrg    assert llvm_version is not None
180848b8605Smrg    env['llvm'] = True
181848b8605Smrg
182848b8605Smrg    print 'scons: Found LLVM version %s' % llvm_version
183848b8605Smrg    env['LLVM_VERSION'] = llvm_version
184848b8605Smrg
185848b8605Smrg    # Define HAVE_LLVM macro with the major/minor version number (e.g., 0x0206 for 2.6)
186848b8605Smrg    llvm_version_major = int(llvm_version.version[0])
187848b8605Smrg    llvm_version_minor = int(llvm_version.version[1])
188848b8605Smrg    llvm_version_hex = '0x%02x%02x' % (llvm_version_major, llvm_version_minor)
189848b8605Smrg    env.Prepend(CPPDEFINES = [('HAVE_LLVM', llvm_version_hex)])
190848b8605Smrg
191848b8605Smrgdef exists(env):
192848b8605Smrg    return True
193848b8605Smrg
194848b8605Smrg# vim:set ts=4 sw=4 et:
195