# -*- Python -*-
#
#
# All the helper functions are defined in:
#  - site_scons/talk.py
# Use 'import talk' in any .scons file to get access to it.
# Add any new helper functions to it; unittest are available
# in talk_unittest.py.
#
# Each 'component' that is built is defined in a .scons file.
# See talk.Components(...) for further info on file naming convention.
#
# To add a new platform clone and modify the root_env object. Remember to add
# the new environment object to the envs list otherwise it will not be included
# in the build.
#
#
#

import talk
import os
import platform

#-------------------------------------------------------------------------------
# The build files/directories to 'build'.
# If the name is the name of a directory then that directory shall contain a
# .scons file with the same name as the directory itself:
#  Ex: The directory session/phone contains a file called phone.scons
# This list must be in order of library dependencies. e.g., if
# session/phone/phone.scons defines a target that links to a library target
# defined in sound/sound.scons, then 'sound' must come first.
# When no particular order is imposed by library dependencies, try to keep in
# mostly alphabetical order.
#
components = talk.Components("libjingle.scons")

#-------------------------------------------------------------------------------
# Build environments
#

# The list of build environments.
envs = []

# The root of all builds.
root_env = Environment(
  tools = [
    'component_bits',
    'component_setup',
    'replace_strings',
    'talk_noops',
    #'talk_utils',
  ],
  BUILD_SCONSCRIPTS = components,
  DESTINATION_ROOT = '$MAIN_DIR/build',
  CPPPATH = [
    '$OBJ_ROOT',     # generated headers are relative to here
    '$MAIN_DIR/..',  # TODO(dape): how can we use GOOGLECLIENT instead?
  ],
  CPPDEFINES = [
    'LOGGING=1',

    # Feature selection
    'FEATURE_ENABLE_SSL',
    'FEATURE_ENABLE_VOICEMAIL',
    'FEATURE_ENABLE_PSTN',
    'HAVE_SRTP',
  ],
  # Ensure the os environment is captured for any scripts we call out to
  ENV = os.environ,
)

# This is where we set common environments
#
# Detect if building on 64-bit or 32-bit platform.
DeclareBit('build_platform_64bit', 'Platform of the build machine is 64-bit')
if platform.architecture()[0] == "64bit":
  root_env.SetBits('build_platform_64bit')

# This bit denotes that an env is for 64-bit builds. When set, all build
# artifacts will be 64-bit. When unset, all build artifacts will be 32-bit.
DeclareBit('host_platform_64bit',
           'Platform of the host machine (where artifacts will execute) is '
               '64-bit')

# This bit denotes that we are cross-compiling using a sysroot.
DeclareBit('cross_compile',
           'Cross compiling using the SYSROOT environment variable')

def CrossArch(env):
  """Return whether or not the host platform architecture differs from the build
     environment architecture."""
  if env.Bit('cross_compile'):
    # The architecture of the Python process may not match the architecture of
    # the sysroot, so we just assume it's not a cross-arch build or that it
    # doesn't matter. Currently it only matters if you try to build a cross-arch
    # Debian package, so just don't do that.
    return False
  else:
    return env.Bit('host_platform_64bit') != env.Bit('build_platform_64bit')
root_env.AddMethod(CrossArch)

DeclareBit('use_static_openssl', 'Build OpenSSL as a static library')

DeclareBit('have_dbus_glib',
           'Whether the build system has the dbus-glib-1 package')
DeclareBit('have_libpulse',
           'Whether the build system has the libpulse package')


# List all the locales we localize to.
root_env.AppendUnique(locales = [
    'af', 'am', 'ar', 'bg', 'bn', 'ca', 'cs', 'da', 'de', 'el', 'en', 'en-GB',
    'es', 'es-419', 'et', 'eu', 'fa', 'fi', 'fil', 'fr', 'fr-CA', 'gl', 'gu',
    'hi', 'hr', 'hu', 'id', 'is', 'it', 'iw', 'ja', 'kn', 'ko', 'lt', 'lv',
    'ml', 'mr', 'ms', 'nl', 'no', 'or', 'pl', 'pt-BR', 'pt-PT', 'ro', 'ru',
    'sk', 'sl', 'sr', 'sv', 'sw', 'ta', 'te', 'th', 'tl', 'tr', 'uk', 'ur',
    'vi', 'zh-CN', 'zh-HK', 'zh-TW', 'zu'])

