# -*- mode: python -*-

Import("endian")
Import("env")
Import("get_option")
Import("has_option")
Import("use_system_version_of_library")

env = env.Clone()

env.InjectThirdParty('asio')

env.SConscript(
    dirs=[
        'cmdline_utils',
        'concurrency',
        'net',
        'options_parser',
    ],
    exports=[
        'env',
    ],
)

env.Library(
    target='version_impl',
    source=[
        'version_impl.cpp',
    ],
    LIBDEPS=[
        '$BUILD_DIR/mongo/base',
    ]
)

env.Library(
    target='intrusive_counter',
    source=[
        'intrusive_counter.cpp',
        ],
    LIBDEPS=[
        '$BUILD_DIR/mongo/base',
        ]
    )

env.Library(
    target='log_and_backoff',
    source= [
        'log_and_backoff.cpp',
    ],
    LIBDEPS=[
        '$BUILD_DIR/mongo/base',
    ],
)

env.Library(
    target='regex_util',
    source= [
        'regex_util.cpp',
    ],
    LIBDEPS=[
        '$BUILD_DIR/mongo/base',
    ],
)

debuggerEnv = env.Clone()
if has_option("gdbserver"):
    debuggerEnv.Append(CPPDEFINES=["USE_GDBSERVER"])

debuggerEnv.Library(
    target='debugger',
    source=[
        'debugger.cpp',
        ],
    LIBDEPS=[
        # NOTE: You *must not* add any library dependencies to the debugger library
    ],
    LIBDEPS_TAGS=[
        'init-no-global-side-effects',
    ]
)

env.Library(
    target='summation',
    source=[
        'summation.cpp',
    ],
    LIBDEPS=[
        '$BUILD_DIR/mongo/base',
    ],
)

env.Library(
    target='progress_meter',
    source=[
        'progress_meter.cpp',
        'thread_safe_string.cpp',
    ],
    LIBDEPS=[
        '$BUILD_DIR/mongo/base',
    ],
)

env.Library(
    target='md5',
    source=[
        'md5.cpp',
        'password_digest.cpp',
    ],
)

env.Library(
    target='clock_source_mock',
    source=[
        'clock_source_mock.cpp'
    ],
    LIBDEPS=[
        '$BUILD_DIR/mongo/base',
    ],
)

env.Library(
    target='alarm',
    source=[
        'alarm.cpp',
        'alarm_runner_background_thread.cpp',
    ],
    LIBDEPS=[
        'clock_sources',
        '$BUILD_DIR/mongo/base',
    ],
)

env.Library(
    target="processinfo",
    source=[
        "processinfo.cpp",
        "processinfo_${TARGET_OS}.cpp",
    ],
    LIBDEPS=[
        "$BUILD_DIR/mongo/base",
    ],
)

env.Library(
    target="fail_point",
    source=[
        "fail_point.cpp",
        "fail_point_registry.cpp",
        "fail_point_service.cpp",
        env.Idlc('fail_point_server_parameter.idl')[0],
    ],
    LIBDEPS=[
        "$BUILD_DIR/mongo/base",
        "$BUILD_DIR/mongo/bson/util/bson_extract",
        "$BUILD_DIR/mongo/idl/server_parameter",
    ],
)

env.Library(
    target="periodic_runner",
    source=[
        "periodic_runner.cpp",
    ],
    LIBDEPS=[
        "$BUILD_DIR/mongo/base",
    ],
)

env.Library(
    target="periodic_runner_impl",
    source=[
        "periodic_runner_impl.cpp",
    ],
    LIBDEPS=[
        "$BUILD_DIR/mongo/base",
        "$BUILD_DIR/mongo/db/service_context",
        "periodic_runner",
    ],
)

env.Library(
    target='periodic_runner_factory',
    source=[
        'periodic_runner_factory.cpp',
    ],
    LIBDEPS=[
        "$BUILD_DIR/mongo/db/service_context",
        'periodic_runner',
        'periodic_runner_impl',
    ],
)

