# Copyright (c) 2008 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

# Notes:
# This assumes you have a working gears checkout from p4 in the current dir.
# Steps for this:
# > echo %USER%-chromegears > p4config
# or on linux/osx:
# > echo $USER-chromegears > p4config
# > set P4CONFIG=p4config
# > g4 client -p //depot/googleclient/gears/p4_depot_paths
# > g4 sync
#
# This is a work-in-progress conversion of the current Gears set of Makefiles.
# A lot of the stuff doesn't translate to SCons-land well, and I'm not sure
# how faithful we want to be to the original.
#
# Questions:
# Should we flatten the output directory into
# Hammer/gears/platform/browser/*.obj like Gears does now?  If so, how?

# Notes to self:
# - os.path.abspath('.') (the CWD) is variant_dir if it exists, else it's the
# toplevel_dir (which contains the SConstruct).
# - env.Entry('.') is the entry representing the variant_dir.
# - env.Entry('#') is the entry representing the toplevel_dir.
# - str(entry) gives the path relative to variant_dir, or abspath if the entry
# is outside the variant_dir.
# - entry.path gives the path relative to toplevel_dir.
# - entry.abspath gives the absolute path.

import os

Import('env')

env = env.Clone(
    OPEN_DIR = "gears",
    PRIVATE_DIR = "gears_internal",
    THIRD_PARTY_DIR = "third_party",
    PRIVATE_THIRD_PARTY_DIR = "third_party_internal",
    SYMBIAN_DIR = "symbian_internal",
)

if not os.path.exists(env.Dir('#/$OPEN_DIR').abspath):
  print 'Skipping Gears build: no perforce tree checked out.'
  Return()

# Argument switches

# TODO: how do we detect linux vs osx?
os_guess = env['PLATFORM']
if os_guess == 'posix':
  os_guess = 'linux'
elif os_guess == 'darwin':
  os_guess = 'osx'

# Map of OS -> valid browser targets for that OS.
os_browsers_map = {
    'win32': ['IE', 'FF2', 'FF3', 'NPAPI'],
    'wince': ['IE'],
    'linux': ['FF2', 'FF3'],
    'osx': ['SF', 'FF2', 'FF3'],
    'android': ['NPAPI'],
    'symbian': ['NPAPI'],
}

vars = Variables(None, ARGUMENTS)
vars.AddVariables(
    EnumVariable('OS',
        'Which OS is the target', os_guess, os_browsers_map.keys()),
    EnumVariable('MODE',
        'Type of binary to generate', 'dbg', ['dbg', 'opt']),
    BoolVariable('OFFICIAL_BUILD',
        'Create a binary suitable for public release', 0)
)
vars.Update(env)

env['VALID_BROWSERS'] = os_browsers_map[env['OS']]

# Add BROWSER last, since its valid inputs depend on $OS.
vars.Add(
    EnumVariable('BROWSER',
        'Which browser we want to build the plugin for.  "all" builds all '
        'browsers for this OS.',
        'all', env['VALID_BROWSERS'] + ['all']))
vars.Update(env)

env.Replace(
    USING_CCTESTS = (env['MODE'] == 'dbg' or not env['OFFICIAL_BUILD'])
)

# Version
env.Replace(
    MAJOR = '0',
    MINOR = '4',
    BUILD = '24',
    PATCH = '0',
    VERSION = '${MAJOR}.${MINOR}.${BUILD}.${PATCH}',

    FRIENDLY_NAME = 'Google Gears',
    SHORT_NAME = 'gears',
)

# Platform
# TODO: Symbian builds will override this value.
# For other platforms we set just one value.
if env['OS'] in ['wince', 'android']:
  env.Replace(ARCH = 'arm')
elif env['OS'] == 'osx':
  # On OSX we build a fat binary.
  env.Replace(ARCH = 'i386+ppc')
else:
  env.Replace(ARCH = 'i386')