AddTargetGroup('all_breakpads', 'breakpad files can be built')

AddTargetGroup('all_dsym', 'dsym debug packages can be built')

#-------------------------------------------------------------------------------
# W I N D O W S
#
win_env = root_env.Clone(
  tools = [
    'atlmfc_vc80',
    #'code_signing',
    'component_targets_msvs',
    'directx_9_0_c',
    #'grid_builder',
    'midl',
    'target_platform_windows'
  ],
  # Don't use default vc80 midl.exe.  It doesn't understand vista_sdk idl files.
  MIDL = '$PLATFORM_SDK_VISTA_6_0_DIR/Bin/midl.exe ',
  WIX_DIR = '$GOOGLECLIENT/third_party/wix/v3_0_2925/files',
  # Flags for debug and optimization are added to CCFLAGS instead
  CCPDBFLAGS = '',
  CCFLAGS_DEBUG = '',
  CCFLAGS_OPTIMIZED = '',
  # We force a x86 target even when building on x64 Windows platforms.
  TARGET_ARCH = 'x86',
)


win_env.Decider('MD5-timestamp')
win_env.Append(
  COMPONENT_LIBRARY_PUBLISH = True,  # Put dlls in output dir too
  CCFLAGS = [
    '/Fd${TARGET}.pdb', # pdb per object allows --jobs=
    '/WX',          # warnings are errors
    '/Zc:forScope', # handle 'for (int i = 0 ...)' right
    '/EHs-c-',      # disable C++ EH
    '/GR-',         # disable RTTI
    '/Gy',          # enable function level linking
    '/wd4996',      # ignore POSIX deprecated warnings

    # promote certain level 4 warnings
    '/w14701',     # potentially uninitialized var
    '/w14702',     # unreachable code
    '/w14706',     # assignment within a conditional
    '/w14709',     # comma operator within array index
    '/w14063',     # case 'identifier' is not a valid value for switch of enum
    '/w14064',     # switch of incomplete enum 'enumeration'
    '/w14057',     # 'identifier1' indirection to slightly different base
                   #   types from 'identifier2'
    '/w14263',     # member function does not override any base class virtual
                   #   member function
    '/w14266',     # no override available for virtual memberfunction from base
                   #  'type'; function is hidden
    '/w14296',     # expression is always false
    '/w14355',     # 'this' : used in base member initializer list
  ],
  CPPDEFINES = [
    '_ATL_CSTRING_EXPLICIT_CONSTRUCTORS',
    # TODO(dape): encapsulate all string operations that are not based
    # on std::string/std::wstring and make sure we use the safest versions
    # available on all platforms.
    '_CRT_SECURE_NO_WARNINGS',
    '_USE_32BIT_TIME_T',
    '_UNICODE',
    'UNICODE',
    '_HAS_EXCEPTIONS=0',
    'WIN32',
    # TODO(dape): remove this from logging.cc and enable here instead.
    #'WIN32_LEAN_AND_MEAN',

    'WINVER=0x0500',
    '_WIN32_WINNT=0x0501',
    '_WIN32_IE=0x0501',
    # The Vista platform SDK 6.0 needs at least
    # this NTDDI version or else the headers
    # that LMI includes from it won't compile.
    'NTDDI_VERSION=NTDDI_WINXP',

    # npapi.h requires the following:
    '_WINDOWS',
  ],
  CPPPATH = [
    '$THIRD_PARTY/wtl_71/include',
    '$PLATFORM_SDK_VISTA_6_0_DIR/Include',
  ],
  LIBPATH = [
    '$PLATFORM_SDK_VISTA_6_0_DIR/Lib'
  ],
  LINKFLAGS = [
    '-manifest', # TODO(thaloun): Why do we need this?
    # Some of the third-party libraries we link in don't have public symbols, so
    # ignore that linker warning.
    '/ignore:4221',
    '/nxcompat',    # Binary was tested to be be compatible with Windows DEP.
    '/dynamicbase', # Use ASLR to dynamically rebase at load-time.
    '/fixed:no',    # Binary can be loaded at any base-address.
  ],
  MIDLFLAGS = [
    '/win32',
    '/I$PLATFORM_SDK_VISTA_6_0_DIR/include'
  ]
)