env.Library(
    target='background_job',
    source=[
        "background.cpp",
    ],
    LIBDEPS=[
        '$BUILD_DIR/mongo/base',
        'concurrency/spin_lock',
    ],
)

if env['MONGO_ALLOCATOR'] in ['tcmalloc', 'tcmalloc-experimental']:
    tcmspEnv = env.Clone()

    if not use_system_version_of_library('tcmalloc'):

        # Add in the include path for our vendored tcmalloc.
        tcmspEnv.InjectThirdParty('gperftools')

        # If our changes to tcmalloc are ever upstreamed, this should become set based on a top
        # level configure check, though its effects should still be scoped just to these files.
        tcmspEnv.Append(
            CPPDEFINES=[
                'MONGO_HAVE_GPERFTOOLS_GET_THREAD_CACHE_SIZE',
                'MONGO_HAVE_GPERFTOOLS_SIZE_CLASS_STATS'
            ]
        )

    if not use_system_version_of_library('valgrind'):
        # Include valgrind since tcmalloc disables itself while running under valgrind
        tcmspEnv.InjectThirdParty('valgrind')

    tcmspEnv.Library(
        target='tcmalloc_set_parameter',
        source=[
            'tcmalloc_server_status_section.cpp',
            'tcmalloc_set_parameter.cpp',
            env.Idlc('tcmalloc_parameters.idl')[0],
            'heap_profiler.cpp',
        ],
        LIBDEPS=[
            '$BUILD_DIR/mongo/transport/service_executor',
        ],
        LIBDEPS_PRIVATE=[
            '$BUILD_DIR/mongo/db/commands/server_status',
            '$BUILD_DIR/mongo/idl/server_parameter',
            'processinfo',
        ],
        PROGDEPS_DEPENDENTS=[
            '$BUILD_DIR/mongo/mongod',
            '$BUILD_DIR/mongo/mongos',
        ],
    )

env.Library(
    target='winutil',
    source=[
        'winutil.cpp',
    ],
)

env.Library(
    target='ntservice',
    source=[
        'ntservice.cpp',
    ],
    LIBDEPS=[
        'signal_handlers',
        '$BUILD_DIR/mongo/util/options_parser/options_parser',
    ],
)

env.Library(
    target='clock_sources',
    source=[
        'background_thread_clock_source.cpp',
        'clock_source.cpp',
        'fast_clock_source_factory.cpp',
    ],
    LIBDEPS=[
        '$BUILD_DIR/mongo/base',
    ],
)

if get_option('use-diagnostic-latches') == 'on':
    env.Library(
        target='diagnostic_info',
        source= [
            'diagnostic_info.cpp',
        ],
        LIBDEPS=[
            '$BUILD_DIR/mongo/base',
            "$BUILD_DIR/mongo/db/service_context",
        ],
    )

    env.Library(
        target='latch_analyzer',
        source= [
            'latch_analyzer.cpp',
        ],
        LIBDEPS=[
            '$BUILD_DIR/mongo/base',
            '$BUILD_DIR/mongo/db/commands/test_commands_enabled',
            '$BUILD_DIR/mongo/db/service_context',
        ],
        LIBDEPS_PRIVATE=[
            '$BUILD_DIR/mongo/db/commands/server_status',
        ],
    )

env.Benchmark(
    target='clock_source_bm',
    source=[
        'clock_source_bm.cpp',
    ],
    LIBDEPS=[
        'clock_sources',
        'processinfo',
    ],
)

env.Library(
    target='elapsed_tracker',
    source=[
        'elapsed_tracker.cpp',
    ],
    LIBDEPS=[
        '$BUILD_DIR/mongo/base',
        'net/network', # this is for using listener to check elapsed time
    ],
)

quick_exit_env = env.Clone()
if has_option('gcov'):
    quick_exit_env.Append(
        CPPDEFINES=[
            'MONGO_GCOV',
        ],
    )