# Output dirs
env.Replace(
    BASE_OUTDIR = '$GEARS_DIR/$OS-$ARCH-$MODE',
    COMMON_OUTDIR = '$BASE_OUTDIR/common',
    BROWSER_OUTDIR = '$BASE_OUTDIR/${BROWSER.lower()}',
    IE_OUTDIR = '$BASE_OUTDIR/ie',
    FF2_OUTDIR = '$BASE_OUTDIR/ff2',
    FF3_OUTDIR = '$BASE_OUTDIR/ff3',
    NPAPI_OUTDIR = '$BASE_OUTDIR/npapi',
    SF_OUTDIR = '$BASE_OUTDIR/sf',

    GENFILES_DIR = "$BROWSER_OUTDIR/genfiles",
    COMMON_GENFILES_DIR = "$COMMON_OUTDIR/genfiles",

    INSTALLER_BASEDIR = 'installers',
    INSTALLER_BASENAME = 'gears-${OS}-${MODE}-${VERSION}',
    INSTALLER_OUTDIR = '$BASE_OUTDIR/$INSTALLER_BASEDIR',
)

# Library flags
env.Replace(
    MOZJS_INCLUDE_PATHS = [
        '$MOZJS_DIR',
        '$THIRD_PARTY_DIR/spidermonkey/nspr/pr/include',
        '$THIRD_PARTY_DIR/spidermonkey/nspr/pr/include/private',
        '$THIRD_PARTY_DIR/spidermonkey/nspr/pr/include/obsolete',
        '$OSX_SDK_ROOT/Developer/Headers/FlatCarbon/',
    ],
    MOZJS_DIR = '$THIRD_PARTY_DIR/spidermonkey',
)

# Add our tools to the PATH.
if env['OS'] in ['win32', 'wince']:
  if os.path.exists(env.Dir('#/$PRIVATE_THIRD_PARTY_DIR').abspath):
    # Clear out our environment so we don't accidentally use the system's
    # libs.
    env['ENV']['PATH'] = ''
    env['ENV']['LIB'] = ''
    env['ENV']['INCLUDE'] = ''

    paths = []

    # Keep system32 for 'xcopy'.
    paths += [env.subst('${ENV["SYSTEMROOT"]}/system32')]
    if env['OS'] == 'win32':
      env.Append(
          VC80 = env.Dir('#/$PRIVATE_THIRD_PARTY_DIR/vc_80/files').abspath)
      paths += [
          env.subst('$VC80/common7/ide'),
          env.subst('$VC80/vc/bin'),
          env.subst('$VC80/common7/tools'),
          env.subst('$VC80/common7/tools/bin'),
          env.subst('$VC80/team_tools/performance_tools'),
      ]
    else:  # wince
      env.Append(
          VC80 = env.Dir('#/$PRIVATE_THIRD_PARTY_DIR/vc_80ce/files').abspath)
      paths += [
          env.subst('$VC80/bin/x86_arm'),
          env.subst('$VC80/common7/ide'),
          env.subst('$VC80/common7/tools'),
          env.subst('$VC80/common7/tools/bin'),
          env.subst('$VC80/vc/bin'),
          env.subst('$VC80/smartdevices/sdktools'),
      ]

    paths += [
        env.Dir('#/$PRIVATE_THIRD_PARTY_DIR/wix/v3_0_2925/files').abspath]

    paths += [env.Dir('#/$PRIVATE_THIRD_PARTY_DIR/gnu/files').abspath]
    paths += [env.Dir('#/$PRIVATE_THIRD_PARTY_DIR/python_24').abspath]

    # Prepend them so our tools come first.
    for each in reversed(paths):
      env.PrependENVPath('PATH', each)
  else:
    # If we don't have a private third_party dir, we expect the system
    # environment to be set up correctly to point to tool paths.
    env['ENV']['PATH'] = os.environ['PATH']
    env['ENV']['LIB'] = os.environ['LIB']
    env['ENV']['INCLUDE'] = os.environ['INCLUDE']

  # HACK to disable manifest creation, since it breaks all the time.
  env['LINKCOM'] = env['LINKCOM'][0]
  env['SHLINKCOM'] = env['SHLINKCOM'][0]

# Building M4 files
env.Tool('m4')