# TODO(dape): Figure out what this does; found it in
# omaha/main.scons. This fixes the problem with redefinition
# of OS_WINDOWS symbol.
win_env.FilterOut(CPPDEFINES = ['OS_WINDOWS=OS_WINDOWS'])

# Set up digital signing
DeclareBit('test_signing', 'Sign binaries with the test certificate')
win_env.SetBitFromOption('test_signing', False)
if win_env.Bit('test_signing'):
   win_env.Replace(
     CERTIFICATE_PATH = win_env.File(
         '$GOOGLECLIENT/tools/test_key/testkey.pfx').abspath,
     CERTIFICATE_PASSWORD = 'test',
   )
AddTargetGroup('signed_binaries', 'digitally signed binaries can be built')

win_dbg_env = win_env.Clone(
  BUILD_TYPE = 'dbg',
  BUILD_TYPE_DESCRIPTION = 'Windows debug build',
  BUILD_GROUPS = ['default', 'all'],
  tools = ['target_debug'],
)

win_dbg_env.Prepend(
  CCFLAGS = [
    '/ZI',     # enable debugging
    '/Od',     # disable optimizations
    '/MTd',    # link with LIBCMTD.LIB debug lib
    '/RTC1',   # enable runtime checks
  ],
)

envs.append(win_dbg_env)

win_dbg64_env = win_dbg_env.Clone(
  BUILD_TYPE = 'dbg64',
  BUILD_TYPE_DESCRIPTION = 'Windows debug 64bit build',
  BUILD_GROUPS = ['all'],
)

win_dbg64_env.FilterOut(CCFLAGS = ['/ZI'])

win_dbg64_env.Append(
  CCFLAGS = [
    '/Zi',     # enable debugging that is 64 bit compatible.
    # TODO(fbarchard): fix warnings and remove these disables.
    '/wd4244', # disable cast warning
    '/wd4267', # disable cast warning
  ],
  ARFLAGS = [
    '/MACHINE:x64',
  ],
  CPPDEFINES = [
    'WIN64',
    'ARCH_CPU_64_BITS',
  ],
  LIBFLAGS = [
    '/MACHINE:x64',
  ],
  LINKFLAGS = [
    '/MACHINE:x64',
  ],
)

win_dbg64_env.FilterOut(CPPDEFINES = ['_USE_32BIT_TIME_T'])

win_dbg64_env.Prepend(
  LIBPATH = [
      '$VC80_DIR/vc/lib/amd64',
      '$ATLMFC_VC80_DIR/lib/amd64',
      '$PLATFORM_SDK_VISTA_6_0_DIR/Lib/x64',
  ],
)
win_dbg64_env.PrependENVPath(
  'PATH',
  win_dbg64_env.Dir('$VC80_DIR/vc/bin/x86_amd64'))

win_dbg64_env.SetBits('host_platform_64bit')

envs.append(win_dbg64_env)

win_coverage_env = win_dbg_env.Clone(
  tools = ['code_coverage'],
  BUILD_TYPE = 'coverage',
  BUILD_TYPE_DESCRIPTION = 'Windows code coverage build',
  BUILD_GROUPS = ['all'],
)

win_coverage_env.Append(
  CPPDEFINES = [
    'COVERAGE_ENABLED',
  ],
)

envs.append(win_coverage_env)

win_opt_env = win_env.Clone(
  BUILD_TYPE = 'opt',
  BUILD_TYPE_DESCRIPTION = 'Windows opt build',
  BUILD_GROUPS = ['all'],
  tools = ['target_optimized'],
)