if has_option('use-cpu-profiler'):
    quick_exit_env.Append(
        CPPDEFINES=[
            'MONGO_CPU_PROFILER',
        ],
    )

    if not use_system_version_of_library('tcmalloc'):
        quick_exit_env.InjectThirdParty(
            'gperftools'
        )

quick_exit_env.Library(
    target='quick_exit',
    source=[
        'quick_exit.cpp',
    ],
    LIBDEPS=[
        # NOTE: You *must not* add any other library dependencies to
        # the quick_exit library
        "$BUILD_DIR/third_party/shim_allocator",
    ]
)
env.Library(
    target="secure_compare_memory",
    source=[
        'secure_compare_memory.cpp',
    ],
    LIBDEPS=[
        "$BUILD_DIR/mongo/base",
    ],
)

env.Library(
    target='dns_query',
    source=[
        'dns_query.cpp',
    ],
    LIBDEPS_PRIVATE=[
        "$BUILD_DIR/mongo/base",
    ],
)

env.Library(
    target="secure_zero_memory",
    source=[
        'secure_zero_memory.cpp',
    ],
    LIBDEPS=[
        "$BUILD_DIR/mongo/base",
    ],
)

env.Library(
    target="signal_handlers",
    source=[
        "signal_handlers.cpp",
        "signal_win32.cpp",
    ],
    LIBDEPS=[
        "$BUILD_DIR/mongo/base",
        "$BUILD_DIR/mongo/db/log_process_details",
        "$BUILD_DIR/mongo/db/service_context",
        "$BUILD_DIR/mongo/db/server_options_core",
    ],
)

env.Library(
    target='safe_num',
    source=[
        'safe_num.cpp',
    ],
    LIBDEPS=[
        '$BUILD_DIR/mongo/base',
    ],
)

env.Library(
    target='password',
    source=[
        'password.cpp',
        env.Idlc('password_params.idl')[0],
    ],
    LIBDEPS=[
        '$BUILD_DIR/mongo/base',
    ],
    LIBDEPS_PRIVATE=[
        '$BUILD_DIR/mongo/idl/server_parameter',
    ]
)


env.Benchmark(
    target='decimal_counter_bm',
    source=[
        'decimal_counter_bm.cpp',
    ],
    LIBDEPS=[
    ],
)

env.Benchmark(
    target='future_bm',
    source=[
        'future_bm.cpp',
    ],
    LIBDEPS=[
    ],
)

env.Benchmark(
    target='hash_table_bm',
    source='hash_table_bm.cpp',
    LIBDEPS=[
    ],
)

if env.TargetOSIs('linux'):
    env.Library(
        target='procparser',
        source=[
            "procparser.cpp",
        ],
        LIBDEPS=[
            '$BUILD_DIR/mongo/base',
        ],
    )

if env.TargetOSIs('windows'):
    env.Library(
        target='perfctr_collect',
        source=[
            "perfctr_collect.cpp",
        ],
        LIBDEPS=[
            '$BUILD_DIR/mongo/base',
        ],
    )

icuEnv = env.Clone()

if not use_system_version_of_library("icu"):
    generateICUInit = icuEnv.Command(
        target="icu_init.cpp",
        source=[
            "generate_icu_init_cpp.py",
            ("$BUILD_DIR/third_party/icu4c-57.1/source/mongo_sources/icudt57l.dat"
                if endian == "little"
                else "$BUILD_DIR/third_party/icu4c-57.1/source/mongo_sources/icudt57b.dat"),
        ],
        action="$PYTHON ${SOURCES[0]} -o $TARGET -i ${SOURCES[1]}",
    )
    icuEnv.Alias("generated-sources", generateICUInit)

    icuEnv.InjectThirdParty("icu")
    # Since we are injecting the third-party ICU headers, we must also copy the same defines that we
    # use to configure ICU when building ICU sources. See comment in
    # src/third_party/icu4c-57.1/source/SConscript.
    icuEnv.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),
        ],
    )