env.Append(
    M4ARCH = (env['ARCH'] == 'i386' and 'x86' or '$ARCH'),
    M4FLAGS = [
        '--prefix-builtins',
        '-DPRODUCT_VERSION=$VERSION',
        '-DPRODUCT_VERSION_MAJOR=$MAJOR',
        '-DPRODUCT_VERSION_MINOR=$MINOR',
        '-DPRODUCT_VERSION_BUILD=$BUILD',
        '-DPRODUCT_VERSION_PATCH=$PATCH',
        '-DPRODUCT_OS=$OS',
        '-DPRODUCT_ARCH="$M4ARCH"',
        '-DPRODUCT_GCC_VERSION="gcc3"',
        '-DPRODUCT_MAINTAINER="google"',
        '-DPRODUCT_FRIENDLY_NAME_UQ="$FRIENDLY_NAME"',
        '-DPRODUCT_SHORT_NAME_UQ="$SHORT_NAME"',
        '-DI18N_LANGUAGES="(${",".join(I18N_LANGS)})"',
    ],
    M4PATH = [
        '$OPEN_DIR',
        '.',
    ],
)

# SCons magic to make M4PATH work.
env.Replace(
    M4INCPREFIX = '-I',
    M4INCSUFFIX = '',
    _M4INCFLAGS = ('${_concat(M4INCPREFIX, M4PATH, M4INCSUFFIX, '
                 '__env__, RDirs, TARGET, SOURCE)}'),
    M4COM = '$M4 $M4FLAGS ${_M4INCFLAGS} $SOURCE > $TARGET',
)

# TODO: Dependency scanner for m4 files - doesn't work.  It can't detect files
# that don't exist!
#m4_include_re = re.compile(r'm4_include\((.*)\)', re.M)
#def m4_scan(node, env, path):
#  contents = node.get_contents()
#  includes = m4_include_re.findall(contents)
#  ret_includes = []
#  for include in includes:
#    for dir in path:
#      file = os.path.join(dir, include)
#      if os.path.exists(file):
#        ret_includes.append(file)
#        break
#  return ret_includes
#
#m4_scanner = Scanner(function = m4_scan, skeys = ['.m4', '.html_m4'])
#env.Append(SCANNERS = m4_scanner)


# OS X Iceberg package builder

env.Replace(ICEBERG = '/usr/local/bin/freeze')
if env.WhereIs('$ICEBERG'):
  env.Replace(ICEBERGCOM = '"$ICEBERG" -v $SOURCE')
else:
  env.Replace(ICEBERGCOM =
      'echo To create a Safari installer for Gears, you must install Iceberg'
      ' from http://s.sudre.free.fr/Software/Iceberg.html.  You can install'
      ' the Safari version manually by running the'
      ' $OPEN_DIR/tools/osx/install_gears.sh script.')

iceberg_builder = Builder(action = '$ICEBERGCOM',
    suffix = '.pkg', src_suffix = '.packproj')
env.Append(BUILDERS = {'Iceberg': iceberg_builder})


# C++ build flags.

# Clear out the inherited defines from Chrome's build.  I want to match Gears'
# current build as closely as possible until we switch everyone to SCons, then
# gradually integrate.
env.Replace(
    CPPPATH = [
        '$OPEN_DIR',
        '$OPEN_DIR/..',
        '$THIRD_PARTY_DIR',
        '$THIRD_PARTY_DIR/googleurl',
        '$THIRD_PARTY_DIR/npapi',
        '$THIRD_PARTY_DIR/zlib',
        '$THIRD_PARTY_DIR/v8/bindings_local',
        '.',
        '$COMMON_OUTDIR',
    ],
    CFLAGS = [],
    CCFLAGS = [],
    CXXFLAGS = [],
    CCPDBFLAGS = [],
    CPPDEFINES = [
    # SpiderMonkey (the Firefox JS engine)'s JS_GET_CLASS macro in jsapi.h needs
    # this defined to work with the gecko SDK that we've built.
    # The definition of JS_THREADSAFE must be kept in sync with MOZJS_CPPFLAGS.
        'JS_THREADSAFE'
    ],
    FRAMEWORKPATH = [],
    FRAMEWORKS = [],
    LIBS = [],
    LIBPATH = ['$COMPONENT_LIBRARY_DIR'],
    LINKFLAGS = [],
    SHLINKFLAGS = [],
    COMPONENT_LIBRARY_DIR = '$COMMON_OUTDIR/lib',
)