win_opt_env.Prepend(
  CCFLAGS=[
      '/Zi',       # enable debugging
      '/O1',       # optimize for size
      '/fp:fast',  # float faster but less precise
      '/MT',       # link with LIBCMT.LIB (multi-threaded, static linked crt)
      '/GS',       # enable security checks
  ],
  LINKFLAGS = [
    '/safeseh',     # protect against attacks against exception handlers
    '/opt:ref',     # Remove unused references (functions/data).
  ],
)

envs.append(win_opt_env)

#-------------------------------------------------------------------------------
# P O S I X
#
posix_env = root_env.Clone()
posix_env.Append(
  CPPDEFINES = [
    'HASHNAMESPACE=__gnu_cxx',
    'HASH_NAMESPACE=__gnu_cxx',
    'POSIX',
    'DISABLE_DYNAMIC_CAST',
    # The POSIX standard says we have to define this.
    '_REENTRANT',
  ],
  CCFLAGS = [
    '-Wall',
    '-Werror',
    '-Wno-switch',
    '-fno-exceptions',
    # Needed for a clean ABI and for link-time dead-code removal to work
    # properly.
    '-fvisibility=hidden',
    # Generate debugging info in the DWARF2 format.
    '-gdwarf-2',
    # Generate maximal debugging information. (It is stripped from what we ship
    # to users, so we want it for both dbg and opt.)
    # Note that hammer automatically supplies "-g" for mac/linux dbg, so that
    # flag must be filtered out of linux_dbg and mac_dbg envs below.
    '-g3',
  ],
  CXXFLAGS = [
    '-Wno-non-virtual-dtor',
    '-Wno-ctor-dtor-privacy',
    '-fno-rtti',
  ],
)

# Switch-hit between NSS and OpenSSL
if 'NSS_BUILD_PLATFORM' in root_env['ENV']:
   posix_env.AppendUnique(CPPDEFINES=['HAVE_NSS_SSL_H=1',
                                      'NSS_SSL_RELATIVE_PATH'])
else:
   posix_env.AppendUnique(CPPDEFINES=['HAVE_OPENSSL_SSL_H=1'])


#-------------------------------------------------------------------------------
# M A C OSX
#
mac_env = posix_env.Clone(
  tools = [
    'target_platform_mac',
    #'talk_mac',
    #'fill_plist',
  ],
)
# Use static OpenSSL on mac so that we can use the latest APIs on all
# supported mac platforms (10.5+).
mac_env.SetBits('use_static_openssl')

# For libjingle we don't specify a sysroot or minimum OS version.
mac_osx_version_min_32 = ""
mac_osx_version_min_64 = ""

# Generic mac environment common to all targets
mac_env.Append(
  CPPDEFINES = [
    'OSX',
  ],
  CCFLAGS = [
    '-arch', 'i386',
    '-fasm-blocks',
  ],
  LINKFLAGS = [
    '-Wl,-search_paths_first',
    # This flag makes all members of a static library be included in the
    # final exe - that increases the size of the exe, but without it
    # Obj-C categories aren't properly included in the exe.
    # TODO(thaloun): consider only defining for libs that actually have objc.
    '-ObjC',
    '-arch', 'i386',
    '-dead_strip',
  ],
  FRAMEWORKS = [
    'CoreServices',
    'Security',
    'SystemConfiguration',
    'OpenGL',
    'CoreAudio',
    'Quartz',
    'Cocoa',
    'QTKit',
  ]
)

if 'NSS_BUILD_PLATFORM' in root_env['ENV']:
  mac_env.AppendUnique(LINKFLAGS = ['-Lthird_party/mozilla/dist/' + root_env['ENV']['NSS_BUILD_PLATFORM'] + '/lib'])
else:
  mac_env.AppendUnique(LINKFLAGS = ['-Lthird_party/openssl'])


# add debug flags to environment
def mac_debug_include(env):
  env.Append(
    CCFLAGS = [
      '-O0',
    ],
    CPPDEFINES = [
      'DEBUG=1',
    ],
  )
  # Remove -g set by hammer, which is not what we want (we have set -g3 above).
  env.FilterOut(CCFLAGS = ['-g'])

