Autodetect no-strict-aliasing, propagate toolchain option to SCons
authorBert Belder <bertbelder@gmail.com>
Thu, 17 Feb 2011 02:15:24 +0000 (03:15 +0100)
committerRyan Dahl <ry@tinyclouds.org>
Thu, 24 Feb 2011 21:47:14 +0000 (13:47 -0800)
BUG=v8:884

deps/v8/SConstruct
deps/v8/src/SConscript

index 84707e9..6b155e4 100644 (file)
@@ -27,6 +27,7 @@
 
 import platform
 import re
+import subprocess
 import sys
 import os
 from os.path import join, dirname, abspath
@@ -142,6 +143,9 @@ LIBRARY_FLAGS = {
       # Use visibility=default to disable this.
       'CXXFLAGS':     ['-fvisibility=hidden']
     },
+    'strictaliasing:off': {
+      'CCFLAGS':      ['-fno-strict-aliasing']
+    },
     'mode:debug': {
       'CCFLAGS':      ['-g', '-O0'],
       'CPPDEFINES':   ['ENABLE_DISASSEMBLER', 'DEBUG'],
@@ -652,8 +656,16 @@ def Abort(message):
   sys.exit(1)
 
 
-def GuessToolchain(os):
-  tools = Environment()['TOOLS']
+def GuessOS(env):
+  return utils.GuessOS()
+
+
+def GuessArch(env):
+  return utils.GuessArchitecture()
+
+
+def GuessToolchain(env):
+  tools = env['TOOLS']
   if 'gcc' in tools:
     return 'gcc'
   elif 'msvc' in tools:
@@ -662,7 +674,9 @@ def GuessToolchain(os):
     return None
 
 
-def GuessVisibility(os, toolchain):
+def GuessVisibility(env):
+  os = env['os']
+  toolchain = env['toolchain'];
   if (os == 'win32' or os == 'cygwin') and toolchain == 'gcc':
     # MinGW / Cygwin can't do it.
     return 'default'
@@ -672,27 +686,35 @@ def GuessVisibility(os, toolchain):
     return 'hidden'
 
 
-OS_GUESS = utils.GuessOS()
-TOOLCHAIN_GUESS = GuessToolchain(OS_GUESS)
-ARCH_GUESS = utils.GuessArchitecture()
-VISIBILITY_GUESS = GuessVisibility(OS_GUESS, TOOLCHAIN_GUESS)
+def GuessStrictAliasing(env):
+  # There seems to be a problem with gcc 4.5.x
+  # see http://code.google.com/p/v8/issues/detail?id=884
+  # it can be worked around by disabling strict aliasing
+  toolchain = env['toolchain'];
+  if toolchain == 'gcc':
+    env = Environment(tools=['gcc'])
+    version = subprocess.Popen([env['CC'], '-dumpversion'],
+        stdout=subprocess.PIPE).communicate()[0]
+    if version.find('4.5.') == 0:
+      return 'off'
+  return 'default'
 
 
 SIMPLE_OPTIONS = {
   'toolchain': {
     'values': ['gcc', 'msvc'],
-    'default': TOOLCHAIN_GUESS,
-    'help': 'the toolchain to use (%s)' % TOOLCHAIN_GUESS
+    'guess': GuessToolchain,
+    'help': 'the toolchain to use'
   },
   'os': {
     'values': ['freebsd', 'linux', 'macos', 'win32', 'android', 'openbsd', 'solaris', 'cygwin'],
-    'default': OS_GUESS,
-    'help': 'the os to build for (%s)' % OS_GUESS
+    'guess': GuessOS,
+    'help': 'the os to build for'
   },
   'arch': {
     'values':['arm', 'ia32', 'x64', 'mips'],
-    'default': ARCH_GUESS,
-    'help': 'the architecture to build for (%s)' % ARCH_GUESS
+    'guess': GuessArch,
+    'help': 'the architecture to build for'
   },
   'regexp': {
     'values': ['native', 'interpreted'],
@@ -801,8 +823,15 @@ SIMPLE_OPTIONS = {
   },
   'visibility': {
     'values': ['default', 'hidden'],
-    'default': VISIBILITY_GUESS,
-    'help': 'shared library symbol visibility (%s)' % VISIBILITY_GUESS
+    'guess': GuessVisibility,
+    'depends': ['os', 'toolchain'],
+    'help': 'shared library symbol visibility'
+  },
+  'strictaliasing': {
+    'values': ['default', 'off'],
+    'guess': GuessStrictAliasing,
+    'depends': ['toolchain'],
+    'help': 'assume strict aliasing while optimizing'
   },
   'pgo': {
     'values': ['off', 'instrument', 'optimize'],
@@ -812,6 +841,26 @@ SIMPLE_OPTIONS = {
 }
 
 
+def AddOption(result, name, option):
+  if 'guess' in option:
+    # Option has a guess function
+    guess = option.get('guess')
+    guess_env = Environment(options=result)
+    # Check if all options that the guess function depends on are set
+    if 'depends' in option:
+      for dependency in option.get('depends'):
+        if not dependency in guess_env:
+          return False
+    default = guess(guess_env)
+  else:
+    # Option has a fixed default
+    default = option.get('default')
+
+  help = '%s (%s)' % (option.get('help'), ", ".join(option['values']))
+  result.Add(name, help, default)
+  return True
+
+
 def GetOptions():
   result = Options()
   result.Add('mode', 'compilation mode (debug, release)', 'release')
@@ -819,12 +868,28 @@ def GetOptions():
   result.Add('cache', 'directory to use for scons build cache', '')
   result.Add('env', 'override environment settings (NAME0:value0,NAME1:value1,...)', '')
   result.Add('importenv', 'import environment settings (NAME0,NAME1,...)', '')
-  for (name, option) in SIMPLE_OPTIONS.iteritems():
-    help = '%s (%s)' % (name, ", ".join(option['values']))
-    result.Add(name, help, option.get('default'))
+  options = SIMPLE_OPTIONS
+  while len(options):
+    postpone = {}
+    for (name, option) in options.iteritems():
+      if not AddOption(result, name, option):
+        postpone[name] = option
+    options = postpone
   return result
 
 
+def GetTools(opts):
+  env = Environment(options=opts)
+  os = env['os']
+  toolchain = env['toolchain']
+  if os == 'win32' and toolchain == 'gcc':
+    return ['mingw']
+  elif os == 'win32' and toolchain == 'msvc':
+    return ['msvc', 'mslink', 'mslib', 'msvs']
+  else:
+    return ['default']
+
+
 def GetVersionComponents():
   MAJOR_VERSION_PATTERN = re.compile(r"#define\s+MAJOR_VERSION\s+(.*)")
   MINOR_VERSION_PATTERN = re.compile(r"#define\s+MINOR_VERSION\s+(.*)")
@@ -905,7 +970,7 @@ def VerifyOptions(env):
     print env['simulator']
     Abort("Option unalignedaccesses only supported for the ARM architecture.")
   for (name, option) in SIMPLE_OPTIONS.iteritems():
-    if (not option.get('default')) and (name not in ARGUMENTS):
+    if (not name in env):
       message = ("A value for option %s must be specified (%s)." %
           (name, ", ".join(option['values'])))
       Abort(message)
@@ -1033,7 +1098,7 @@ def ParseEnvOverrides(arg, imports):
   return overrides
 
 
-def BuildSpecific(env, mode, env_overrides):
+def BuildSpecific(env, mode, env_overrides, tools):
   options = {'mode': mode}
   for option in SIMPLE_OPTIONS:
     options[option] = env[option]
@@ -1086,7 +1151,7 @@ def BuildSpecific(env, mode, env_overrides):
   (object_files, shell_files, mksnapshot) = env.SConscript(
     join('src', 'SConscript'),
     build_dir=join('obj', target_id),
-    exports='context',
+    exports='context tools',
     duplicate=False
   )
 
@@ -1106,21 +1171,21 @@ def BuildSpecific(env, mode, env_overrides):
     library = env.SharedLibrary(library_name, object_files, PDB=pdb_name)
   context.library_targets.append(library)
 
-  d8_env = Environment()
+  d8_env = Environment(tools=tools)
   d8_env.Replace(**context.flags['d8'])
   context.ApplyEnvOverrides(d8_env)
   shell = d8_env.Program('d8' + suffix, object_files + shell_files)
   context.d8_targets.append(shell)
 
   for sample in context.samples:
-    sample_env = Environment()
+    sample_env = Environment(tools=tools)
     sample_env.Replace(**context.flags['sample'])
     sample_env.Prepend(LIBS=[library_name])
     context.ApplyEnvOverrides(sample_env)
     sample_object = sample_env.SConscript(
       join('samples', 'SConscript'),
       build_dir=join('obj', 'sample', sample, target_id),
-      exports='sample context',
+      exports='sample context tools',
       duplicate=False
     )
     sample_name = sample + suffix
@@ -1133,7 +1198,7 @@ def BuildSpecific(env, mode, env_overrides):
   cctest_program = cctest_env.SConscript(
     join('test', 'cctest', 'SConscript'),
     build_dir=join('obj', 'test', target_id),
-    exports='context object_files',
+    exports='context object_files tools',
     duplicate=False
   )
   context.cctest_targets.append(cctest_program)
@@ -1143,7 +1208,9 @@ def BuildSpecific(env, mode, env_overrides):
 
 def Build():
   opts = GetOptions()
-  env = Environment(options=opts)
+  tools = GetTools(opts)
+  env = Environment(options=opts, tools=tools)
+
   Help(opts.GenerateHelpText(env))
   VerifyOptions(env)
   env_overrides = ParseEnvOverrides(env['env'], env['importenv'])
@@ -1157,7 +1224,7 @@ def Build():
   d8s = []
   modes = SplitList(env['mode'])
   for mode in modes:
-    context = BuildSpecific(env.Copy(), mode, env_overrides)
+    context = BuildSpecific(env.Copy(), mode, env_overrides, tools)
     libraries += context.library_targets
     mksnapshots += context.mksnapshot_targets
     cctests += context.cctest_targets
index 34ca91c..598e4af 100755 (executable)
@@ -31,6 +31,7 @@ root_dir = dirname(File('SConstruct').rfile().abspath)
 sys.path.append(join(root_dir, 'tools'))
 import js2c
 Import('context')
+Import('tools')
 
 
 SOURCES = {
@@ -305,7 +306,7 @@ def Abort(message):
 
 
 def ConfigureObjectFiles():
-  env = Environment()
+  env = Environment(tools=tools)
   env.Replace(**context.flags['v8'])
   context.ApplyEnvOverrides(env)
   env['BUILDERS']['JS2C'] = Builder(action=js2c.JS2C)