# -*- mode: python -*-

Import([
    "get_option",
    "env",
])

env = env.Clone()
env.InjectThirdParty(libraries=['zlib'])
env.InjectThirdParty(libraries=['icu'])

env['CCFLAGS_WERROR'] = []


def removeIfPresent(lst, item):
    try:
        lst.remove(item)
    except ValueError:
        pass


for to_remove in ['-Wall', '-W', '/W3', '-Wsign-compare', '/permissive-']:
    removeIfPresent(env['CCFLAGS'], to_remove)

# See what -D's show up in make.  The AB_CD one might change, but we're little
# endian only for now so I think it's sane
env.Prepend(CPPDEFINES=[
    ('IMPL_MFBT', 1),
    ('JS_USE_CUSTOM_ALLOCATOR', 1),
    ('STATIC_JS_API', 1),
    ('U_NO_DEFAULT_INCLUDE_UTF_HEADERS', 1),
    ('UCONFIG_NO_BREAK_ITERATION', 1),
    ('UCONFIG_NO_FORMATTING', 1),
    ('UCONFIG_NO_TRANSLITERATION', 1),
    ('UCONFIG_NO_REGULAR_EXPRESSIONS', 1),
    ('U_CHARSET_IS_UTF8', 1),
    ('U_DISABLE_RENAMING', 1),
    ('U_STATIC_IMPLEMENTATION', 1),
    ('U_USING_ICU_NAMESPACE', 0),
])

if get_option('spider-monkey-dbg') == "on":
    env.Prepend(CPPDEFINES=[
        'DEBUG',
        'JS_DEBUG',
        'JS_GC_ZEAL',
    ])

env.Append(FORCEINCLUDES=['js-confdefs.h'], )

if env.TargetOSIs('windows'):
    env.Append(
        CCFLAGS=[
            # The default MSVC preprocessor elides commas in some cases as a convenience, but this
            # behavior breaks compilation of jspubtd.h. Enabling the newer preprocessor fixes the
            # # problem.
            '/Zc:preprocessor',

            # Compiling with /Zc:preprocessor causes warnings for some non-standard behavior in
            # # Windows system header files. We ignore these warnings so that they don't cause the
            # build to fail.
            '/wd5104',
            '/wd5105',

            # 'declaration' : no matching operator delete found; memory will not be freed if
            # initialization throws an exception
            '/wd4291',

            # name" : the inline specifier cannot be used when a friend declaration refers to a
            # specialization of a function template
            '/wd4396',

            # nonstandard extension used : zero-sized array in struct/union
            '/wd4200',

            # 'identifier' : no suitable definition provided for explicit template instantiation
            # request
            '/wd4661',

            # 'operation' : unsafe mix of type 'type' and type 'type' in operation
            '/wd4805',

            # 'reinterpret_cast': conversion from 'type' to 'type' of greater size
            '/wd4312',

            # 'operator': unsafe use of type 'type' in operation
            '/wd4804',

            # not enough arguments for function-like macro invocation
            '/wd4003',
        ], )
else:
    env.Append(CXXFLAGS=[
        '-Wno-non-virtual-dtor',
        '-Wno-invalid-offsetof',
        '-Wno-sign-compare',
    ], )

# js/src, js/public and mfbt are the only required sources right now, that
# could change in the future
#
# Also:
# We pre-generate configs for platforms and just check them in.  Running
# mozilla's config requires a relatively huge portion of their tree.
env.Prepend(CPPPATH=[
    'extract/js/src',
    'extract/js/src/jit',
    'extract/js/src/gc',
    'extract/mfbt',
    'extract/intl/icu/source/common',
    'include',
    'mongo_sources',
    'platform/' + env["TARGET_ARCH"] + "/" + env["TARGET_OS"] + "/build",
    'platform/' + env["TARGET_ARCH"] + "/" + env["TARGET_OS"] + "/include",
])

