# Copyright 2008 the V8 project authors. All rights reserved.
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
#     * Redistributions of source code must retain the above copyright
#       notice, this list of conditions and the following disclaimer.
#     * Redistributions in binary form must reproduce the above
#       copyright notice, this list of conditions and the following
#       disclaimer in the documentation and/or other materials provided
#       with the distribution.
#     * Neither the name of Google Inc. nor the names of its
#       contributors may be used to endorse or promote products derived
#       from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

import sys
from os.path import join, dirname, abspath
root_dir = dirname(File('SConstruct').rfile().abspath)
sys.path.append(join(root_dir, 'tools'))
import js2c
Import('context')


SOURCES = {
  'all': [
    'accessors.cc', 'allocation.cc', 'api.cc', 'assembler.cc', 'ast.cc',
    'bootstrapper.cc', 'builtins.cc', 'checks.cc', 'code-stubs.cc',
    'codegen.cc', 'compilation-cache.cc', 'compiler.cc', 'contexts.cc',
    'conversions.cc', 'counters.cc', 'dateparser.cc', 'debug.cc',
    'disassembler.cc', 'execution.cc', 'factory.cc', 'flags.cc', 'frames.cc',
    'global-handles.cc', 'handles.cc', 'hashmap.cc', 'heap.cc', 'ic.cc',
    'interpreter-irregexp.cc', 'jsregexp.cc', 'log.cc', 'mark-compact.cc',
    'messages.cc', 'objects.cc', 'parser.cc', 'property.cc',
    'regexp-macro-assembler.cc', 'regexp-macro-assembler-irregexp.cc',
    'rewriter.cc', 'runtime.cc', 'scanner.cc', 'scopeinfo.cc', 'scopes.cc',
    'serialize.cc', 'snapshot-common.cc', 'spaces.cc', 'string-stream.cc',
    'stub-cache.cc', 'token.cc', 'top.cc', 'unicode.cc', 'usage-analyzer.cc',
    'utils.cc', 'v8-counters.cc', 'v8.cc', 'v8threads.cc', 'variables.cc',
    'zone.cc'
  ],
  'arch:arm':  ['assembler-arm.cc', 'builtins-arm.cc', 'codegen-arm.cc',
      'cpu-arm.cc', 'disasm-arm.cc', 'frames-arm.cc', 'ic-arm.cc',
      'macro-assembler-arm.cc', 'regexp-macro-assembler-arm.cc', 
      'stub-cache-arm.cc'],
  'arch:ia32': ['assembler-ia32.cc', 'builtins-ia32.cc', 'codegen-ia32.cc',
      'cpu-ia32.cc', 'disasm-ia32.cc', 'frames-ia32.cc', 'ic-ia32.cc',
      'macro-assembler-ia32.cc', 'regexp-macro-assembler-ia32.cc',
      'stub-cache-ia32.cc'],
  'simulator:arm': ['simulator-arm.cc'],
  'os:freebsd': ['platform-freebsd.cc'],
  'os:linux':   ['platform-linux.cc'],
  'os:macos':   ['platform-macos.cc'],
  'os:nullos':  ['platform-nullos.cc'],
  'os:win32':   ['platform-win32.cc'],
  'mode:release': [],
  'mode:debug': [
    'objects-debug.cc', 'prettyprinter.cc', 'regexp-macro-assembler-tracer.cc'
  ]
}


D8_FILES = {
  'all': [
    'd8.cc'
  ],
  'console:readline': [
    'd8-readline.cc'
  ]
}


LIBRARY_FILES = '''
runtime.js
v8natives.js
array.js
string.js
uri.js
math.js
messages.js
apinatives.js
debug-delay.js
mirror-delay.js
date-delay.js
regexp-delay.js
'''.split()


JSCRE_FILES = '''
pcre_compile.cpp
pcre_exec.cpp
pcre_tables.cpp
pcre_ucp_searchfuncs.cpp
pcre_xclass.cpp
'''.split()


def Abort(message):
  print message
  sys.exit(1)


def ConfigureObjectFiles():
  env = Environment()
  env.Replace(**context.flags['v8'])
  context.ApplyEnvOverrides(env)
  env['BUILDERS']['JS2C'] = Builder(action=js2c.JS2C)
  env['BUILDERS']['Snapshot'] = Builder(action='$SOURCE $TARGET --logfile "$LOGFILE"')

  # Build the standard platform-independent source files.
  source_files = context.GetRelevantSources(SOURCES)

  d8_files = context.GetRelevantSources(D8_FILES)
  d8_js = env.JS2C('d8-js.cc', 'd8.js', TYPE='D8')
  d8_js_obj = context.ConfigureObject(env, d8_js, CPPPATH=['.'])
  d8_objs = [context.ConfigureObject(env, [d8_files]), d8_js_obj]

  # Combine the JavaScript library files into a single C++ file and
  # compile it.
  library_files = [s for s in LIBRARY_FILES]
  library_files.append('macros.py')
  libraries_src, libraries_empty_src = env.JS2C(['libraries.cc', 'libraries-empty.cc'], library_files, TYPE='CORE')
  libraries_obj = context.ConfigureObject(env, libraries_src, CPPPATH=['.'])

  # Build JSCRE.
  jscre_env = env.Copy()
  jscre_env.Replace(**context.flags['jscre'])
  jscre_files = [join('third_party', 'jscre', s) for s in JSCRE_FILES]
  jscre_obj = context.ConfigureObject(jscre_env, jscre_files)

  # Build dtoa.
  dtoa_env = env.Copy()
  dtoa_env.Replace(**context.flags['dtoa'])
  dtoa_files = ['dtoa-config.c']
  dtoa_obj = context.ConfigureObject(dtoa_env, dtoa_files)

  source_objs = context.ConfigureObject(env, source_files)
  non_snapshot_files = [jscre_obj, dtoa_obj, source_objs]

  # Create snapshot if necessary.
  empty_snapshot_obj = context.ConfigureObject(env, 'snapshot-empty.cc')
  if context.use_snapshot:
    mksnapshot_src = 'mksnapshot.cc'
    mksnapshot = env.Program('mksnapshot', [mksnapshot_src, libraries_obj, non_snapshot_files, empty_snapshot_obj], PDB='mksnapshot.exe.pdb')
    snapshot_cc = env.Snapshot('snapshot.cc', mksnapshot, LOGFILE=File('snapshot.log').abspath)
    snapshot_obj = context.ConfigureObject(env, snapshot_cc, CPPPATH=['.'])
    libraries_obj = context.ConfigureObject(env, libraries_empty_src, CPPPATH=['.'])
  else:
    snapshot_obj = empty_snapshot_obj

  library_objs = [non_snapshot_files, libraries_obj, snapshot_obj]
  return (library_objs, d8_objs)


(library_objs, d8_objs) = ConfigureObjectFiles()
Return('library_objs d8_objs')