# add 32/64 bit specific options to specified environment
def mac_common_include_x86_32(env):
  env.Append(
    CCFLAGS = [
      '-m32',
    ],
    LINKFLAGS = [
      '-m32',
    ],
    FRAMEWORKS = [
      'Carbon',
      'QuickTime',
    ],
  )
  envs.append(env)

def mac_common_include_x86_64(env):
  env.Append(
    CCFLAGS = [
      '-m64',
      '-fPIC',
    ],
    CPPDEFINES = [
      'ARCH_CPU_64_BITS',
      'CARBON_DEPRECATED',
    ],
    LINKFLAGS = [
      '-m64',
    ],
    FRAMEWORKS = [
      'AppKit',
    ],
  )
  env.SetBits('host_platform_64bit')
  envs.append(env)

def mac_osx_version_min(env, ver):
  if ver != "":
    sdk_path = '/Developer/SDKs/MacOSX%s.sdk' % ver
    env.Append(
      CCFLAGS = [
        '-mmacosx-version-min=' + ver,
        '-isysroot', sdk_path,
      ],
      LINKFLAGS = [
        '-mmacosx-version-min=' + ver,
        '-isysroot', sdk_path,
      ],
      osx_sdk_path = sdk_path,
      osx_version_min = ver,
    )

# Create all environments
mac_dbg_env = mac_env.Clone(
  BUILD_TYPE = 'dbg',
  BUILD_TYPE_DESCRIPTION = 'Mac debug build',
  BUILD_GROUPS = ['default', 'all'],
  tools = ['target_debug'],
)

mac_opt_env = mac_env.Clone(
  BUILD_TYPE = 'opt',
  BUILD_TYPE_DESCRIPTION = 'Mac opt build',
  BUILD_GROUPS = ['all'],
  tools = ['target_optimized'],
)

mac_dbg64_env = mac_dbg_env.Clone(
  BUILD_TYPE = 'dbg64',
  BUILD_TYPE_DESCRIPTION = 'Mac debug 64bit build',
  BUILD_GROUPS = ['all'],
)

mac_opt64_env = mac_opt_env.Clone(
  BUILD_TYPE = 'opt64',
  BUILD_TYPE_DESCRIPTION = 'Mac opt 64bit build',
  BUILD_GROUPS = ['all'],
)

mac_debug_include(mac_dbg_env)
mac_debug_include(mac_dbg64_env)
mac_common_include_x86_32(mac_dbg_env)
mac_common_include_x86_32(mac_opt_env)
mac_common_include_x86_64(mac_dbg64_env)
mac_common_include_x86_64(mac_opt64_env)
mac_osx_version_min(mac_dbg_env, mac_osx_version_min_32)
mac_osx_version_min(mac_opt_env, mac_osx_version_min_32)
mac_osx_version_min(mac_dbg64_env, mac_osx_version_min_64)
mac_osx_version_min(mac_opt64_env, mac_osx_version_min_64)


#-------------------------------------------------------------------------------
# L I N U X
#
linux_common_env = posix_env.Clone(
  tools = [
    'target_platform_linux',
    'talk_linux',
  ],
)

linux_common_env.Append(
  CPPDEFINES = [
    'LINUX',
  ],
  CCFLAGS = [
    # Needed for link-time dead-code removal to work properly.
    '-ffunction-sections',
    '-fdata-sections',
  ],
  LINKFLAGS = [
    # Enable dead-code removal.
    '-Wl,--gc-sections',
    # Elide dependencies on shared libraries that we're not actually using.
    '-Wl,--as-needed',
    '-Wl,--start-group',
  ],
  _LIBFLAGS = ['-Wl,--end-group'],
)

# Remove default rpath set by Hammer. Hammer sets it to LIB_DIR, which is wrong.
# The rpath is the _run-time_ library search path for the resulting binary, i.e.
# the one used by ld.so at load time. Setting it equal to the path to build
# output on the build machine is nonsense.
linux_common_env.Replace(
  RPATH = [],
)

# Enable the optional DBus-GLib code if the build machine has the required
# dependency.
linux_common_env.EnableFeatureWherePackagePresent('have_dbus_glib',
                                                  'HAVE_DBUS_GLIB',
                                                  'dbus-glib-1')