if env['MODE'] == 'dbg':
  env.Append(
      CPPDEFINES = [
          'DEBUG=1',
          '_DEBUG=1',
      ],
      M4FLAGS = '-DDEBUG=1',
  )
else:
  env.Append(
      CPPDEFINES = 'NDEBUG=1',
      M4FLAGS = '-DNDEBUG=1',
  )
if env['USING_CCTESTS']:
  env.Append(
      CPPDEFINES = 'USING_CCTESTS=1',
      M4FLAGS = '-DUSING_CCTESTS=1',
  )
if env['OFFICIAL_BUILD']:
  env.Append(
      CPPDEFINES = 'OFFICIAL_BUILD=1',
      M4FLAGS = '-DOFFICIAL_BUILD=1',
  )

# TODO: if USING_PNG
env.Append(CPPDEFINES = 'PNG_USER_CONFIG')
# TODO: if USING_ZLIB
env.Append(
    CPPDEFINES = [
        'NO_GZIP',
        'NO_GZCOMPRESS',
    ]
)
if env['OS'] == 'wince':
  env.Append(CPPDEFINES = 'NO_ERRNO_H')

# Languages

env['I18N_LANGS'] = [
    'en-US',
    'ar',
    'bg',
    'ca',
    'cs',
    'da',
    'de',
    'el',
    'en-GB',
    'es',
    'et',
    'fa',
    'fi',
    'fil',
    'fr',
    'he',
    'hi',
    'hr',
    'hu',
    'id',
    'is',
    'it',
    'ja',
    'ko',
    'lt',
    'lv',
    'ms',
    'nl',
    'no',
    'pl',
    'pt-BR',
    'pt-PT',
    'ro',
    'ru',
    'sk',
    'sl',
    'sr',
    'sv',
    'th',
    'tr',
    'uk',
    'ur',
    'vi',
    'zh-CN',
    'zh-TW',
    'ml',
    'te',
    'gu',
    'kn',
    'or',
    'bn',
    'ta',
    'mr',
]

# Platform-specific flags follow.