# When using ICU from third_party, icu_init.cpp will load a subset of
# ICU's data files using udata_setCommonData() in an initializer.
# When using the system ICU, we rely on those files being in the install path.
icuEnv.Library(
    target='icu_init',
    source=[
        'icu_init.cpp' if not use_system_version_of_library('icu') else 'icu_init_stub.cpp',
    ],
    LIBDEPS_PRIVATE=[
        '$BUILD_DIR/mongo/base',
        '$BUILD_DIR/third_party/shim_icu',
    ],
)

icuEnv.Library(
    target='icu',
    source=[
        'icu.cpp',
    ],
    LIBDEPS_PRIVATE=[
        'icu_init',
        '$BUILD_DIR/mongo/base',
        '$BUILD_DIR/third_party/shim_icu',
    ],
)

icuEnv.CppUnitTest(
    target='util_test',
    source=[
        'alarm_test.cpp',
        'assert_util_test.cpp',
        'background_job_test.cpp',
        'background_thread_clock_source_test.cpp',
        'base64_test.cpp',
        'clock_source_mock_test.cpp',
        'concepts_test.cpp',
        'container_size_helper_test.cpp',
        'decimal_counter_test.cpp',
        'decorable_test.cpp',
        'diagnostic_info_test.cpp' if get_option('use-diagnostic-latches') == 'on' else [],
        'dns_name_test.cpp',
        'dns_query_test.cpp',
        'duration_test.cpp',
        'errno_util_test.cpp',
        'fail_point_test.cpp',
        'future_test_edge_cases.cpp',
        'future_test_executor_future.cpp',
        'future_test_future_int.cpp',
        'future_test_future_move_only.cpp',
        'future_test_future_void.cpp',
        'future_test_promise_int.cpp',
        'future_test_promise_void.cpp',
        'future_test_shared_future.cpp',
        'hierarchical_acquisition_test.cpp',
        'icu_test.cpp',
        'static_immortal_test.cpp',
        'invalidating_lru_cache_test.cpp',
        'itoa_test.cpp',
        'latch_analyzer_test.cpp' if get_option('use-diagnostic-latches') == 'on' else [],
        'lockable_adapter_test.cpp',
        'lru_cache_test.cpp',
        'md5_test.cpp',
        'md5main.cpp',
        'periodic_runner_impl_test.cpp',
        'processinfo_test.cpp',
        'procparser_test.cpp' if env.TargetOSIs('linux') else [],
        'producer_consumer_queue_test.cpp',
        'progress_meter_test.cpp',
        'registry_list_test.cpp',
        'represent_as_test.cpp',
        'safe_num_test.cpp',
        'secure_zero_memory_test.cpp',
        'signal_handlers_synchronous_test.cpp' if not env.TargetOSIs('windows') else [],
        'str_test.cpp',
        'string_map_test.cpp',
        'strong_weak_finish_line_test.cpp',
        'summation_test.cpp',
        'text_test.cpp',
        'tick_source_test.cpp',
        'time_support_test.cpp',
        'unique_function_test.cpp',
        'unowned_ptr_test.cpp',
    ],
    LIBDEPS=[
        '$BUILD_DIR/mongo/base',
        '$BUILD_DIR/mongo/db/service_context',
        '$BUILD_DIR/mongo/db/service_context_test_fixture',
        'alarm',
        'background_job',
        'clock_source_mock',
        'clock_sources',
        'diagnostic_info' if get_option('use-diagnostic-latches') == 'on' else [],
        'dns_query',
        'fail_point',
        'icu',
        'latch_analyzer' if get_option('use-diagnostic-latches') == 'on' else [],
        'md5',
        'periodic_runner_impl',
        'processinfo',
        'procparser' if env.TargetOSIs('linux') else [],
        'progress_meter',
        'safe_num',
        'secure_zero_memory',
        'summation',
    ],
)

if env.TargetOSIs('windows'):
    env.CppUnitTest(
        target='util_windows_test',
        source=[
            'ntservice_test.cpp',
            'perfctr_collect_test.cpp',
        ],
        LIBDEPS=[
            'ntservice',
            'perfctr_collect',
        ],
        LIBS=[
            'shell32',
            env['LIBS']
        ],
    )