def linux_common_include_x86_32(env):
  """Include x86-32 settings into an env based on linux_common."""
  env.Append(
    CCFLAGS = [
      '-m32',
    ],
    LINKFLAGS = [
      '-m32',
    ],
  )

def linux_common_include_x86_64(env):
  """Include x86-64 settings into an env based on linux_common."""
  env.Append(
    CCFLAGS = [
      '-m64',
      '-fPIC',
    ],
    LINKFLAGS = [
      '-m64',
    ],
  )
  env.SetBits('host_platform_64bit')

#-------------------------------------------------------------------------------
# L I N U X -- C R O S S -- B U I L D

# Cross build requires the following tool names be provided by the environment:
linux_cross_common_env = linux_common_env.Clone(
  AR = os.environ.get("AR"),
  AS = os.environ.get("AS"),
  LD = os.environ.get("LD"),
  NM = os.environ.get("NM"),
  RANLIB = os.environ.get("RANLIB"),
  CC = str(os.environ.get("CC")) +
    ' --sysroot=' + str(os.environ.get("SYSROOT")),
  CXX = str(os.environ.get("CXX")) +
    ' --sysroot=' + str(os.environ.get("SYSROOT")),
)
linux_cross_common_env.SetBits('cross_compile')

# The rest of these paths and flags are optional:
if os.environ.get("CPPPATH"):
  linux_cross_common_env.Append(
    CPPPATH = os.environ.get("CPPPATH").split(':'),
  )
if os.environ.get("LIBPATH"):
  linux_cross_common_env.Append(
    LIBPATH = os.environ.get("LIBPATH").split(':'),
  )
if os.environ.get("CFLAGS"):
  linux_cross_common_env.Append(
    CFLAGS = os.environ.get("CFLAGS").split(' '),
  )
if os.environ.get("CCFLAGS"):
  linux_cross_common_env.Append(
    CCFLAGS = os.environ.get("CCFLAGS").split(' '),
  )
if os.environ.get("CXXFLAGS"):
  linux_cross_common_env.Append(
    CXXFLAGS = os.environ.get("CXXFLAGS").split(' '),
  )
if os.environ.get("LIBFLAGS"):
  linux_cross_common_env.Append(
    _LIBFLAGS = os.environ.get("LIBFLAGS").split(' '),
  )
if os.environ.get("LINKFLAGS"):
  linux_cross_common_env.Prepend(
    LINKFLAGS = os.environ.get("LINKFLAGS").split(' '),
  )

#-------------------------------------------------------------------------------
# L I N U X -- T R A D I T I O N A L -- X 8 6
#
# Settings that are specific to our desktop Linux x86 targets.
def linux_common_include_traditional(env):
  """Include traditional Linux settings into an env based on linux_common."""
  # OpenSSL has infamously poor ABI stability, so that building against one
  # version and running against a different one often will not work. Since our
  # non-ChromeOS Linux builds are used on many different distros and distro
  # versions, this means we can't safely dynamically link to OpenSSL because the
  # product would end up being broken on any computer with a different version
  # installed. So instead we build it ourself and statically link to it.
  env.SetBits('use_static_openssl')
  # Enable the optional PulseAudio code if the build machine has the required
  # dependency.
  # TODO(?): This belongs in linux_common_env, but we can't safely move it there
  # yet because pkg-config is not being used properly with ChromeOS builds (see
  # TODO below).
  env.EnableFeatureWherePackagePresent('have_libpulse',
                                       'HAVE_LIBPULSE',
                                       'libpulse')

def linux_traditional_include_dbg(env):
  """Include traditional Linux dbg settings into an env based on the above."""
  # Remove -g set by hammer, which is not what we want (we have set -g3 above).
  env.FilterOut(CCFLAGS = ['-g'])

def linux_traditional_include_opt(env):
  """Include traditional Linux opt settings into an env based on the above."""
  # Remove -O2 set by hammer, which is not what we want.
  env.FilterOut(CCFLAGS = ['-O2'])
  env.Append(CCFLAGS = ['-Os'])

