Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. """gallium
  2.  
  3. Frontend-tool for Gallium3D architecture.
  4.  
  5. """
  6.  
  7. #
  8. # Copyright 2008 VMware, Inc.
  9. # All Rights Reserved.
  10. #
  11. # Permission is hereby granted, free of charge, to any person obtaining a
  12. # copy of this software and associated documentation files (the
  13. # "Software"), to deal in the Software without restriction, including
  14. # without limitation the rights to use, copy, modify, merge, publish,
  15. # distribute, sub license, and/or sell copies of the Software, and to
  16. # permit persons to whom the Software is furnished to do so, subject to
  17. # the following conditions:
  18. #
  19. # The above copyright notice and this permission notice (including the
  20. # next paragraph) shall be included in all copies or substantial portions
  21. # of the Software.
  22. #
  23. # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  24. # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  25. # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
  26. # IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
  27. # ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
  28. # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
  29. # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  30. #
  31.  
  32.  
  33. import distutils.version
  34. import os
  35. import os.path
  36. import re
  37. import subprocess
  38. import platform as host_platform
  39. import sys
  40. import tempfile
  41.  
  42. import SCons.Action
  43. import SCons.Builder
  44. import SCons.Scanner
  45.  
  46.  
  47. def symlink(target, source, env):
  48.     target = str(target[0])
  49.     source = str(source[0])
  50.     if os.path.islink(target) or os.path.exists(target):
  51.         os.remove(target)
  52.     os.symlink(os.path.basename(source), target)
  53.  
  54. def install(env, source, subdir):
  55.     target_dir = os.path.join(env.Dir('#.').srcnode().abspath, env['build_dir'], subdir)
  56.     return env.Install(target_dir, source)
  57.  
  58. def install_program(env, source):
  59.     return install(env, source, 'bin')
  60.  
  61. def install_shared_library(env, sources, version = ()):
  62.     targets = []
  63.     install_dir = os.path.join(env.Dir('#.').srcnode().abspath, env['build_dir'])
  64.     version = tuple(map(str, version))
  65.     if env['SHLIBSUFFIX'] == '.dll':
  66.         dlls = env.FindIxes(sources, 'SHLIBPREFIX', 'SHLIBSUFFIX')
  67.         targets += install(env, dlls, 'bin')
  68.         libs = env.FindIxes(sources, 'LIBPREFIX', 'LIBSUFFIX')
  69.         targets += install(env, libs, 'lib')
  70.     else:
  71.         for source in sources:
  72.             target_dir =  os.path.join(install_dir, 'lib')
  73.             target_name = '.'.join((str(source),) + version)
  74.             last = env.InstallAs(os.path.join(target_dir, target_name), source)
  75.             targets += last
  76.             while len(version):
  77.                 version = version[:-1]
  78.                 target_name = '.'.join((str(source),) + version)
  79.                 action = SCons.Action.Action(symlink, "  Symlinking $TARGET ...")
  80.                 last = env.Command(os.path.join(target_dir, target_name), last, action)
  81.                 targets += last
  82.     return targets
  83.  
  84.  
  85. def createInstallMethods(env):
  86.     env.AddMethod(install_program, 'InstallProgram')
  87.     env.AddMethod(install_shared_library, 'InstallSharedLibrary')
  88.  
  89.  
  90. def msvc2013_compat(env):
  91.     if env['gcc']:
  92.         env.Append(CCFLAGS = [
  93.             '-Werror=vla',
  94.             '-Werror=pointer-arith',
  95.         ])
  96.  
  97. def msvc2008_compat(env):
  98.     msvc2013_compat(env)
  99.     if env['gcc']:
  100.         env.Append(CFLAGS = [
  101.             '-Werror=declaration-after-statement',
  102.         ])
  103.  
  104. def createMSVCCompatMethods(env):
  105.     env.AddMethod(msvc2013_compat, 'MSVC2013Compat')
  106.     env.AddMethod(msvc2008_compat, 'MSVC2008Compat')
  107.  
  108.  
  109. def num_jobs():
  110.     try:
  111.         return int(os.environ['NUMBER_OF_PROCESSORS'])
  112.     except (ValueError, KeyError):
  113.         pass
  114.  
  115.     try:
  116.         return os.sysconf('SC_NPROCESSORS_ONLN')
  117.     except (ValueError, OSError, AttributeError):
  118.         pass
  119.  
  120.     try:
  121.         return int(os.popen2("sysctl -n hw.ncpu")[1].read())
  122.     except ValueError:
  123.         pass
  124.  
  125.     return 1
  126.  
  127.  
  128. def check_cc(env, cc, expr, cpp_opt = '-E'):
  129.     # Invoke C-preprocessor to determine whether the specified expression is
  130.     # true or not.
  131.  
  132.     sys.stdout.write('Checking for %s ... ' % cc)
  133.  
  134.     source = tempfile.NamedTemporaryFile(suffix='.c', delete=False)
  135.     source.write('#if !(%s)\n#error\n#endif\n' % expr)
  136.     source.close()
  137.  
  138.     pipe = SCons.Action._subproc(env, [env['CC'], cpp_opt, source.name],
  139.                                  stdin = 'devnull',
  140.                                  stderr = 'devnull',
  141.                                  stdout = 'devnull')
  142.     result = pipe.wait() == 0
  143.  
  144.     os.unlink(source.name)
  145.  
  146.     sys.stdout.write(' %s\n' % ['no', 'yes'][int(bool(result))])
  147.     return result
  148.  
  149.  
  150. def check_prog(env, prog):
  151.     """Check whether this program exists."""
  152.  
  153.     sys.stdout.write('Checking for %s ... ' % prog)
  154.  
  155.     result = env.Detect(prog)
  156.  
  157.     sys.stdout.write(' %s\n' % ['no', 'yes'][int(bool(result))])
  158.     return result
  159.  
  160.  
  161. def generate(env):
  162.     """Common environment generation code"""
  163.  
  164.     # Tell tools which machine to compile for
  165.     env['TARGET_ARCH'] = env['machine']
  166.     env['MSVS_ARCH'] = env['machine']
  167.  
  168.     # Toolchain
  169.     platform = env['platform']
  170.     env.Tool(env['toolchain'])
  171.  
  172.     # Allow override compiler and specify additional flags from environment
  173.     if os.environ.has_key('CC'):
  174.         env['CC'] = os.environ['CC']
  175.         # Update CCVERSION to match
  176.         pipe = SCons.Action._subproc(env, [env['CC'], '--version'],
  177.                                      stdin = 'devnull',
  178.                                      stderr = 'devnull',
  179.                                      stdout = subprocess.PIPE)
  180.         if pipe.wait() == 0:
  181.             line = pipe.stdout.readline()
  182.             match = re.search(r'[0-9]+(\.[0-9]+)+', line)
  183.             if match:
  184.                 env['CCVERSION'] = match.group(0)
  185.     if os.environ.has_key('CFLAGS'):
  186.         env['CCFLAGS'] += SCons.Util.CLVar(os.environ['CFLAGS'])
  187.     if os.environ.has_key('CXX'):
  188.         env['CXX'] = os.environ['CXX']
  189.     if os.environ.has_key('CXXFLAGS'):
  190.         env['CXXFLAGS'] += SCons.Util.CLVar(os.environ['CXXFLAGS'])
  191.     if os.environ.has_key('LDFLAGS'):
  192.         env['LINKFLAGS'] += SCons.Util.CLVar(os.environ['LDFLAGS'])
  193.  
  194.     # Detect gcc/clang not by executable name, but through pre-defined macros
  195.     # as autoconf does, to avoid drawing wrong conclusions when using tools
  196.     # that overrice CC/CXX like scan-build.
  197.     env['gcc'] = 0
  198.     env['clang'] = 0
  199.     env['msvc'] = 0
  200.     if host_platform.system() == 'Windows':
  201.         env['msvc'] = check_cc(env, 'MSVC', 'defined(_MSC_VER)', '/E')
  202.     if not env['msvc']:
  203.         env['gcc'] = check_cc(env, 'GCC', 'defined(__GNUC__) && !defined(__clang__)')
  204.         env['clang'] = check_cc(env, 'Clang', '__clang__')
  205.     env['suncc'] = env['platform'] == 'sunos' and os.path.basename(env['CC']) == 'cc'
  206.     env['icc'] = 'icc' == os.path.basename(env['CC'])
  207.  
  208.     if env['msvc'] and env['toolchain'] == 'default' and env['machine'] == 'x86_64':
  209.         # MSVC x64 support is broken in earlier versions of scons
  210.         env.EnsurePythonVersion(2, 0)
  211.  
  212.     # shortcuts
  213.     machine = env['machine']
  214.     platform = env['platform']
  215.     x86 = env['machine'] == 'x86'
  216.     ppc = env['machine'] == 'ppc'
  217.     gcc_compat = env['gcc'] or env['clang']
  218.     msvc = env['msvc']
  219.     suncc = env['suncc']
  220.     icc = env['icc']
  221.  
  222.     # Determine whether we are cross compiling; in particular, whether we need
  223.     # to compile code generators with a different compiler as the target code.
  224.     hosthost_platform = host_platform.system().lower()
  225.     if hosthost_platform.startswith('cygwin'):
  226.         hosthost_platform = 'cygwin'
  227.     host_machine = os.environ.get('PROCESSOR_ARCHITEW6432', os.environ.get('PROCESSOR_ARCHITECTURE', host_platform.machine()))
  228.     host_machine = {
  229.         'x86': 'x86',
  230.         'i386': 'x86',
  231.         'i486': 'x86',
  232.         'i586': 'x86',
  233.         'i686': 'x86',
  234.         'ppc' : 'ppc',
  235.         'AMD64': 'x86_64',
  236.         'x86_64': 'x86_64',
  237.     }.get(host_machine, 'generic')
  238.     env['crosscompile'] = platform != hosthost_platform
  239.     if machine == 'x86_64' and host_machine != 'x86_64':
  240.         env['crosscompile'] = True
  241.     env['hostonly'] = False
  242.  
  243.     # Backwards compatability with the debug= profile= options
  244.     if env['build'] == 'debug':
  245.         if not env['debug']:
  246.             print 'scons: warning: debug option is deprecated and will be removed eventually; use instead'
  247.             print
  248.             print ' scons build=release'
  249.             print
  250.             env['build'] = 'release'
  251.         if env['profile']:
  252.             print 'scons: warning: profile option is deprecated and will be removed eventually; use instead'
  253.             print
  254.             print ' scons build=profile'
  255.             print
  256.             env['build'] = 'profile'
  257.     if False:
  258.         # Enforce SConscripts to use the new build variable
  259.         env.popitem('debug')
  260.         env.popitem('profile')
  261.     else:
  262.         # Backwards portability with older sconscripts
  263.         if env['build'] in ('debug', 'checked'):
  264.             env['debug'] = True
  265.             env['profile'] = False
  266.         if env['build'] == 'profile':
  267.             env['debug'] = False
  268.             env['profile'] = True
  269.         if env['build'] == 'release':
  270.             env['debug'] = False
  271.             env['profile'] = False
  272.  
  273.     # Put build output in a separate dir, which depends on the current
  274.     # configuration. See also http://www.scons.org/wiki/AdvancedBuildExample
  275.     build_topdir = 'build'
  276.     build_subdir = env['platform']
  277.     if env['embedded']:
  278.         build_subdir =  'embedded-' + build_subdir
  279.     if env['machine'] != 'generic':
  280.         build_subdir += '-' + env['machine']
  281.     if env['build'] != 'release':
  282.         build_subdir += '-' +  env['build']
  283.     build_dir = os.path.join(build_topdir, build_subdir)
  284.     # Place the .sconsign file in the build dir too, to avoid issues with
  285.     # different scons versions building the same source file
  286.     env['build_dir'] = build_dir
  287.     env.SConsignFile(os.path.join(build_dir, '.sconsign'))
  288.     if 'SCONS_CACHE_DIR' in os.environ:
  289.         print 'scons: Using build cache in %s.' % (os.environ['SCONS_CACHE_DIR'],)
  290.         env.CacheDir(os.environ['SCONS_CACHE_DIR'])
  291.     env['CONFIGUREDIR'] = os.path.join(build_dir, 'conf')
  292.     env['CONFIGURELOG'] = os.path.join(os.path.abspath(build_dir), 'config.log')
  293.  
  294.     # Parallel build
  295.     if env.GetOption('num_jobs') <= 1:
  296.         env.SetOption('num_jobs', num_jobs())
  297.  
  298.     env.Decider('MD5-timestamp')
  299.     env.SetOption('max_drift', 60)
  300.  
  301.     # C preprocessor options
  302.     cppdefines = []
  303.     if env['build'] in ('debug', 'checked'):
  304.         cppdefines += ['DEBUG']
  305.     else:
  306.         cppdefines += ['NDEBUG']
  307.     if env['build'] == 'profile':
  308.         cppdefines += ['PROFILE']
  309.     if env['platform'] in ('posix', 'linux', 'freebsd', 'darwin'):
  310.         cppdefines += [
  311.             '_POSIX_SOURCE',
  312.             ('_POSIX_C_SOURCE', '199309L'),
  313.             '_SVID_SOURCE',
  314.             '_BSD_SOURCE',
  315.             '_GNU_SOURCE',
  316.             '_DEFAULT_SOURCE',
  317.             'HAVE_PTHREAD',
  318.             'HAVE_POSIX_MEMALIGN',
  319.         ]
  320.         if env['platform'] == 'darwin':
  321.             cppdefines += [
  322.                 '_DARWIN_C_SOURCE',
  323.                 'GLX_USE_APPLEGL',
  324.                 'GLX_DIRECT_RENDERING',
  325.             ]
  326.         else:
  327.             cppdefines += [
  328.                 'GLX_DIRECT_RENDERING',
  329.                 'GLX_INDIRECT_RENDERING',
  330.             ]
  331.         if env['platform'] in ('linux', 'freebsd'):
  332.             cppdefines += ['HAVE_ALIAS']
  333.         else:
  334.             cppdefines += ['GLX_ALIAS_UNSUPPORTED']
  335.  
  336.         if env['platform'] in ('linux', 'darwin'):
  337.             cppdefines += ['HAVE_XLOCALE_H']
  338.  
  339.     if env['platform'] == 'haiku':
  340.         cppdefines += [
  341.             'HAVE_PTHREAD',
  342.             'HAVE_POSIX_MEMALIGN'
  343.         ]
  344.     if platform == 'windows':
  345.         cppdefines += [
  346.             'WIN32',
  347.             '_WINDOWS',
  348.             #'_UNICODE',
  349.             #'UNICODE',
  350.             # http://msdn.microsoft.com/en-us/library/aa383745.aspx
  351.             ('_WIN32_WINNT', '0x0601'),
  352.             ('WINVER', '0x0601'),
  353.         ]
  354.         if gcc_compat:
  355.             cppdefines += [('__MSVCRT_VERSION__', '0x0700')]
  356.         if msvc:
  357.             cppdefines += [
  358.                 'VC_EXTRALEAN',
  359.                 '_USE_MATH_DEFINES',
  360.                 '_CRT_SECURE_NO_WARNINGS',
  361.                 '_CRT_SECURE_NO_DEPRECATE',
  362.                 '_SCL_SECURE_NO_WARNINGS',
  363.                 '_SCL_SECURE_NO_DEPRECATE',
  364.                 '_ALLOW_KEYWORD_MACROS',
  365.                 '_HAS_EXCEPTIONS=0', # Tell C++ STL to not use exceptions
  366.             ]
  367.         if env['build'] in ('debug', 'checked'):
  368.             cppdefines += ['_DEBUG']
  369.     if platform == 'windows':
  370.         cppdefines += ['PIPE_SUBSYSTEM_WINDOWS_USER']
  371.     if env['embedded']:
  372.         cppdefines += ['PIPE_SUBSYSTEM_EMBEDDED']
  373.     if env['texture_float']:
  374.         print 'warning: Floating-point textures enabled.'
  375.         print 'warning: Please consult docs/patents.txt with your lawyer before building Mesa.'
  376.         cppdefines += ['TEXTURE_FLOAT_ENABLED']
  377.     if gcc_compat:
  378.         ccversion = env['CCVERSION']
  379.         cppdefines += [
  380.             'HAVE___BUILTIN_EXPECT',
  381.             'HAVE___BUILTIN_FFS',
  382.             'HAVE___BUILTIN_FFSLL',
  383.             'HAVE_FUNC_ATTRIBUTE_FLATTEN',
  384.             'HAVE_FUNC_ATTRIBUTE_UNUSED',
  385.             # GCC 3.0
  386.             'HAVE_FUNC_ATTRIBUTE_FORMAT',
  387.             'HAVE_FUNC_ATTRIBUTE_PACKED',
  388.             # GCC 3.4
  389.             'HAVE___BUILTIN_CTZ',
  390.             'HAVE___BUILTIN_POPCOUNT',
  391.             'HAVE___BUILTIN_POPCOUNTLL',
  392.             'HAVE___BUILTIN_CLZ',
  393.             'HAVE___BUILTIN_CLZLL',
  394.         ]
  395.         if distutils.version.LooseVersion(ccversion) >= distutils.version.LooseVersion('4.5'):
  396.             cppdefines += ['HAVE___BUILTIN_UNREACHABLE']
  397.     env.Append(CPPDEFINES = cppdefines)
  398.  
  399.     # C compiler options
  400.     cflags = [] # C
  401.     cxxflags = [] # C++
  402.     ccflags = [] # C & C++
  403.     if gcc_compat:
  404.         ccversion = env['CCVERSION']
  405.         if env['build'] == 'debug':
  406.             ccflags += ['-O0']
  407.         elif env['gcc'] and ccversion.startswith('4.2.'):
  408.             # gcc 4.2.x optimizer is broken
  409.             print "warning: gcc 4.2.x optimizer is broken -- disabling optimizations"
  410.             ccflags += ['-O0']
  411.         else:
  412.             ccflags += ['-O3']
  413.         if env['gcc']:
  414.             # gcc's builtin memcmp is slower than glibc's
  415.             # http://gcc.gnu.org/bugzilla/show_bug.cgi?id=43052
  416.             ccflags += ['-fno-builtin-memcmp']
  417.         # Work around aliasing bugs - developers should comment this out
  418.         ccflags += ['-fno-strict-aliasing']
  419.         ccflags += ['-g']
  420.         if env['build'] in ('checked', 'profile'):
  421.             # See http://code.google.com/p/jrfonseca/wiki/Gprof2Dot#Which_options_should_I_pass_to_gcc_when_compiling_for_profiling?
  422.             ccflags += [
  423.                 '-fno-omit-frame-pointer',
  424.             ]
  425.             if env['gcc']:
  426.                 ccflags += ['-fno-optimize-sibling-calls']
  427.         if env['machine'] == 'x86':
  428.             ccflags += [
  429.                 '-m32',
  430.                 #'-march=pentium4',
  431.             ]
  432.             if platform != 'haiku':
  433.                 # NOTE: We need to ensure stack is realigned given that we
  434.                 # produce shared objects, and have no control over the stack
  435.                 # alignment policy of the application. Therefore we need
  436.                 # -mstackrealign ore -mincoming-stack-boundary=2.
  437.                 #
  438.                 # XXX: We could have SSE without -mstackrealign if we always used
  439.                 # __attribute__((force_align_arg_pointer)), but that's not
  440.                 # always the case.
  441.                 ccflags += [
  442.                     '-mstackrealign', # ensure stack is aligned
  443.                     '-msse', '-msse2', # enable SIMD intrinsics
  444.                     '-mfpmath=sse', # generate SSE floating-point arithmetic
  445.                 ]
  446.             if platform in ['windows', 'darwin']:
  447.                 # Workaround http://gcc.gnu.org/bugzilla/show_bug.cgi?id=37216
  448.                 ccflags += ['-fno-common']
  449.             if platform in ['haiku']:
  450.                 # Make optimizations compatible with Pentium or higher on Haiku
  451.                 ccflags += [
  452.                     '-mstackrealign', # ensure stack is aligned
  453.                     '-march=i586', # Haiku target is Pentium
  454.                     '-mtune=i686' # use i686 where we can
  455.                 ]
  456.         if env['machine'] == 'x86_64':
  457.             ccflags += ['-m64']
  458.             if platform == 'darwin':
  459.                 ccflags += ['-fno-common']
  460.         if env['platform'] not in ('cygwin', 'haiku', 'windows'):
  461.             ccflags += ['-fvisibility=hidden']
  462.         # See also:
  463.         # - http://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html
  464.         ccflags += [
  465.             '-Wall',
  466.             '-Wno-long-long',
  467.             '-fmessage-length=0', # be nice to Eclipse
  468.         ]
  469.         cflags += [
  470.             '-Wmissing-prototypes',
  471.             '-std=gnu99',
  472.         ]
  473.     if icc:
  474.         cflags += [
  475.             '-std=gnu99',
  476.         ]
  477.     if msvc:
  478.         # See also:
  479.         # - http://msdn.microsoft.com/en-us/library/19z1t1wy.aspx
  480.         # - cl /?
  481.         if 'MSVC_VERSION' not in env or distutils.version.LooseVersion(env['MSVC_VERSION']) < distutils.version.LooseVersion('12.0'):
  482.             # Use bundled stdbool.h and stdint.h headers for older MSVC
  483.             # versions.  stdint.h was introduced in MSVC 2010, but stdbool.h
  484.             # was only introduced in MSVC 2013.
  485.             top_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))
  486.             env.Append(CPPPATH = [os.path.join(top_dir, 'include/c99')])
  487.         if env['build'] == 'debug':
  488.             ccflags += [
  489.               '/Od', # disable optimizations
  490.               '/Oi', # enable intrinsic functions
  491.             ]
  492.         else:
  493.             if 'MSVC_VERSION' in env and distutils.version.LooseVersion(env['MSVC_VERSION']) < distutils.version.LooseVersion('11.0'):
  494.                 print 'scons: warning: Visual Studio versions prior to 2012 are known to produce incorrect code when optimizations are enabled ( https://bugs.freedesktop.org/show_bug.cgi?id=58718 )'
  495.             ccflags += [
  496.                 '/O2', # optimize for speed
  497.             ]
  498.         if env['build'] == 'release':
  499.             ccflags += [
  500.                 '/GL', # enable whole program optimization
  501.             ]
  502.         else:
  503.             ccflags += [
  504.                 '/Oy-', # disable frame pointer omission
  505.                 '/GL-', # disable whole program optimization
  506.             ]
  507.         ccflags += [
  508.             '/W3', # warning level
  509.             '/wd4018', # signed/unsigned mismatch
  510.             '/wd4056', # overflow in floating-point constant arithmetic
  511.             '/wd4244', # conversion from 'type1' to 'type2', possible loss of data
  512.             '/wd4267', # 'var' : conversion from 'size_t' to 'type', possible loss of data
  513.             '/wd4305', # truncation from 'type1' to 'type2'
  514.             '/wd4351', # new behavior: elements of array 'array' will be default initialized
  515.             '/wd4756', # overflow in constant arithmetic
  516.             '/wd4800', # forcing value to bool 'true' or 'false' (performance warning)
  517.             '/wd4996', # disable deprecated POSIX name warnings
  518.         ]
  519.         if env['machine'] == 'x86':
  520.             ccflags += [
  521.                 '/arch:SSE2', # use the SSE2 instructions (default since MSVC 2012)
  522.             ]
  523.         if platform == 'windows':
  524.             ccflags += [
  525.                 # TODO
  526.             ]
  527.         # Automatic pdb generation
  528.         # See http://scons.tigris.org/issues/show_bug.cgi?id=1656
  529.         env.EnsureSConsVersion(0, 98, 0)
  530.         env['PDB'] = '${TARGET.base}.pdb'
  531.     env.Append(CCFLAGS = ccflags)
  532.     env.Append(CFLAGS = cflags)
  533.     env.Append(CXXFLAGS = cxxflags)
  534.  
  535.     if env['platform'] == 'windows' and msvc:
  536.         # Choose the appropriate MSVC CRT
  537.         # http://msdn.microsoft.com/en-us/library/2kzt1wy3.aspx
  538.         if env['build'] in ('debug', 'checked'):
  539.             env.Append(CCFLAGS = ['/MTd'])
  540.             env.Append(SHCCFLAGS = ['/LDd'])
  541.         else:
  542.             env.Append(CCFLAGS = ['/MT'])
  543.             env.Append(SHCCFLAGS = ['/LD'])
  544.    
  545.     # Static code analysis
  546.     if env['analyze']:
  547.         if env['msvc']:
  548.             # http://msdn.microsoft.com/en-us/library/ms173498.aspx
  549.             env.Append(CCFLAGS = [
  550.                 '/analyze',
  551.                 #'/analyze:log', '${TARGET.base}.xml',
  552.                 '/wd28251', # Inconsistent annotation for function
  553.             ])
  554.         if env['clang']:
  555.             # scan-build will produce more comprehensive output
  556.             env.Append(CCFLAGS = ['--analyze'])
  557.  
  558.     # Assembler options
  559.     if gcc_compat:
  560.         if env['machine'] == 'x86':
  561.             env.Append(ASFLAGS = ['-m32'])
  562.         if env['machine'] == 'x86_64':
  563.             env.Append(ASFLAGS = ['-m64'])
  564.  
  565.     # Linker options
  566.     linkflags = []
  567.     shlinkflags = []
  568.     if gcc_compat:
  569.         if env['machine'] == 'x86':
  570.             linkflags += ['-m32']
  571.         if env['machine'] == 'x86_64':
  572.             linkflags += ['-m64']
  573.         if env['platform'] not in ('darwin'):
  574.             shlinkflags += [
  575.                 '-Wl,-Bsymbolic',
  576.             ]
  577.         # Handle circular dependencies in the libraries
  578.         if env['platform'] in ('darwin'):
  579.             pass
  580.         else:
  581.             env['_LIBFLAGS'] = '-Wl,--start-group ' + env['_LIBFLAGS'] + ' -Wl,--end-group'
  582.         if env['platform'] == 'windows':
  583.             linkflags += [
  584.                 '-Wl,--nxcompat', # DEP
  585.                 '-Wl,--dynamicbase', # ASLR
  586.             ]
  587.             # Avoid depending on gcc runtime DLLs
  588.             linkflags += ['-static-libgcc']
  589.             if 'w64' in env['CC'].split('-'):
  590.                 linkflags += ['-static-libstdc++']
  591.             # Handle the @xx symbol munging of DLL exports
  592.             shlinkflags += ['-Wl,--enable-stdcall-fixup']
  593.             #shlinkflags += ['-Wl,--kill-at']
  594.     if msvc:
  595.         if env['build'] == 'release':
  596.             # enable Link-time Code Generation
  597.             linkflags += ['/LTCG']
  598.             env.Append(ARFLAGS = ['/LTCG'])
  599.     if platform == 'windows' and msvc:
  600.         # See also:
  601.         # - http://msdn2.microsoft.com/en-us/library/y0zzbyt4.aspx
  602.         linkflags += [
  603.             '/fixed:no',
  604.             '/incremental:no',
  605.             '/dynamicbase', # ASLR
  606.             '/nxcompat', # DEP
  607.         ]
  608.     env.Append(LINKFLAGS = linkflags)
  609.     env.Append(SHLINKFLAGS = shlinkflags)
  610.  
  611.     # We have C++ in several libraries, so always link with the C++ compiler
  612.     if gcc_compat:
  613.         env['LINK'] = env['CXX']
  614.  
  615.     # Default libs
  616.     libs = []
  617.     if env['platform'] in ('darwin', 'freebsd', 'linux', 'posix', 'sunos'):
  618.         libs += ['m', 'pthread', 'dl']
  619.     if env['platform'] in ('linux',):
  620.         libs += ['rt']
  621.     if env['platform'] in ('haiku'):
  622.         libs += ['root', 'be', 'network', 'translation']
  623.     env.Append(LIBS = libs)
  624.  
  625.     # OpenMP
  626.     if env['openmp']:
  627.         if env['msvc']:
  628.             env.Append(CCFLAGS = ['/openmp'])
  629.             # When building openmp release VS2008 link.exe crashes with LNK1103 error.
  630.             # Workaround: overwrite PDB flags with empty value as it isn't required anyways
  631.             if env['build'] == 'release':
  632.                 env['PDB'] = ''
  633.         if env['gcc']:
  634.             env.Append(CCFLAGS = ['-fopenmp'])
  635.             env.Append(LIBS = ['gomp'])
  636.  
  637.     # Load tools
  638.     env.Tool('lex')
  639.     if env['msvc']:
  640.         env.Append(LEXFLAGS = [
  641.             # Force flex to use const keyword in prototypes, as relies on
  642.             # __cplusplus or __STDC__ macro to determine whether it's safe to
  643.             # use const keyword, but MSVC never defines __STDC__ unless we
  644.             # disable all MSVC extensions.
  645.             '-DYY_USE_CONST=',
  646.         ])
  647.         # Flex relies on __STDC_VERSION__>=199901L to decide when to include
  648.         # C99 inttypes.h.  We always have inttypes.h available with MSVC
  649.         # (either the one bundled with MSVC 2013, or the one we bundle
  650.         # ourselves), but we can't just define __STDC_VERSION__ without
  651.         # breaking stuff, as MSVC doesn't fully support C99.  There's also no
  652.         # way to premptively include stdint.
  653.         env.Append(CCFLAGS = ['-FIinttypes.h'])
  654.     if host_platform.system() == 'Windows':
  655.         # Prefer winflexbison binaries, as not only they are easier to install
  656.         # (no additional dependencies), but also better Windows support.
  657.         if check_prog(env, 'win_flex'):
  658.             env["LEX"] = 'win_flex'
  659.             env.Append(LEXFLAGS = [
  660.                 # windows compatibility (uses <io.h> instead of <unistd.h> and
  661.                 # _isatty, _fileno functions)
  662.                 '--wincompat'
  663.             ])
  664.  
  665.     env.Tool('yacc')
  666.     if host_platform.system() == 'Windows':
  667.         if check_prog(env, 'win_bison'):
  668.             env["YACC"] = 'win_bison'
  669.  
  670.     if env['llvm']:
  671.         env.Tool('llvm')
  672.    
  673.     # Custom builders and methods
  674.     env.Tool('custom')
  675.     createInstallMethods(env)
  676.     createMSVCCompatMethods(env)
  677.  
  678.     env.PkgCheckModules('X11', ['x11', 'xext', 'xdamage', 'xfixes', 'glproto >= 1.4.13'])
  679.     env.PkgCheckModules('XCB', ['x11-xcb', 'xcb-glx >= 1.8.1', 'xcb-dri2 >= 1.8'])
  680.     env.PkgCheckModules('XF86VIDMODE', ['xxf86vm'])
  681.     env.PkgCheckModules('DRM', ['libdrm >= 2.4.38'])
  682.     env.PkgCheckModules('UDEV', ['libudev >= 151'])
  683.  
  684.     if env['x11']:
  685.         env.Append(CPPPATH = env['X11_CPPPATH'])
  686.  
  687.     env['dri'] = env['x11'] and env['drm']
  688.  
  689.     # for debugging
  690.     #print env.Dump()
  691.  
  692.  
  693. def exists(env):
  694.     return 1
  695.