scons: Detect and support LLVM 2.7.
authorJosé Fonseca <jfonseca@vmware.com>
Fri, 5 Mar 2010 15:07:50 +0000 (15:07 +0000)
committerJosé Fonseca <jfonseca@vmware.com>
Sat, 6 Mar 2010 09:34:31 +0000 (09:34 +0000)
scons/llvm.py

index 37c503ec986dd959104dae30392979bef7c3b8fc..88a63854bc6d1fffa470bb55049bb1b6f1e6f7e1 100644 (file)
@@ -29,7 +29,9 @@ Tool-specific initialization for LLVM
 
 import os
 import os.path
+import re
 import sys
+import distutils.version
 
 import SCons.Errors
 import SCons.Util
@@ -60,71 +62,97 @@ def generate(env):
 
     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.AppendUnique(CPPDEFINES = [
-                '__STDC_LIMIT_MACROS', 
-                '__STDC_CONSTANT_MACROS',
-                'HAVE_STDINT_H',
+        if llvm_dir is None:
+            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)
+                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 = [
+                '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',
             ])
-            env.Prepend(LIBPATH = [os.path.join(llvm_dir, 'lib')])
+        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',
+                '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',
-                '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['debug']:
-                    # 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'])
-            env['LLVM_VERSION'] = '2.6'
-        return
+        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['debug']:
+                # 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'])
     elif env.Detect('llvm-config'):
-        version = env.backtick('llvm-config --version').rstrip()
+        llvm_version = env.backtick('llvm-config --version').rstrip()
 
         try:
             env.ParseConfig('llvm-config --cppflags')
             env.ParseConfig('llvm-config --libs jit interpreter nativecodegen bitwriter')
             env.ParseConfig('llvm-config --ldflags')
         except OSError:
-            print 'llvm-config version %s failed' % version
+            print 'llvm-config version %s failed' % llvm_version
         else:
-            if env['platform'] == 'windows':
-                env.Append(LIBS = ['imagehlp', 'psapi'])
             env['LINK'] = env['CXX']
-            env['LLVM_VERSION'] = version
+    else:
+        return
+
+    assert llvm_version is not None
+
+    print 'scons: Found LLVM version %s' % llvm_version
+    llvm_version = distutils.version.LooseVersion(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