sources = [
    "mongo_sources/mongoErrorReportToString.cpp",
    "mongo_sources/freeOpToJSContext.cpp",
    "extract/js/src/builtin/RegExp.cpp",
    "extract/js/src/vm/ProfilingStack.cpp",
    "extract/js/src/frontend/Parser.cpp",
    "extract/js/src/gc/StoreBuffer.cpp",
    "extract/js/src/jsmath.cpp",
    "extract/js/src/mfbt/Unified_cpp_mfbt0.cpp",
    "extract/js/src/mfbt/Unified_cpp_mfbt1.cpp",
    "extract/js/src/util/DoubleToString.cpp",
    "extract/js/src/vm/Interpreter.cpp",
    "extract/mfbt/lz4/lz4.c",
    "extract/mfbt/lz4/lz4frame.c",
    "extract/mfbt/lz4/lz4hc.c",
    "extract/mfbt/lz4/xxhash.c",
    "extract/mozglue/misc/AutoProfilerLabel.cpp",
    "extract/mozglue/misc/AwakeTimeStamp.cpp",
    "extract/mozglue/misc/MmapFaultHandler.cpp",
    "extract/mozglue/misc/Printf.cpp",
    "extract/mozglue/misc/SIMD.cpp",
    "extract/mozglue/misc/StackWalk.cpp",
    "extract/mozglue/misc/TimeStamp.cpp",
    "extract/mozglue/misc/Uptime.cpp",
    "extract/js/src/irregexp/imported/regexp-ast.cc",
    "extract/js/src/irregexp/imported/regexp-compiler.cc",
    "extract/js/src/irregexp/RegExpNativeMacroAssembler.cpp",
    "extract/js/src/wasm/WasmCode-platform.cpp",
]

if env['TARGET_ARCH'] == 'x86_64' and not env.TargetOSIs('windows'):
    env.Append(CCFLAGS=['-mavx2'])
    sources.extend(["extract/mozglue/misc/SIMD_avx2.cpp", "extract/mozglue/misc/SSE.cpp"])

if env.TargetOSIs('windows'):
    sources.extend([
        "extract/mozglue/misc/ConditionVariable_windows.cpp",
        "extract/mozglue/misc/Mutex_windows.cpp",
        "extract/mozglue/misc/TimeStamp_windows.cpp",
    ])
else:
    sources.extend([
        "extract/mozglue/misc/ConditionVariable_posix.cpp",
        "extract/mozglue/misc/Mutex_posix.cpp",
        "extract/mozglue/misc/TimeStamp_posix.cpp",
    ])

sources.append([
    "extract/modules/fdlibm/{}".format(f) for f in [
        'e_acos.cpp',
        'e_acosf.cpp',
        'e_acosh.cpp',
        'e_asin.cpp',
        'e_asinf.cpp',
        'e_atan2.cpp',
        'e_atanh.cpp',
        'e_cosh.cpp',
        'e_exp.cpp',
        'e_expf.cpp',
        'e_hypot.cpp',
        'e_log.cpp',
        'e_log10.cpp',
        'e_log2.cpp',
        'e_logf.cpp',
        'e_pow.cpp',
        'e_powf.cpp',
        'e_sinh.cpp',
        'e_sqrtf.cpp',
        'k_cos.cpp',
        'k_cosf.cpp',
        'k_exp.cpp',
        'k_expf.cpp',
        'k_rem_pio2.cpp',
        'k_sin.cpp',
        'k_sinf.cpp',
        'k_tan.cpp',
        'k_tanf.cpp',
        's_asinh.cpp',
        's_atan.cpp',
        's_atanf.cpp',
        's_cbrt.cpp',
        's_ceil.cpp',
        's_ceilf.cpp',
        # 's_copysign.cpp', # Unused file.
        's_cos.cpp',
        's_cosf.cpp',
        's_exp2.cpp',
        's_exp2f.cpp',
        's_expm1.cpp',
        's_fabs.cpp',
        's_fabsf.cpp',
        's_floor.cpp',
        's_floorf.cpp',
        's_log1p.cpp',
        's_nearbyint.cpp',
        's_rint.cpp',
        's_rintf.cpp',
        's_scalbn.cpp',
        's_sin.cpp',
        's_sinf.cpp',
        's_tan.cpp',
        's_tanf.cpp',
        's_tanh.cpp',
        's_trunc.cpp',
        's_truncf.cpp',
    ]
])

