# The keys in sources are the paths to the directories
# the values are an array of source files in those directories to compile
sources = {}
sources['API'] = [
    'API/JSBase.cpp',
    'API/JSCallbackConstructor.cpp',
    'API/JSCallbackFunction.cpp',
    'API/JSCallbackObject.cpp',
    'API/JSClassRef.cpp',
    'API/JSContextRef.cpp',
    'API/JSObjectRef.cpp',
    'API/JSProfilerPrivate.cpp',
    'API/JSStringRef.cpp',
    'API/JSValueRef.cpp',
    'API/OpaqueJSString.cpp',
]
sources['bytecompiler'] = [
    'bytecompiler/BytecodeGenerator.cpp',
]
sources['debugger'] = [
    'debugger/Debugger.cpp',
    'debugger/DebuggerCallFrame.cpp',
]
sources['parser'] = [
    'parser/Lexer.cpp',
    'parser/Nodes.cpp',
    'parser/Parser.cpp',
]
sources['pcre'] = [
    'pcre/pcre_compile.cpp',
    'pcre/pcre_exec.cpp',
    'pcre/pcre_tables.cpp',
    'pcre/pcre_ucp_searchfuncs.cpp',
    'pcre/pcre_xclass.cpp',
]
sources['profiler'] = [
    'profiler/HeavyProfile.cpp',
    'profiler/Profile.cpp',
    'profiler/ProfileGenerator.cpp',
    'profiler/ProfileNode.cpp',
    'profiler/Profiler.cpp',
    'profiler/TreeProfile.cpp',
]
sources['runtime'] = [
    'runtime/ArgList.cpp',
    'runtime/Arguments.cpp',
    'runtime/ArrayConstructor.cpp',
    'runtime/ArrayPrototype.cpp',
    'runtime/BooleanConstructor.cpp',
    'runtime/BooleanObject.cpp',
    'runtime/BooleanPrototype.cpp',
    'runtime/ByteArray.cpp',
    'runtime/CallData.cpp',
    'runtime/Collector.cpp',
    'runtime/Completion.cpp',
    'runtime/CommonIdentifiers.cpp',
    'runtime/ConstructData.cpp',
    'runtime/DateConstructor.cpp',
    'runtime/DateInstance.cpp',
    'runtime/DateMath.cpp',
    'runtime/DatePrototype.cpp',
    'runtime/Error.cpp',
    'runtime/ErrorConstructor.cpp',
    'runtime/ErrorInstance.cpp',
    'runtime/ErrorPrototype.cpp',
    'runtime/ExceptionHelpers.cpp',
    'runtime/FunctionConstructor.cpp',
    'runtime/FunctionPrototype.cpp',
    'runtime/GetterSetter.cpp',
    'runtime/GlobalEvalFunction.cpp',
    'runtime/Identifier.cpp',
    'runtime/InitializeThreading.cpp',
    'runtime/InternalFunction.cpp',
    'runtime/JSActivation.cpp',
    'runtime/JSArray.cpp',
    'runtime/JSByteArray.cpp',
    'runtime/JSCell.cpp',
    'runtime/JSFunction.cpp',
    'runtime/JSGlobalData.cpp',
    'runtime/JSGlobalObject.cpp',
    'runtime/JSGlobalObjectFunctions.cpp',
    'runtime/JSImmediate.cpp',
    'runtime/JSLock.cpp',
    'runtime/JSNotAnObject.cpp',
    'runtime/JSNumberCell.cpp',
    'runtime/JSObject.cpp',
    'runtime/JSPropertyNameIterator.cpp',
    'runtime/JSStaticScopeObject.cpp',
    'runtime/JSString.cpp',
    'runtime/JSValue.cpp',
    'runtime/JSVariableObject.cpp',
    'runtime/JSWrapperObject.cpp',
    'runtime/Lookup.cpp',
    'runtime/MathObject.cpp',
    'runtime/NativeErrorConstructor.cpp',
    'runtime/NativeErrorPrototype.cpp',
    'runtime/NumberConstructor.cpp',
    'runtime/NumberObject.cpp',
    'runtime/NumberPrototype.cpp',
    'runtime/ObjectConstructor.cpp',
    'runtime/ObjectPrototype.cpp',
    'runtime/Operations.cpp',
    'runtime/PropertyNameArray.cpp',
    'runtime/PropertySlot.cpp',
    'runtime/PrototypeFunction.cpp',
    'runtime/RegExp.cpp',
    'runtime/RegExpConstructor.cpp',
    'runtime/RegExpObject.cpp',
    'runtime/RegExpPrototype.cpp',
    'runtime/ScopeChain.cpp',
    'runtime/SmallStrings.cpp',
    'runtime/StringConstructor.cpp',
    'runtime/StringObject.cpp',
    'runtime/StringPrototype.cpp',
    'runtime/Structure.cpp',
    'runtime/StructureChain.cpp',
    'runtime/UString.cpp',
]
sources['bytecode'] = [
    'bytecode/CodeBlock.cpp',
    'bytecode/StructureStubInfo.cpp',
    'bytecode/JumpTable.cpp',
    'bytecode/Opcode.cpp',
    'bytecode/SamplingTool.cpp',
]
sources['interpreter'] = [
    'interpreter/CallFrame.cpp',
    'interpreter/Interpreter.cpp',
    'interpreter/RegisterFile.cpp',
]
sources['jit'] = [
    'jit/ExecutableAllocator.cpp',
    'jit/JIT.cpp',
]
sources['wrec'] = [
    'wrec/CharacterClass.cpp',
    'wrec/CharacterClassConstructor.cpp',
    'wrec/WREC.cpp',
    'wrec/WRECFunctors.cpp',
    'wrec/WRECGenerator.cpp',
    'wrec/WRECParser.cpp',
]
sources['wtf'] = [
    'wtf/Assertions.cpp',
    'wtf/CurrentTime.cpp',
    'wtf/FastMalloc.cpp',
    'wtf/HashTable.cpp',
    'wtf/RandomNumber.cpp',
    'wtf/RefCountedLeakCounter.cpp',
    'wtf/Threading.cpp',
    'wtf/dtoa.cpp',
]
sources['wtf/unicode'] = [
    'wtf/unicode/CollatorDefault.cpp',
    'wtf/unicode/UTF8.cpp',
]
sources['wtf/unicode/icu'] = [
    'wtf/unicode/icu/CollatorICU.cpp',
]