if env['OS'] in ['win32', 'wince']:
  env.Replace(ARFLAGS = [])
  env.Append(
      CPPDEFINES = [
          'STRICT',
          '_UNICODE',
          'UNICODE',
          '_USRDLL',
          'WIN32',
          '_WINDLL',
          '_CRT_SECURE_NO_DEPRECATE',
          'NOMINMAX',

# In VC8, the way to disable exceptions is to remove all /EH* flags, and to
# define _HAS_EXCEPTIONS=0 (for C++ headers) and _ATL_NO_EXCEPTIONS (for ATL).
          '_HAS_EXCEPTIONS=0',
          '_ATL_NO_EXCEPTIONS',
# Do not export UTF functions.
          'U_STATIC_IMPLEMENTATION',
      ],
# Static lib flags.
      ARFLAGS = [
          '/NOLOGO',
      ],
# Shared lib and exe flags.
      LINKFLAGS = [
          '/NOLOGO',
          '/DEBUG',
          '/RELEASE',
          '/PDB:${TARGET.base}.pdb',
# Set the preferred base address.  This value was chosen because (a) it's near
# the top of the valid address range, and (b) it doesn't conflict with other
# DLLs loaded by Chrome in either the browser or plugin process.
          '/BASE:0x65000000',
      ],
      CPPFLAGS = [
          '/nologo',
          '/Zc:wchar_t-',
          '/c',
          '/W3',
          '/WX',
          '/GR-',
          '/Fd"${TARGET.base}.pdb"',
      ],
      CXXFLAGS = [
          '/TP',
          '/J',
      ],
      CPPPATH = [
          '$VC80_CPPPATH',
          '$THIRD_PARTY_DIR/breakpad/src',
      ],
      CCPDBFLAGS = [
          '/Zi',  # TODO: Chrome defines /Z7, no idea what these are.
      ],
      LIBPATH = [
          '$VC80_LIBPATH',
      ],
  )
  if env['OS'] == 'win32':
    env.Append(
        CPPDEFINES = [
# We require APPVER=5.0 for things like HWND_MESSAGE.
# When APPVER=5.0, win32.mak in the Platform SDK sets:
#   C defines:  WINVER=0x0500
#               _WIN32_WINNT=0x0500
#               _WIN32_IE=0x0500
#               _RICHEDIT_VER=0x0010
#   RC defines: WINVER=0x0500
#   MIDL flags: /target NT50
# Note: _WIN32_WINDOWS was replaced by _WIN32_WINNT for post-Win95 builds.
# Note: XP_WIN is only used by Firefox headers
            '_WINDOWS',
            'WINVER=0x0500',
            '_WIN32_WINNT=0x0500',
            '_WIN32_IE=0x0500',
            '_RICHEDIT_VER=0x0010',
            '_MERGE_PROXYSTUB',
            'BREAKPAD_AVOID_STREAMS',
            'XP_WIN',
        ],
        ARFLAGS = [
            '/MACHINE:X86',
        ],
        LINKFLAGS = [
            '/MACHINE:X86',
            '/NODEFAULTLIB:msvcrt',
# Flags for security hardening (only available for win32, not wince).
            '/DYNAMICBASE',
            '/SAFESEH',

# We only use /SUBSYSTEM on DLLs. For EXEs we omit the flag, and
# the presence of main() or WinMain() determines the subsystem.
            '/SUBSYSTEM:WINDOWS',
        ],
        VC80_CPPPATH = [
# TODO: switch over to Chrome's SDK.
# Note: these must come after $THIRD_PARTY_DIR/npapi because we want our own
# npapi.h to take precedence.
            '$PRIVATE_THIRD_PARTY_DIR/atlmfc_vc80/files/include',
            '$PRIVATE_THIRD_PARTY_DIR/platformsdk_vc80/files/include',
            '$PRIVATE_THIRD_PARTY_DIR/vc_80/files/vc/include',
        ],
        VC80_LIBPATH = [
            '$PRIVATE_THIRD_PARTY_DIR/atlmfc_vc80/files/lib',
            '$PRIVATE_THIRD_PARTY_DIR/platformsdk_vc80/files/lib',
            '$PRIVATE_THIRD_PARTY_DIR/vc_80/files/vc/lib',
        ],
    )
  else:  # OS=wince
    env.Append(
        CPPDEFINES = [
# For Windows Mobile we need:
#   C defines:  _WIN32_WCE=0x0501
#               _UNDER_CE=0x0501
            '_WIN32_WCE=0x501',
            'WINVER=_WIN32_WCE',
            'UNDER_CE=0x501',
            'OS_WINCE',
            'WIN32_PLATFORM_PSPC',
            'ARM',
            '_ARM_',
            'POCKETPC2003_UI_MODEL',
            '_CE_ALLOW_SINGLE_THREADED_OBJECTS_IN_MTA',
            '_CE_CRT_ALLOW_WIN_MINMAX',
        ],
        ARFLAGS = [
            '/MACHINE:THUMB',
        ],
        LINKFLAGS = [
            '/MACHINE:THUMB',
            '/NODEFAULTLIB:secchk.lib',
            '/NODEFAULTLIB:oldnames.lib',
            '/SUBSYSTEM:WINDOWSCE,5.01',
        ],
        VC80_CPPPATH = [
            '$PRIVATE_THIRD_PARTY_DIR/atlmfc_vc80ce/files/include',
            '$PRIVATE_THIRD_PARTY_DIR/vc_80ce/files/include',
# Visual Studio must be setup before the PocketPC SDK.
            '$PRIVATE_THIRD_PARTY_DIR/pocketpc_sdk_ce_50/files/include/armv4i',
        ],
        VC80_LIBPATH = [
            '$PRIVATE_THIRD_PARTY_DIR/atlmfc_vc80ce/files/lib/armv4i',
            '$PRIVATE_THIRD_PARTY_DIR/vc_80ce/files/lib/armv4i',
            '$PRIVATE_THIRD_PARTY_DIR/pocketpc_sdk_ce_50/files/lib/armv4i',
        ],
    )

  if env['MODE'] == 'dbg':
    env.Append(
        CPPFLAGS = [
          '/MTd',
        ],
    )
  else:  # MODE=opt
    env.Append(
        CPPFLAGS = [
          '/MT',
          '/O2',
        ],
        LINKFLAGS = [
          '/INCREMENTAL:NO',
          '/OPT:REF',
          '/OPT:ICF',
        ],
    )