def gen_linux_nonhermetic(linux_env, type_suffix, desc_suffix):
  groups = ['nonhermetic']
  if not linux_env.CrossArch():
    groups = groups + ['nonhermetic-native']
    # The non-hermetic, native-arch dbg build is the default.
    dbg_groups = groups + ['default']
    native_desc = ', native '
    # No suffix for native modes.
    type_suffix = ''
  else:
    groups = groups + ['nonhermetic-cross']
    dbg_groups = groups
    native_desc = ', cross-built for '

  linux_dbg_env = linux_env.Clone(
    BUILD_TYPE = 'dbg' + type_suffix,
    BUILD_TYPE_DESCRIPTION = 'Linux debug build%s%s' % (native_desc,
        desc_suffix),
    BUILD_GROUPS = dbg_groups,
    tools = ['target_debug'],
  )
  linux_traditional_include_dbg(linux_dbg_env)
  envs.append(linux_dbg_env)

  linux_opt_env = linux_env.Clone(
    BUILD_TYPE = 'opt' + type_suffix,
    BUILD_TYPE_DESCRIPTION = 'Linux optimized build%s%s' % (native_desc,
        desc_suffix),
    BUILD_GROUPS = groups,
    tools = ['target_optimized'],
  )
  linux_traditional_include_opt(linux_opt_env)
  envs.append(linux_opt_env)

linux_nonhermetic_common_env = linux_common_env.Clone()
linux_common_include_traditional(linux_nonhermetic_common_env)

linux_nonhermetic_x86_32_env = linux_nonhermetic_common_env.Clone()
linux_common_include_x86_32(linux_nonhermetic_x86_32_env)
gen_linux_nonhermetic(linux_nonhermetic_x86_32_env, '32', '32-bit')

linux_nonhermetic_x86_64_env = linux_nonhermetic_common_env.Clone()
linux_common_include_x86_64(linux_nonhermetic_x86_64_env)
gen_linux_nonhermetic(linux_nonhermetic_x86_64_env, '64', '64-bit')

def gen_linux_hermetic(linux_env, type_suffix, desc):
  groups = ['hermetic']

  linux_dbg_env = linux_env.Clone(
    BUILD_TYPE = 'hermetic-dbg' + type_suffix,
    BUILD_TYPE_DESCRIPTION = 'Hermetic %s Linux debug build' % desc,
    BUILD_GROUPS = groups,
    tools = ['target_debug'],
  )
  linux_traditional_include_dbg(linux_dbg_env)
  envs.append(linux_dbg_env)

  linux_opt_env = linux_env.Clone(
    BUILD_TYPE = 'hermetic-opt' + type_suffix,
    BUILD_TYPE_DESCRIPTION = 'Hermetic %s Linux optimized build' % desc,
    BUILD_GROUPS = groups,
    tools = ['target_optimized'],
  )
  linux_traditional_include_opt(linux_opt_env)
  envs.append(linux_opt_env)

linux_hermetic_common_env = linux_cross_common_env.Clone()
linux_common_include_traditional(linux_hermetic_common_env)

linux_hermetic_x86_32_env = linux_hermetic_common_env.Clone()
linux_common_include_x86_32(linux_hermetic_x86_32_env)
gen_linux_hermetic(linux_hermetic_x86_32_env, '32', '32-bit')

linux_hermetic_x86_64_env = linux_hermetic_common_env.Clone()
linux_common_include_x86_64(linux_hermetic_x86_64_env)
gen_linux_hermetic(linux_hermetic_x86_64_env, '64', '64-bit')

#-------------------------------------------------------------------------------
# L I N U X -- C R O S S -- B U I L D -- A R M

# TODO(noahric): All the following Linux builds are running against a sysroot
# but improperly using the host machine's pkg-config environment. The ChromeOS
# ones should probably be using
# https://cs.corp.google.com/#chrome/src/build/linux/pkg-config-wrapper.

linux_cross_arm_env = linux_cross_common_env.Clone()
linux_cross_arm_env.Append(
  CPPDEFINES = [
    'NACL_BUILD_ARCH=arm',
    'DISABLE_EFFECTS=1',
  ],
  CCFLAGS = [
    '-fPIC',
  ],
)
DeclareBit('arm', 'ARM build')
linux_cross_arm_env.SetBits('arm')