env = Environment()

building_on_win32 = env['PLATFORM'] == 'win32' or env['PLATFORM'] == 'cygwin'

# Scons uses gcc when building under cygwin by default
# We also have to manually force 8.0 or Scons will try and
# look up what version to use using the registry and fail
# due to lack of cygwin-python registry support
if env['PLATFORM'] == 'cygwin':
    env['MSVS_VERSION'] = '8.0'
    # Some systems have PROGRAMFILES, some have ProgramFiles
    # Scons msvc tool only expects 'ProgramFiles'
    import os
    if os.getenv('PROGRAMFILES') and not os.getenv('ProgramFiles'):
        os.environ['ProgramFiles'] = os.getenv('PROGRAMFILES')

    env.Tool('msvc')
    env.Tool('mslink')
    env.Tool('mslib')

# Scons is failing to carry the %PATH% value through correctly
# Hack IncrediBuild into our path so cl.exe doesn't crash
if env['PLATFORM'] == 'win32':
    env.AppendENVPath('PATH', 'c:/Program Files/Xoreax/IncrediBuild')

if env['PLATFORM'] == 'darwin':
    sources['API'].append('API/JSStringRefCF.cpp')
    sources['profiler'].append('profiler/ProfilerServer.mm')
    sources['wtf'].append('wtf/ThreadingPthreads.cpp')
    sources['wtf'].append('wtf/MainThread.cpp')
    sources['wtf/mac'] = ['wtf/mac/MainThreadMac.mm']
    sources['wtf'].append('wtf/TCSystemAlloc.cpp')
    sources['jit'].append('jit/ExecutableAllocatorPosix.cpp')
elif building_on_win32:
    sources['wtf'].append('wtf/ThreadingNone.cpp')
    sources['jit'].append('jit/ExecutableAllocatorWin.cpp')
    env.Append(CPPDEFINES = ['ENABLE_JSC_MULTIPLE_THREADS=0'])

derived_sources_path = 'DerivedSources/JavaScriptCore/'
def DerivedSources(path):
    return derived_sources_path + path

derived_sources_results = map(DerivedSources, [
    'ArrayPrototype.lut.h',
    'DatePrototype.lut.h',
    'MathObject.lut.h',
    'NumberConstructor.lut.h',
    'RegExpConstructor.lut.h',
    'RegExpObject.lut.h',
    'StringPrototype.lut.h'
    'chartables.c',
    'grammar.cpp',
    'grammar.h',
    'lexer.lut.h',
])