#--------------------------- LINUX ---------------------------
elif env['OS'] == 'linux':
  env.Append(
      CPPDEFINES = [
          'LINUX',
      ],
      CPPPATH = [
          '$THIRD_PARTY_DIR/gtk/include/gtk-2.0',
          '$THIRD_PARTY_DIR/gtk/include/atk-1.0',
          '$THIRD_PARTY_DIR/gtk/include/glib-2.0',
          '$THIRD_PARTY_DIR/gtk/include/pango-1.0',
          '$THIRD_PARTY_DIR/gtk/include/cairo',
          '$THIRD_PARTY_DIR/gtk/lib/gtk-2.0/include',
          '$THIRD_PARTY_DIR/gtk/lib/glib-2.0/include',
      ],
      CCFLAGS = [
          '-fPIC',
          '-fmessage-length=0',
          '-Wall',
          '-Werror',
# NS_LITERAL_STRING does not work properly without this compiler option
          '-fshort-wchar',
# Additions to compile on hardy
          '-Wno-unused-variable',
          '-Wno-missing-braces',
          '-Wno-address',
          '-m32',
      ],
      CXXFLAGS = [
          '-fno-exceptions',
          '-fno-rtti',
          '-Wno-non-virtual-dtor',
          '-Wno-ctor-dtor-privacy',
          '-funsigned-char',
          '-Wno-char-subscripts',
      ],
      LINKFLAGS = [
          '-fPIC',
          '-Bsymbolic',
          '-pthread',

# TODO: Following are DLLFLAGS.  Figure something out for non-lib targets.
          '-shared',
          '-Wl,--version-script',
          '-Wl,$OPEN_DIR/tools/xpcom-ld-script',
# for PortAudio: need pthread and math
          '-lpthread',
          '-lm',
# Additions to compile on hardy
          '-m32',
      ],
  )
  if env['MODE'] == 'dbg':
    env.Append(
      CPPFLAGS = [
          '-g',
          '-O0',
      ],
    )
  else:  # MODE=opt
    env.Append(
      CPPFLAGS = [
          '-O2',
      ],
    )
#--------------------------- OSX ---------------------------
elif env['OS'] == 'osx':
# Gears uses the 10.4 SDK, so we need to build with g++-4.0.
# Chrome uses g++-4.2 so we override this here.
  env['CC'] = 'gcc-4.0'
  env['CXX'] = 'g++-4.0'