# Detect NEON support from the -mfpu build flag.
DeclareBit('arm_neon', 'ARM supporting neon')
if '-mfpu=neon' in linux_cross_arm_env['CFLAGS'] or \
   '-mfpu=neon' in linux_cross_arm_env['CCFLAGS'] or \
   '-mfpu=neon' in linux_cross_arm_env['CXXFLAGS']:
  print "Building with ARM NEON support."
  linux_cross_arm_env.SetBits('arm_neon')

# Detect hardfp from the -mfloat-abi build flag
DeclareBit('arm_hardfp', 'ARM supporting hardfp')
if '-mfloat-abi=hard' in linux_cross_arm_env['CFLAGS'] or \
   '-mfloat-abi=hard' in linux_cross_arm_env['CCFLAGS'] or \
   '-mfloat-abi=hard' in linux_cross_arm_env['CXXFLAGS']:
  print "Building with hard floating point support."
  linux_cross_arm_env.SetBits('arm_hardfp')

linux_cross_arm_dbg_env = linux_cross_arm_env.Clone(
  BUILD_TYPE = 'arm-dbg',
  BUILD_TYPE_DESCRIPTION = 'Cross-compiled ARM debug build',
  BUILD_GROUPS = ['arm'],
  tools = ['target_debug'],
)
envs.append(linux_cross_arm_dbg_env)

linux_cross_arm_opt_env = linux_cross_arm_env.Clone(
  BUILD_TYPE = 'arm-opt',
  BUILD_TYPE_DESCRIPTION = 'Cross-compiled ARM optimized build',
  BUILD_GROUPS = ['arm'],
  tools = ['target_optimized'],
)
envs.append(linux_cross_arm_opt_env)



# Create a group for installers
AddTargetGroup('all_installers', 'installers that can be built')

# Parse child .scons files
BuildEnvironments(envs)

# Explicitly set which targets to build when not stated on commandline
Default(None)
# Build the following, which excludes unit test output (ie running them)
# To run unittests, specify the test to run, or run_all_tests.  See -h option.
Default(['all_libraries', 'all_programs', 'all_test_programs'])

# .sln creation code lifted from googleclient/bar/main.scons.  Must be after
# the call to BuildEnvironments for all_foo aliases to be defined.
# Run 'hammer --mode=all --vsproj' to generate
DeclareBit('vsproj', 'Generate Visual Studio projects and solution files.')
win_env.SetBitFromOption('vsproj', False)

if win_env.Bit('vsproj'):
  vs_env = win_env.Clone()
  vs_env.Append(
    COMPONENT_VS_SOURCE_SUFFIXES = [
      '.def',
      '.grd',
      '.html',
      '.idl',
      '.mk',
      '.txt',
      '.py',
      '.scons',
      '.wxs.template',
    ]
  )

  # Source project
  p = vs_env.ComponentVSDirProject(
    'flute_source',
    ['$MAIN_DIR',
    ],
    COMPONENT_VS_SOURCE_FOLDERS = [
      # Files are assigned to first matching folder. Folder names of None
      # are filters.
      (None, '$DESTINATION_ROOT'),
      ('flute', '$MAIN_DIR'),
      ('google3', '$GOOGLE3'),
      ('third_party', '$THIRD_PARTY'),
    ],
    # Force source project to main dir, so that Visual Studio can find the
    # source files corresponding to build errors.
    COMPONENT_VS_PROJECT_DIR = '$MAIN_DIR',
  )
  vs_env.AlwaysBuild(p)

  # Solution and target projects
  s = vs_env.ComponentVSSolution(
    # 'libjingle',  # Please uncomment this line if you build VS proj files.
    ['all_libraries', 'all_programs', 'all_test_programs'],
    projects = [p],
  )

  print '***Unfortunately the vsproj creator isn\'t smart enough to '
  print '***automatically get the correct output locations.  It is very easy'
  print '***though to change it in the properties pane to the following'
  print '***$(SolutionDir)/build/<foo>/staging/<bar>.exe'
  Default(None)
  Default([s])