Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  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.             '__STDC_LIMIT_MACROS',
  104.             '__STDC_CONSTANT_MACROS',
  105.             'HAVE_STDINT_H',
  106.         ])
  107.         env.Prepend(LIBPATH = [os.path.join(llvm_dir, 'lib')])
  108.         # LIBS should match the output of `llvm-config --libs engine mcjit bitwriter x86asmprinter`
  109.         if llvm_version >= distutils.version.LooseVersion('3.6'):
  110.             env.Prepend(LIBS = [
  111.                 'LLVMBitWriter', 'LLVMX86Disassembler', 'LLVMX86AsmParser',
  112.                 'LLVMX86CodeGen', 'LLVMSelectionDAG', 'LLVMAsmPrinter',
  113.                 'LLVMCodeGen', 'LLVMScalarOpts', 'LLVMProfileData',
  114.                 'LLVMInstCombine', 'LLVMTransformUtils', 'LLVMipa',
  115.                 'LLVMAnalysis', 'LLVMX86Desc', 'LLVMMCDisassembler',
  116.                 'LLVMX86Info', 'LLVMX86AsmPrinter', 'LLVMX86Utils',
  117.                 'LLVMMCJIT', 'LLVMTarget', 'LLVMExecutionEngine',
  118.                 'LLVMRuntimeDyld', 'LLVMObject', 'LLVMMCParser',
  119.                 'LLVMBitReader', 'LLVMMC', 'LLVMCore', 'LLVMSupport'
  120.             ])
  121.         elif llvm_version >= distutils.version.LooseVersion('3.5'):
  122.             env.Prepend(LIBS = [
  123.                 'LLVMBitWriter', 'LLVMMCJIT', 'LLVMRuntimeDyld',
  124.                 'LLVMX86Disassembler', 'LLVMX86AsmParser', 'LLVMX86CodeGen',
  125.                 'LLVMSelectionDAG', 'LLVMAsmPrinter', 'LLVMX86Desc',
  126.                 'LLVMObject', 'LLVMMCParser', 'LLVMBitReader', 'LLVMX86Info',
  127.                 'LLVMX86AsmPrinter', 'LLVMX86Utils', 'LLVMJIT',
  128.                 'LLVMExecutionEngine', 'LLVMCodeGen', 'LLVMScalarOpts',
  129.                 'LLVMInstCombine', 'LLVMTransformUtils', 'LLVMipa',
  130.                 'LLVMAnalysis', 'LLVMTarget', 'LLVMMC', 'LLVMCore',
  131.                 'LLVMSupport'
  132.             ])
  133.         else:
  134.             env.Prepend(LIBS = [
  135.                 'LLVMBitWriter', 'LLVMX86Disassembler', 'LLVMX86AsmParser',
  136.                 'LLVMX86CodeGen', 'LLVMX86Desc', 'LLVMSelectionDAG',
  137.                 'LLVMAsmPrinter', 'LLVMMCParser', 'LLVMX86AsmPrinter',
  138.                 'LLVMX86Utils', 'LLVMX86Info', 'LLVMMCJIT', 'LLVMJIT',
  139.                 'LLVMExecutionEngine', 'LLVMCodeGen', 'LLVMScalarOpts',
  140.                 'LLVMInstCombine', 'LLVMTransformUtils', 'LLVMipa',
  141.                 'LLVMAnalysis', 'LLVMTarget', 'LLVMMC', 'LLVMCore',
  142.                 'LLVMSupport', 'LLVMRuntimeDyld', 'LLVMObject'
  143.             ])
  144.         env.Append(LIBS = [
  145.             'imagehlp',
  146.             'psapi',
  147.             'shell32',
  148.             'advapi32'
  149.         ])
  150.         if env['msvc']:
  151.             # Some of the LLVM C headers use the inline keyword without
  152.             # defining it.
  153.             env.Append(CPPDEFINES = [('inline', '__inline')])
  154.             # Match some of the warning options from llvm/cmake/modules/HandleLLVMOptions.cmake
  155.             env.AppendUnique(CXXFLAGS = [
  156.                 '/wd4355', # 'this' : used in base member initializer list
  157.                 '/wd4624', # 'derived class' : destructor could not be generated because a base class destructor is inaccessible
  158.             ])
  159.             if env['build'] in ('debug', 'checked'):
  160.                 # LLVM libraries are static, build with /MT, and they
  161.                 # automatically link agains LIBCMT. When we're doing a
  162.                 # debug build we'll be linking against LIBCMTD, so disable
  163.                 # that.
  164.                 env.Append(LINKFLAGS = ['/nodefaultlib:LIBCMT'])
  165.     else:
  166.         if not env.Detect('llvm-config'):
  167.             print 'scons: llvm-config script not found'
  168.             return
  169.  
  170.         llvm_version = env.backtick('llvm-config --version').rstrip()
  171.         llvm_version = distutils.version.LooseVersion(llvm_version)
  172.  
  173.         if llvm_version < distutils.version.LooseVersion(required_llvm_version):
  174.             print 'scons: LLVM version %s found, but %s is required' % (llvm_version, required_llvm_version)
  175.             return
  176.  
  177.         try:
  178.             # Treat --cppflags specially to prevent NDEBUG from disabling
  179.             # assertion failures in debug builds.
  180.             cppflags = env.ParseFlags('!llvm-config --cppflags')
  181.             try:
  182.                 cppflags['CPPDEFINES'].remove('NDEBUG')
  183.             except ValueError:
  184.                 pass
  185.             env.MergeFlags(cppflags)
  186.  
  187.             # Match llvm --fno-rtti flag
  188.             cxxflags = env.backtick('llvm-config --cxxflags').split()
  189.             if '-fno-rtti' in cxxflags:
  190.                 env.Append(CXXFLAGS = ['-fno-rtti'])
  191.  
  192.             components = ['engine', 'mcjit', 'bitwriter', 'x86asmprinter']
  193.  
  194.             env.ParseConfig('llvm-config --libs ' + ' '.join(components))
  195.             env.ParseConfig('llvm-config --ldflags')
  196.             if llvm_version >= distutils.version.LooseVersion('3.5'):
  197.                 env.ParseConfig('llvm-config --system-libs')
  198.                 env.Append(CXXFLAGS = ['-std=c++11'])
  199.         except OSError:
  200.             print 'scons: llvm-config version %s failed' % llvm_version
  201.             return
  202.  
  203.     assert llvm_version is not None
  204.     env['llvm'] = True
  205.  
  206.     print 'scons: Found LLVM version %s' % llvm_version
  207.     env['LLVM_VERSION'] = llvm_version
  208.  
  209.     # Define HAVE_LLVM macro with the major/minor version number (e.g., 0x0206 for 2.6)
  210.     llvm_version_major = int(llvm_version.version[0])
  211.     llvm_version_minor = int(llvm_version.version[1])
  212.     llvm_version_hex = '0x%02x%02x' % (llvm_version_major, llvm_version_minor)
  213.     env.Prepend(CPPDEFINES = [('HAVE_LLVM', llvm_version_hex)])
  214.  
  215. def exists(env):
  216.     return True
  217.  
  218. # vim:set ts=4 sw=4 et:
  219.