# Compile assembly files with the same command line as C files.
  env['ASCOM'] = '$CCCOM'
  
  env.Append(OSX_SDK_ROOT = '/Developer/SDKs/MacOSX10.4u.sdk')

  env.Append(
      CPPDEFINES = [
          'OSX',
          'OS_MACOSX',
# for breakpad
          'USE_PROTECTED_ALLOCATIONS=1',
      ],
      CPPPATH = [
# Breakpad assumes it is in the include path
          '$THIRD_PARTY_DIR/breakpad_osx/src',
      ],
      CCFLAGS = [
           '-mmacosx-version-min=10.4',
          ('-arch', 'ppc'),
          ('-arch', 'i386'),
          '-fPIC',
          '-fmessage-length=0',
# TODO
#          '-Wall',
# NS_LITERAL_STRING does not work properly without this compiler option
          '-fshort-wchar',
          '-fvisibility=hidden',
# Breakpad on OSX needs debug symbols to use the STABS format, rather than the
# default DWARF debug symbols format. Note that we enable gstabs for debug &
# opt; we strip them later in opt.
          '-gstabs+',
      ],
      CXXFLAGS = [
          '-fvisibility-inlines-hidden',
          '-fno-exceptions',
          '-fno-rtti',
          ('-Wall',
           '-Wno-non-virtual-dtor',
           '-Wno-ctor-dtor-privacy',
           '-Wno-char-subscripts',
# When a function is deprecated in gcc, it stupidly warns about all functions
# and member functions that have the same name, regardless of signature.
# Example: Standard osx headers deprecate 'SetPort', which causes a warning for
# url_canon::Replacements::SetPort().
           '-Wno-deprecated-declarations',
          ),
          '-funsigned-char',
          ('-include', env.File('#/$OPEN_DIR/base/safari/prefix_header.h').abspath),
          ('-isysroot', '$OSX_SDK_ROOT')
      ],
      LINKFLAGS = [
           '-mmacosx-version-min=10.4',
           '-fPIC',
           '-Bsymbolic',
           ('-arch', 'ppc'),
           ('-arch', 'i386'),
           ('-isysroot', '$OSX_SDK_ROOT'),
           '-Wl,-dead_strip',
          '-bundle',  # DLLFLAGS
      ],
      FRAMEWORKS = [
          'Carbon',
          'CoreServices',
          'Cocoa',
          'WebKit',
      ],
      M4FLAGS = [
          '-DGEARS_ENABLER_PATH="$INSTALLER_OUTDIR/Safari/GearsEnabler"',
          '-DGEARS_PLUGIN_PATH="$INSTALLER_OUTDIR/Safari/Gears.plugin"',
          '-DGEARS_INSTALLER_OUT_DIR="$INSTALLER_OUTDIR/Safari"',
      ],
  )
  if not env['OFFICIAL_BUILD']:
    # For PortAudio:
    env.Append(FRAMEWORKS = [
        'CoreAudio',
        'AudioToolbox',
        'AudioUnit',
    ])
  if env['MODE'] == 'dbg':
    env.Append(
        CPPFLAGS = [
            '-g',
            '-O0',
        ],
    )
  else:  # MODE=opt
    env.Append(
        CPPFLAGS = [
            '-O2',
        ],
    )

# TODO(mpcomplete): fix this and properly separate our DLL flags from EXE
# flags.
env.Append(SHLINKFLAGS = ['$LINKFLAGS'])
if env['OS'] in ['wince', 'win32']:
  env.Append(SHLINKFLAGS = ['/DLL'])

# Custom builder to work around a scons and/or hammer bug.  ComponentLibrary
# tries to install the library to COMPONENT_LIBRARY_DIR, but since we overrode
# that value, scons gets confused.  I'm not sure who is at fault here.
# See http://code.google.com/p/chromium/issues/detail?id=4177.
def GearsStaticLibrary(env, *args, **kw):
  lib = env.ChromeStaticLibrary(*args, **kw)
  env.Install('$COMPONENT_LIBRARY_DIR', lib[0])
  return lib
env.AddMethod(GearsStaticLibrary)

# Load all the components

sconscripts = [
    'SConscript.googleurl',
    'SConscript.libjpeg',
    'SConscript.libpng',
    'SConscript.libmozjs',
    'SConscript.sqlite',
    'SConscript.zlib',
    'SConscript.libbreakpad_osx',
    'SConscript.libgd',
    'SConscript.portaudio',
]

#if os.path.exists(env.Entry('#/$PRIVATE_DIR/SConscript').abspath):
#  env = env.SConscript('#/$PRIVATE_DIR/SConscript',
#      exports=['env', 'env_res'])

# Include the input file list.
env = env.SConscript('SConscript.inputs', exports=['env'])

for each in sconscripts:
  env.SConscript(each,
                 exports=['env'],
                 variant_dir='$COMMON_OUTDIR',
                 duplicate=0)

# Must come before SConscript.browser because it Imports targets from this
# SConscript.
env.SConscript('SConscript.common',
               exports=['env'],
               variant_dir='$COMMON_OUTDIR',
               duplicate=0)

browsers = [env['BROWSER']]
if browsers[0] == 'all':
  browsers = env['VALID_BROWSERS']
print 'Building:', browsers

for each in browsers:
  env.Replace(BROWSER = each)
  env.SConscript('SConscript.browser',
                 exports=['env'],
                 variant_dir='$BROWSER_OUTDIR',
                 duplicate=0)

# Note: even though the installers write to $INSTALLER_OUTDIR, they need to
# read files from other dirs, so we give them a variant_dir at the toplevel.
env.SConscript('SConscript.installers',
               exports=['env'],
               variant_dir='$BASE_OUTDIR',
               duplicate=0)

env.Alias('gears-installers', 'gears')