if env.TargetOSIs('windows'):
    env.Prepend(CPPDEFINES=[
        ("_CRT_RAND_S", "1"),
        ("NO_COMPUTED_GOTO", 1),
    ])

if env['TARGET_ARCH'] == 'x86_64':
    env.Prepend(CPPDEFINES=[("WASM_HUGE_MEMORY", "1")])

sourceFilePatterns = [
    "/build/*.cpp",
    "/build/jit/*.cpp",
    "/build/gc/*.cpp",
    "/build/util/*.cpp",
    "/build/wasm/*.cpp",
    "/build/irregexp/*.cpp",
    "/build/debugger/*.cpp",
    "/build/frontend/*.cpp",
]

for srcPattern in sourceFilePatterns:
    sources.extend(Glob('platform/' + env["TARGET_ARCH"] + "/" + env["TARGET_OS"] + srcPattern))

# All of those unified sources come in from configure.  The files don't
# actually build individually anymore.
env.Library(
    target="mozjs",
    source=sources,
    LIBDEPS_TAGS=[
        # Depends on allocation symbols defined elsewhere
        'illegal_cyclic_or_unresolved_dependencies_allowlisted',
    ],
    LIBDEPS=[
        '$BUILD_DIR/third_party/shim_icu',
        '$BUILD_DIR/third_party/shim_zlib',
    ],
)

#########################
env = env.Clone()

# The below list of defines are used to configure ICU. They must be duplicated exactly in every
# library that injects the third-party ICU headers. If this list is changed here, it must be changed
# in other such libraries as well.
env.Append(
    CPPDEFINES=[
        ('UCONFIG_NO_BREAK_ITERATION', 1),
        ('UCONFIG_NO_FORMATTING', 1),
        ('UCONFIG_NO_TRANSLITERATION', 1),
        ('UCONFIG_NO_REGULAR_EXPRESSIONS', 1),
        ('U_CHARSET_IS_UTF8', 1),
        ('U_DISABLE_RENAMING', 1),
        ('U_STATIC_IMPLEMENTATION', 1),
        ('U_USING_ICU_NAMESPACE', 0),
    ], )

if env.TargetOSIs('solaris'):
    # On Solaris, compile of certain files fails if the below define is not enabled.  Specifically,
    # files that include "source/common/uposixdefs.h" will have _XOPEN_SOURCE=600 and
    # _XOPEN_SOURCE_EXTENDED=1 defined by default; if the file also includes <sys/feature_tests.h>,
    # then the application is assumed to conform to the XPG4v2 specification, which generates an
    # error because XPG4v2 programs are incompatible with C99. If we keep _XOPEN_SOURCE=600 but
    # force _XOPEN_SOURCE_EXTENDED=0, then <sys/feature_tests.h> chooses XPG6, which resolves the
    # error (since XPG6 is compatible with C99).
    env.Append(CPPDEFINES=[
        ('_XOPEN_SOURCE_EXTENDED', 0),
    ], )


def removeIfPresent(lst, item):
    try:
        lst.remove(item)
    except ValueError:
        pass


env['CCFLAGS_WERROR'] = []
for to_remove in ['-Wall', '-W']:
    removeIfPresent(env['CCFLAGS'], to_remove)

# Suppress sign-compare warnings.
if env.ToolchainIs('clang', 'GCC'):
    env.Append(CCFLAGS=['-Wno-sign-compare'])

if env.TargetOSIs('windows'):
    # C4996: '...': was declared deprecated
    env.Append(CCFLAGS=['/wd4996'])

# Suppress `register` keyword warnings in FreeBSD builds

if env.TargetOSIs('freebsd'):
    env.Append(CCFLAGS=['-Wno-error=register'])
    env.Append(CCFLAGS=['-Wno-register'])
