Merge branch 'gallium-polygon-stipple'
[mesa.git] / scons / llvm.py
index 73e9310f71b44ec0cf45a0f0bc199ad92f1b3089..66f972df5fbfcc396fcdd1c92e22f7c2ea583f1d 100644 (file)
@@ -29,13 +29,17 @@ Tool-specific initialization for LLVM
 
 import os
 import os.path
+import re
 import sys
+import distutils.version
 
 import SCons.Errors
 import SCons.Util
 
 
 def generate(env):
+    env['llvm'] = False
+
     try:
         llvm_dir = os.environ['LLVM']
     except KeyError:
@@ -58,60 +62,111 @@ def generate(env):
 
         env.PrependENVPath('PATH', llvm_bin_dir)
 
-    if env['msvc']:
+    if env['platform'] == 'windows':
         # XXX: There is no llvm-config on Windows, so assume a standard layout
-        if llvm_dir is not None:
-            env.Prepend(CPPPATH = [os.path.join(llvm_dir, 'include')])
-            env.Prepend(LIBPATH = [os.path.join(llvm_dir, 'lib')])
+        if llvm_dir is None:
+            print 'scons: LLVM environment variable must be specified when building for windows'
+            return
+
+        # Try to determine the LLVM version from llvm/Config/config.h
+        llvm_config = os.path.join(llvm_dir, 'include/llvm/Config/config.h')
+        if not os.path.exists(llvm_config):
+            print 'scons: could not find %s' % llvm_config
+            return
+        llvm_version_re = re.compile(r'^#define PACKAGE_VERSION "([^"]*)"')
+        llvm_version = None
+        for line in open(llvm_config, 'rt'):
+            mo = llvm_version_re.match(line)
+            if mo:
+                llvm_version = mo.group(1)
+                llvm_version = distutils.version.LooseVersion(llvm_version)
+                break
+        if llvm_version is None:
+            print 'scons: could not determine the LLVM version from %s' % llvm_config
+            return
+
+        env.Prepend(CPPPATH = [os.path.join(llvm_dir, 'include')])
+        env.AppendUnique(CPPDEFINES = [
+            '__STDC_LIMIT_MACROS', 
+            '__STDC_CONSTANT_MACROS',
+            'HAVE_STDINT_H',
+        ])
+        env.Prepend(LIBPATH = [os.path.join(llvm_dir, 'lib')])
+        if llvm_version >= distutils.version.LooseVersion('2.7'):
+            # 2.7
             env.Prepend(LIBS = [
-                'LLVMBitWriter',
-                'LLVMCore',
-                'LLVMSupport',
-                'LLVMSystem',
-                'LLVMSupport',
+                'LLVMLinker', 'LLVMipo', 'LLVMInterpreter',
+                'LLVMInstrumentation', 'LLVMJIT', 'LLVMExecutionEngine',
+                'LLVMBitWriter', 'LLVMX86Disassembler', 'LLVMX86AsmParser',
+                'LLVMMCParser', 'LLVMX86AsmPrinter', 'LLVMX86CodeGen',
+                'LLVMSelectionDAG', 'LLVMX86Info', 'LLVMAsmPrinter',
+                'LLVMCodeGen', 'LLVMScalarOpts', 'LLVMInstCombine',
+                'LLVMTransformUtils', 'LLVMipa', 'LLVMAsmParser',
+                'LLVMArchive', 'LLVMBitReader', 'LLVMAnalysis', 'LLVMTarget',
+                'LLVMMC', 'LLVMCore', 'LLVMSupport', 'LLVMSystem',
+            ])
+        else:
+            # 2.6
+            env.Prepend(LIBS = [
+                'LLVMX86AsmParser', 'LLVMX86AsmPrinter', 'LLVMX86CodeGen',
+                'LLVMX86Info', 'LLVMLinker', 'LLVMipo', 'LLVMInterpreter',
+                'LLVMInstrumentation', 'LLVMJIT', 'LLVMExecutionEngine',
+                'LLVMDebugger', 'LLVMBitWriter', 'LLVMAsmParser',
+                'LLVMArchive', 'LLVMBitReader', 'LLVMSelectionDAG',
+                'LLVMAsmPrinter', 'LLVMCodeGen', 'LLVMScalarOpts',
+                'LLVMTransformUtils', 'LLVMipa', 'LLVMAnalysis',
+                'LLVMTarget', 'LLVMMC', 'LLVMCore', 'LLVMSupport',
                 'LLVMSystem',
-                'LLVMCore',
-                'LLVMCodeGen',
-                'LLVMSelectionDAG',
-                'LLVMAsmPrinter',
-                'LLVMBitReader',
-                'LLVMBitWriter',
-                'LLVMTransformUtils',
-                'LLVMInstrumentation',
-                'LLVMScalarOpts',
-                'LLVMipo',
-                'LLVMHello',
-                'LLVMLinker',
-                'LLVMAnalysis',
-                'LLVMipa',
-                'LLVMX86CodeGen',
-                'LLVMX86AsmPrinter',
-                'LLVMExecutionEngine',
-                'LLVMInterpreter',
-                'LLVMJIT',
-                'LLVMTarget',
-                'LLVMAsmParser',
-                'LLVMDebugger',
-                'LLVMArchive',
-                'imagehlp',
-                'psapi',
             ])