derived_sources_sources = [
    'runtime/ArrayPrototype.cpp',
    'runtime/DatePrototype.cpp',
    'runtime/MathObject.cpp',
    'runtime/NumberConstructor.cpp',
    'runtime/RegExpConstructor.cpp',
    'runtime/RegExpObject.cpp',
    'runtime/StringPrototype.cpp',
    'parser/Grammar.y',
    'parser/Lexer.cpp',
]

# Generate DerivedSources
# Make sure Windows knows where bash (and all the other cygwin commands) live
if env['PLATFORM'] == 'win32':
    env.AppendENVPath('PATH', 'C:/cygwin/bin')
env.Command(derived_sources_results, derived_sources_sources, 'bash make-generated-sources.sh')
sources[derived_sources_path] = [DerivedSources('Grammar.cpp')]

# Handle os-version specific build settings
if env['PLATFORM'] == 'darwin':
    from subprocess import Popen, PIPE
    version_pieces = Popen(["sw_vers", "-productVersion"], stdout = PIPE).communicate()[0].split('.')
    if map(int, version_pieces)[:2] > (10, 5):
        # Dtrace doesn't exist in Tiger, and was broken in Leopard
        env.Command(DerivedSources('TracingDtrace.h'), 'runtime/Tracing.d', '/usr/sbin/dtrace -h -o $TARGET -s $SOURCE')

# This build file builds the Chromium port for now, support for
# others could be added later.
env.Append(CPPDEFINES = ['BUILDING_CHROMIUM__'])

# I'm not certain how many of these windows defines are actually required.
if building_on_win32:
    env.Append(CPPDEFINES = ['_WIN32_WINNT=0x0600', 'WINVER=0x0600', 'WIN32', '_WINDOWS', 'NOMINMAX', 'UNICODE', '_UNICODE', '__STD_C', '_HAS_EXCEPTIONS=0'])

# Scons out-of-the-box only supports precompiled headers for MSVC
# remove this when we fix Scons to understand GCC precompiled headers
if env['CC'] == 'gcc':
    env['CCFLAGS'] = '-include JavaScriptCorePrefix.h'
# Turns out the MSVC PCH support is badly broken
# env['PCH'] = 'JavaScriptCorePrefix.h'
# env['PCHSTOP'] = 'JavaScriptCorePrefix.h'

if env['PLATFORM'] == 'darwin':
    env['FRAMEWORKS'] = ['CoreFoundation', 'Foundation']
    env['LIBS'] = ['icucore']
    # Apple does not ship the ICU headers with Mac OS X, so WebKit includes a copy of 3.2 headers
    env.Append(CPPPATH = 'icu')

webkit_libraries_path = "../WebKitLibraries/win/"
def WebKitLibraries(path):
    return webkit_libraries_path + path

include_paths = ['.', '..', 'ForwardingHeaders'] + sources.keys()
env.Append(CPPPATH = include_paths)
if building_on_win32:
    env.Append(CPPPATH = ['os-win32', WebKitLibraries('include')])
    env.Prepend(LIBPATH = [WebKitLibraries('lib')])
    env.Append(LIBS = ['icuin', 'icuuc', 'user32', 'winmm'])

# Save off a copy of the environment for use with jsc
jsc_env = env.Clone()

if building_on_win32:
    env.StaticLibrary("JavaScriptCore", sources.values())
else:
    env.SharedLibrary("JavaScriptCore", sources.values())


env = jsc_env

# Build the jsc testing shell
shell_sources = ['jsc.cpp']
build_directory = '.' # This should be changed to point to wherever JavaScriptCore gets built to

# It's hacky to re-use the same environment from JavaScriptCore
# but it makes building on windows easier for now
env['CPPPATH'] = include_paths
env['LIBS'] = ['JavaScriptCore']
env['LIBPATH'] = [build_directory]

if env['PLATFORM'] == 'darwin':
    env.Append(LIBS = ['edit'])
    env.Append(CPPPATH = 'icu')
elif building_on_win32:
    env.Append(CPPPATH = ['os-win32', WebKitLibraries('include')])
    env.Prepend(LIBPATH = [WebKitLibraries('lib')])
    env.Append(LIBS = ['icuin', 'icuuc', 'user32', 'winmm'])

env.Program('jsc', shell_sources)