-            env['LLVM_VERSION'] = '2.5'
-        return
-    elif env.Detect('llvm-config'):
-        version = env.backtick('llvm-config --version').rstrip()
+        env.Append(LIBS = [
+            'imagehlp',
+            'psapi',
+        ])
+        if env['msvc']:
+            # Some of the LLVM C headers use the inline keyword without
+            # defining it.
+            env.Append(CPPDEFINES = [('inline', '__inline')])
+            if env['build'] in ('debug', 'checked'):
+                # LLVM libraries are static, build with /MT, and they
+                # automatically link agains LIBCMT. When we're doing a
+                # debug build we'll be linking against LIBCMTD, so disable
+                # that.
+                env.Append(LINKFLAGS = ['/nodefaultlib:LIBCMT'])
+    else:
+        if not env.Detect('llvm-config'):
+            print 'scons: llvm-config script not found' % llvm_version
+            return
+
+        llvm_version = env.backtick('llvm-config --version').rstrip()
+        llvm_version = distutils.version.LooseVersion(llvm_version)
 
         try:
-            env.ParseConfig('llvm-config --cppflags')
-            env.ParseConfig('llvm-config --libs jit interpreter nativecodegen bitwriter')
+            # Treat --cppflags specially to prevent NDEBUG from disabling
+            # assertion failures in debug builds.
+            cppflags = env.ParseFlags('!llvm-config --cppflags')
+            try:
+                cppflags['CPPDEFINES'].remove('NDEBUG')
+            except ValueError:
+                pass
+            env.MergeFlags(cppflags)
+
+            env.ParseConfig('llvm-config --libs')
             env.ParseConfig('llvm-config --ldflags')
         except OSError:
-            print 'llvm-config version %s failed' % version
-        else:
-            if env['platform'] == 'windows':
-                env.Append(LIBS = ['imagehlp', 'psapi'])
-            env['LINK'] = env['CXX']
-            env['LLVM_VERSION'] = version
+            print 'scons: llvm-config version %s failed' % llvm_version
+            return
+
+    assert llvm_version is not None
+    env['llvm'] = True
+
+    print 'scons: Found LLVM version %s' % llvm_version
+    env['LLVM_VERSION'] = llvm_version
+
+    # Define HAVE_LLVM macro with the major/minor version number (e.g., 0x0206 for 2.6)
+    llvm_version_major = int(llvm_version.version[0])
+    llvm_version_minor = int(llvm_version.version[1])
+    llvm_version_hex = '0x%02x%02x' % (llvm_version_major, llvm_version_minor)
+    env.Prepend(CPPDEFINES = [('HAVE_LLVM', llvm_version_hex)])
 
 def exists(env):
     return True