# -*- mode: python; -*-

# This SConscript describes build rules for the "mongo" project.

import itertools
import os
import re
import sys
from buildscripts import utils

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

env = env.Clone()

env.InjectMongoIncludePaths()

# Add needed Percona dependencies
env.InjectThirdPartyIncludePaths(libraries=['percona_incl'])
env.Append(LIBPATH = ['#/src/third_party/install/lib'])

env.SConscript(
    dirs=[
        'base',
        'bson',
        'client',
        'crypto',
        'db',
        'dbtests',
        'embedded',
        'executor',
        'idl',
        'installer',
        'logger',
        'platform',
        'rpc',
        's',
        'scripting',
        'shell',
        'tools',
        'transport',
        'unittest',
        'util',
    ],
    exports=[
        'env',
    ],
)

# NOTE: This library does not really belong here. Its presence here is
# temporary. Do not add to this library, do not remove from it, and do
# not declare other libraries in this file.
env.Library(
    target='base',
    source=[
        'base/data_range.cpp',
        'base/data_range_cursor.cpp',
        'base/data_type.cpp',
        'base/data_type_string_data.cpp',
        'base/data_type_terminated.cpp',
        'base/error_codes.cpp',
        'base/error_extra_info.cpp',
        'base/global_initializer.cpp',
        'base/global_initializer_registerer.cpp',
        'base/init.cpp',
        'base/initializer.cpp',
        'base/initializer_dependency_graph.cpp',
        'base/make_string_vector.cpp',
        'base/parse_number.cpp',
        'base/shim.cpp',
        'base/simple_string_data_comparator.cpp',
        'base/status.cpp',
        'base/string_data.cpp',
        'base/validate_locale.cpp',
        'bson/bson_comparator_interface_base.cpp',
        'bson/bson_depth.cpp',
        'bson/bson_validate.cpp',
        'bson/bsonelement.cpp',
        'bson/bsonmisc.cpp',
        'bson/bsonobj.cpp',
        'bson/bsonobjbuilder.cpp',
        'bson/bsontypes.cpp',
        'bson/json.cpp',
        'bson/oid.cpp',
        'bson/simple_bsonelement_comparator.cpp',
        'bson/simple_bsonobj_comparator.cpp',
        'bson/timestamp.cpp',
        'logger/component_message_log_domain.cpp',
        'logger/console.cpp',
        'logger/log_component.cpp',
        'logger/log_component_settings.cpp',
        'logger/log_manager.cpp',
        'logger/log_severity.cpp',
        'logger/logger.cpp',
        'logger/logstream_builder.cpp',
        'logger/message_event_utf8_encoder.cpp',
        'logger/message_log_domain.cpp',
        'logger/ramlog.cpp',
        'logger/redaction.cpp',
        'logger/rotatable_file_manager.cpp',
        'logger/rotatable_file_writer.cpp',
        'platform/decimal128.cpp',
        'platform/posix_fadvise.cpp',
        'platform/process_id.cpp',
        'platform/random.cpp',
        'platform/shared_library.cpp',
        'platform/shared_library_${TARGET_OS_FAMILY}.cpp',
        'platform/stack_locator.cpp',
        'platform/stack_locator_${TARGET_OS}.cpp',
        'platform/strcasestr.cpp',
        'platform/strnlen.cpp',
        'util/allocator.cpp',
        'util/assert_util.cpp',
        'util/base64.cpp',
        'util/concurrency/idle_thread_block.cpp',
        'util/concurrency/thread_name.cpp',
        'util/duration.cpp',
        'util/errno_util.cpp',
        'util/exception_filter_win32.cpp',
        'util/exit.cpp',
        'util/file.cpp',
        'util/hex.cpp',
        'util/itoa.cpp',
        'util/log.cpp',
        'util/platform_init.cpp',
        'util/signal_handlers_synchronous.cpp',
        'util/stacktrace.cpp',
        'util/stacktrace_${TARGET_OS_FAMILY}.cpp',
        'util/startup_test.cpp',
        'util/stringutils.cpp',
        'util/system_clock_source.cpp',
        'util/system_tick_source.cpp',
        'util/text.cpp',
        'util/time_support.cpp',
        'util/timer.cpp',
        'util/uuid.cpp',
        'util/version.cpp',
    ],
    # NOTE: This library *must not* depend on any libraries than
    # the ones declared here. Do not add to this list.
    LIBDEPS=[
        '$BUILD_DIR/third_party/murmurhash3/murmurhash3',
        '$BUILD_DIR/third_party/shim_allocator',
        '$BUILD_DIR/third_party/shim_boost',
        '$BUILD_DIR/third_party/shim_intel_decimal128',
        '$BUILD_DIR/third_party/shim_pcrecpp',
        'util/quick_exit',
    ],
    LIBDEPS_PRIVATE=[
        'util/debugger',
    ],
)

js_engine_ver = get_option("js-engine") if get_option("server-js") == "on" else "none"

# On windows, we need to escape the backslashes in the command-line
# so that windows paths look okay.
cmd_line = " ".join(sys.argv).encode('string-escape')
if env.TargetOSIs('windows'):
    cmd_line = cmd_line.replace('\\', r'\\')

module_list = '{ %s }' % ', '.join([ '"{0}"'.format(x) for x in env['MONGO_MODULES'] ])

# This generates a numeric representation of the version string so that
# you can easily compare versions of MongoDB without having to parse
# the version string.
#
# The rules for this are
# {major}{minor}{release}{pre/rc/final}
# If the version is pre-release and not an rc, the final number is 0
# If the version is an RC, the final number of 1 + rc number
# If the version is pre-release between RC's, the final number is 1 + rc number
# If the version is a final release, the final number is 99
#
# Examples:
# 3.1.1-123     = 3010100
# 3.1.1-rc2     = 3010103
# 3.1.1-rc2-123 = 3010103
# 3.1.1         = 3010199
#
version_parts = [ x for x in re.match(r'^(\d+)\.(\d+)\.(\d+)-?((?:(rc)(\d+))?.*)?',
    env['MONGO_VERSION']).groups() ]
version_extra = version_parts[3] if version_parts[3] else ""
if version_parts[4] == 'rc':
    version_parts[3] = int(version_parts[5]) + -50
elif version_parts[3]:
    version_parts[2] = int(version_parts[2]) + 1
    version_parts[3] = -100
else:
    version_parts[3] = 0
version_parts = [ int(x) for x in version_parts[:4]]

# This turns the MONGO_BUILDINFO_ENVIRONMENT_DATA tuples into a std::vector of
# std::tuple<string, string, bool, bool>.
buildInfoInitializer = []
for tup in env['MONGO_BUILDINFO_ENVIRONMENT_DATA']:
    def pyToCXXBool(val):
        return "true" if val else "false"
    def wrapInQuotes(val):
        return 'R"raw_delimiter({0})raw_delimiter"'.format(val.replace("\\", r"\\"))
    buildInfoInitializer.append(
        'std::make_tuple({0})'.format(', '.join(
            (
                wrapInQuotes(tup[0]),
                wrapInQuotes(env.subst(tup[1])),
                pyToCXXBool(tup[2]),
                pyToCXXBool(tup[3]),
            )
        ))
    )
buildInfoInitializer = '{{ {0} }}'.format(', '.join(buildInfoInitializer))

generatedVersionFile = env.Substfile(
    'util/version_constants.h.in',
    SUBST_DICT=[
        ('@mongo_version@', env['MONGO_VERSION']),
        ('@mongo_version_major@', version_parts[0]),
        ('@mongo_version_minor@', version_parts[1]),
        ('@mongo_version_patch@', version_parts[2]),
        ('@mongo_version_extra@', version_parts[3]),
        ('@mongo_version_extra_str@', version_extra),
        ('@mongo_git_hash@', env['MONGO_GIT_HASH']),
        ('@buildinfo_js_engine@', js_engine_ver),
        ('@buildinfo_allocator@', env['MONGO_ALLOCATOR']),
        ('@buildinfo_modules@', module_list),
        ('@buildinfo_environment_data@', buildInfoInitializer),
    ])
env.Alias('generated-sources', generatedVersionFile)

if env.TargetOSIs('windows'):
    enterpriseEnv = env.Clone().InjectModule("enterprise")
    generatedResourceConstantFile = enterpriseEnv.Substfile(
        'util/resource_constants.h.in',
        SUBST_DICT=[
            ('@mongo_version@', env['MONGO_VERSION']),
            ('@mongo_version_major@', version_parts[0]),
            ('@mongo_version_minor@', version_parts[1]),
            ('@mongo_version_patch@', version_parts[2]),
            ('@mongo_git_hash@', env['MONGO_GIT_HASH']),
        ])
    env.Alias('generated-sources', generatedResourceConstantFile)

config_header_substs = (
    ('@mongo_config_altivec_vec_vbpermq_output_index@', 'MONGO_CONFIG_ALTIVEC_VEC_VBPERMQ_OUTPUT_INDEX'),
    ('@mongo_config_byte_order@', 'MONGO_CONFIG_BYTE_ORDER'),
    ('@mongo_config_debug_build@', 'MONGO_CONFIG_DEBUG_BUILD'),
    ('@mongo_config_has_ssl_set_ecdh_auto@', 'MONGO_CONFIG_HAS_SSL_SET_ECDH_AUTO'),
    ('@mongo_config_have_execinfo_backtrace@', 'MONGO_CONFIG_HAVE_EXECINFO_BACKTRACE'),
    ('@mongo_config_have_fips_mode_set@', 'MONGO_CONFIG_HAVE_FIPS_MODE_SET'),
    ('@mongo_config_have_header_unistd_h@', 'MONGO_CONFIG_HAVE_HEADER_UNISTD_H'),
    ('@mongo_config_have_memset_s@', 'MONGO_CONFIG_HAVE_MEMSET_S'),
    ('@mongo_config_have_posix_monotonic_clock@', 'MONGO_CONFIG_HAVE_POSIX_MONOTONIC_CLOCK'),
    ('@mongo_config_have_pthread_setname_np@', 'MONGO_CONFIG_HAVE_PTHREAD_SETNAME_NP'),
    ('@mongo_config_have_std_enable_if_t@', 'MONGO_CONFIG_HAVE_STD_ENABLE_IF_T'),
    ('@mongo_config_have_std_make_unique@', 'MONGO_CONFIG_HAVE_STD_MAKE_UNIQUE'),
    ('@mongo_config_have_strnlen@', 'MONGO_CONFIG_HAVE_STRNLEN'),
    ('@mongo_config_max_extended_alignment@', 'MONGO_CONFIG_MAX_EXTENDED_ALIGNMENT'),
    ('@mongo_config_optimized_build@', 'MONGO_CONFIG_OPTIMIZED_BUILD'),
    ('@mongo_config_ssl@', 'MONGO_CONFIG_SSL'),
    ('@mongo_config_ssl_has_asn1_any_definitions@', 'MONGO_CONFIG_HAVE_ASN1_ANY_DEFINITIONS'),
    ('@mongo_config_ssl_provider@', 'MONGO_CONFIG_SSL_PROVIDER'),
    ('@mongo_config_wiredtiger_enabled@', 'MONGO_CONFIG_WIREDTIGER_ENABLED'),
)

def makeConfigHeaderDefine(self, key):
    val = "// #undef {0}".format(key)
    if key in self['CONFIG_HEADER_DEFINES']:
        val = "#define {0} {1}".format(key, self['CONFIG_HEADER_DEFINES'][key])
    return val
env.AddMethod(makeConfigHeaderDefine)

generateConfigHeaderFile = env.Substfile(
    'config.h.in',
    SUBST_DICT=[(k, env.makeConfigHeaderDefine(v)) for (k, v) in config_header_substs]
)
env.Alias('generated-sources', generateConfigHeaderFile)

env.Library(
    target="mongod_options_init",
    source=[
        "db/mongod_options_init.cpp",
    ],
    LIBDEPS=[
        'base',
    ],
    LIBDEPS_PRIVATE=[
        'db/mongod_options',
    ]
)

env.Library(
    target="mongodmain",
    source=[
        "db/db.cpp",
    ],
    LIBDEPS_PRIVATE=[
        'base',
        'db/auth/authmongod',
        'db/catalog/health_log',
        'db/commands/mongod',
        'db/commands/mongod_fcv',
        'db/commands/server_status_servers',
        'db/dbdirectclient',
        'db/ftdc/ftdc_mongod',
        'db/free_mon/free_mon_mongod',
        'db/index_d',
        'db/initialize_snmp',
        'db/keys_collection_client_direct',
        'db/kill_sessions_local',
        'db/logical_session_cache_factory_mongod',
        'db/mongod_options',
        'db/mongodandmongos',
        'db/periodic_runner_job_abort_expired_transactions',
        'db/query_exec',
        'db/repair_database',
        'db/repair_database_and_check_version',
        'db/repl/repl_set_commands',
        'db/repl/storage_interface_impl',
        'db/repl/topology_coordinator',
        'db/s/balancer',
        'db/s/op_observer_sharding_impl',
        'db/s/sharding_runtime_d',
        'db/serveronly',
        'db/service_context_d',
        'db/startup_warnings_mongod',
        'db/system_index',
        'db/ttl_d',
        'executor/network_interface_factory',
        'mongod_options_init',
        'rpc/rpc',
        's/commands/shared_cluster_commands',
        'transport/service_entry_point',
        'transport/transport_layer_manager',
        'util/clock_sources',
        'util/fail_point',
        'util/ntservice',
        'util/options_parser/options_parser_init',
        'util/periodic_runner_factory',
        'util/version_impl',
    ],
)


if env.TargetOSIs('windows'):
    generatedDbManifest = env.Substfile(
        'db/db.manifest.in',
        SUBST_DICT=[
            ('@mongo_version_major@', version_parts[0]),
            ('@mongo_version_minor@', version_parts[1]),
            ('@mongo_version_patch@', version_parts[2]),
            ('@mongo_version_extra@', version_parts[3]),
            ('@mongo_version_extra_str@', version_extra),
        ])

    env.Alias('generated-sources', generatedDbManifest)
    env.Depends("db/db.res", generatedDbManifest)

# Do not discard encryption extension's entry point
env.Append( LINKFLAGS=["-upercona_encryption_extension_init"] );

mongod = env.Program(
    target="mongod",
    source=[
        "db/dbmain.cpp",
    ] + env.WindowsResourceFile("db/db.rc"),
    LIBDEPS=[
        'base',
        'mongodmain',
    ],
    INSTALL_ALIAS=[
        'core',
        'default',
        'servers',
    ],
)

hygienic = get_option('install-mode') == 'hygienic'

if hygienic:
    env.Default('$INSTALL_DIR/bin/mongod$PROGSUFFIX')
else:
    env.Default(env.Install('#/', mongod))

# tools
rewrittenTools = [ "mongodump", "mongorestore", "mongoexport", "mongoimport", "mongostat", "mongotop", "bsondump", "mongofiles" ]

if env.TargetOSIs('windows'):
    generatedServerManifest = env.Substfile(
        's/server.manifest.in',
        SUBST_DICT=[
            ('@mongo_version_major@', version_parts[0]),
            ('@mongo_version_minor@', version_parts[1]),
            ('@mongo_version_patch@', version_parts[2]),
            ('@mongo_version_extra@', version_parts[3]),
            ('@mongo_version_extra_str@', version_extra),
        ])

    env.Alias('generated-sources', generatedServerManifest)
    env.Depends("s/server.res", generatedServerManifest)

# mongos
mongos = env.Program(
    target='mongos',
    source=[
        's/cluster_cursor_stats.cpp',
        's/mongos_options.cpp',
        's/mongos_options_init.cpp',
        's/s_sharding_server_status.cpp',
        's/server.cpp',
        's/service_entry_point_mongos.cpp',
        's/sharding_uptime_reporter.cpp',
        's/version_mongos.cpp',
    ] + env.WindowsResourceFile("s/server.rc"),
    LIBDEPS=[
        'db/auth/authmongos',
        'db/commands/server_status',
        'db/commands/server_status_core',
        'db/commands/server_status_servers',
        'db/curop',
        'db/ftdc/ftdc_mongos',
        'db/logical_time_metadata_hook',
        'db/mongodandmongos',
        'db/server_options',
        'db/startup_warnings_common',
        'db/stats/counters',
        's/commands/cluster_commands',
        's/commands/shared_cluster_commands',
        's/committed_optime_metadata_hook',
        's/coreshard',
        's/is_mongos',
        's/sharding_egress_metadata_hook_for_mongos',
        's/sharding_initialization',
        's/query/cluster_cursor_cleanup_job',
        'transport/service_entry_point',
        'transport/transport_layer_manager',
        'util/clock_sources',
        'util/fail_point',
        'util/ntservice',
        'util/options_parser/options_parser_init',
        'util/version_impl',
    ],
    INSTALL_ALIAS=[
        'servers',
    ],
)

if not hygienic:
    env.Install('#/', mongos)

env.Library("linenoise_utf8",
    source=[
        "shell/linenoise_utf8.cpp",
    ])

# --- shell ---

if not has_option('noshell') and usemozjs:
    shell_core_env = env.Clone()
    if has_option("safeshell"):
        shell_core_env.Append(CPPDEFINES=["MONGO_SAFE_SHELL"])
    shell_core_env.Library("shell_core",
                source=[
                    "shell/linenoise.cpp",
                    "shell/mk_wcwidth.cpp",
                    "shell/mongo-server.cpp",
                    "shell/shell_options.cpp",
                    "shell/shell_utils.cpp",
                    "shell/shell_utils_extended.cpp",
                    "shell/shell_utils_launcher.cpp",
                ],
                LIBDEPS=[
                    'db/catalog/index_key_validate',
                    'db/logical_session_id_helpers',
                    'db/mongohasher',
                    'db/query/command_request_response',
                    'db/query/query_request',
                    'db/server_options_core',
                    'linenoise_utf8',
                    'rpc/protocol',
                    'scripting/scripting',
                    'shell/benchrun',
                    'shell/mongojs',
                    'transport/message_compressor',
                    'transport/transport_layer_manager',
                    'util/net/network',
                    'util/options_parser/options_parser_init',
                    'util/processinfo',
                    'util/signal_handlers',
                    'util/version_impl',
                    'executor/thread_pool_task_executor',
                    'executor/network_interface_thread_pool',
                    'executor/network_interface_factory'
                ],
                # Because `::environ` is resolved in `/usr/lib/crt1.o` on FreeBSD, this library
                # needs to be marked `incomplete` on FreeBSD.
                LIBDEPS_TAGS=[] if not env.TargetOSIs('freebsd') else [
                    'illegal_cyclic_or_unresolved_dependencies_whitelisted',
                ],
    )

    shellEnv = env.Clone()
    if env.TargetOSIs('windows'):
        shellEnv.Append(LIBS=["winmm.lib"])

        generatedMongoManifest = shellEnv.Substfile(
                'shell/shell.manifest.in',
                SUBST_DICT=[
                    ('@mongo_version_major@', version_parts[0]),
                    ('@mongo_version_minor@', version_parts[1]),
                    ('@mongo_version_patch@', version_parts[2]),
                    ('@mongo_version_extra@', version_parts[3]),
                    ('@mongo_version_extra_str@', version_extra),
                ])
        shellEnv.Alias('generated-sources', generatedMongoManifest)
        shellEnv.Depends("shell/shell.res", generatedMongoManifest)

    mongo_shell = shellEnv.Program(
        "mongo",
        [
            "shell/dbshell.cpp",
            "shell/mongodbcr.cpp",
            "shell/shell_options_init.cpp",
        ] + env.WindowsResourceFile("shell/shell.rc"),
        LIBDEPS=[
            "$BUILD_DIR/third_party/shim_pcrecpp",
            "shell_core",
            "db/server_options_core",
            "client/clientdriver_network",
            "$BUILD_DIR/mongo/util/password",
        ],
        LIBDEPS_PRIVATE=[
            "$BUILD_DIR/mongo/client/connection_string",
        ],
        INSTALL_ALIAS=[
            'shell',
            'core',
        ],
    )

    if not hygienic:
        shellEnv.Install( '#/', mongo_shell )
else:
    shellEnv = None

#  ----  INSTALL -------

# binaries

distBinaries = []
distDebugSymbols = []

def add_exe( v ):
    return "${PROGPREFIX}%s${PROGSUFFIX}" % v

def failMissingObjCopy(env, target, source):
    env.FatalError("Generating debug symbols requires objcopy, please set the OBJCOPY variable.")

def installBinary( e, name ):

    if hygienic:
        return

    debug_sym_name = name
    name = add_exe( name )

    debug_sym_cmd = None
    if e.TargetOSIs('linux', 'solaris'):
        if 'OBJCOPY' not in e:
            debug_sym_cmd = failMissingObjCopy
        else:
            debug_sym_cmd = '${OBJCOPY} --only-keep-debug ${SOURCE} ${TARGET}'
        debug_sym_name += '.debug'
    elif e.TargetOSIs('darwin'):
        debug_sym_name += '.dSYM'
        debug_sym_cmd = 'dsymutil -o ${TARGET} ${SOURCE}'
    elif e.ToolchainIs('msvc'):
        debug_sym_name += '.pdb'
        distBinaries.append(debug_sym_name)
        distDebugSymbols.append(debug_sym_name)

    if debug_sym_cmd:
        debug_sym = e.Command(
            debug_sym_name,
            name,
            debug_sym_cmd
        )
        e.Install("#/", debug_sym)
        e.Alias('debugsymbols', debug_sym)
        distDebugSymbols.append(debug_sym)

    if env.TargetOSIs('linux', 'solaris') and (not has_option("nostrip")):
        strip_cmd = e.Command(
            'stripped/%s' % name,
            [name, debug_sym],
            '${OBJCOPY} --strip-debug --add-gnu-debuglink ${SOURCES[1]} ${SOURCES[0]} $TARGET'
        )
        distBinaries.append('stripped/%s' % name)
    else:
        distBinaries.append(name)

    inst = e.Install( "$INSTALL_DIR/bin", name )

    if env.TargetOSIs('posix'):
        e.AddPostAction( inst, 'chmod 755 $TARGET' )

def installExternalBinary( e, name_str ):

    if hygienic:
        return

    name = env.File("#/%s" % add_exe(name_str))
    if not name.isfile():
        env.FatalError("ERROR: external binary not found: {0}", name)

    distBinaries.append(name)

    inst = e.Install( "$INSTALL_DIR/bin", name )

    if env.TargetOSIs('posix'):
        e.AddPostAction( inst, 'chmod 755 $TARGET' )

# "--use-new-tools" adds dependencies for rewritten (Go) tools
# It is required for "dist" but optional for "install"
if has_option("use-new-tools"):
    toolsRoot = "src/mongo-tools"
    for t in rewrittenTools:
        installExternalBinary(env, "%s/%s" % (toolsRoot, t))
    if has_option("build-mongoreplay") and get_option("build-mongoreplay") == "true":
        installExternalBinary(env, "%s/%s" % (toolsRoot, "mongoreplay"))

# legacy tools
if not hygienic:
    env.Alias("tools", "#/" + add_exe("mongobridge"))

installBinary( env, "mongod" )
installBinary( env, "mongos" )

if shellEnv is not None:
    installBinary( shellEnv, "mongo" )
    if not hygienic:
        env.Alias( "core", [ '#/%s' % b for b in [ add_exe( "mongo" ) ] ] )

if not hygienic:
    env.Alias( "core", [ '#/%s' % b for b in [ add_exe( "mongod" ), add_exe( "mongos" ) ] ] )

# Stage the top-level mongodb banners
distsrc = env.Dir('#distsrc')
env.Append(MODULE_BANNERS = [distsrc.File('README'),
                             distsrc.File('THIRD-PARTY-NOTICES'),
                             distsrc.File('MPL-2')])

# If no module has introduced a file named LICENSE-Enterprise.txt then this
# is a Community build, so inject the Community license
if sum(itertools.imap(lambda x: x.name == "LICENSE-Enterprise.txt", env['MODULE_BANNERS'])) == 0:
    env.Append(MODULE_BANNERS = [distsrc.File('LICENSE-Community.txt')])

# All module banners get staged to the top level of the tarfile, so we
# need to fail if we are going to have a name collision.
module_banner_filenames = set([f.name for f in env['MODULE_BANNERS']])
if not len(module_banner_filenames) == len(env['MODULE_BANNERS']):
    # TODO: Be nice and identify conflicts in error.
    env.FatalError("ERROR: Filename conflicts exist in module banners.")

# Build a set of directories containing module banners, and use that
# to build a --transform option for each directory so that the files
# are tar'ed up to the proper location.
module_banner_dirs = set([Dir('#').rel_path(f.get_dir()) for f in env['MODULE_BANNERS']])
module_banner_transforms = ["--transform %s=$SERVER_DIST_BASENAME" % d for d in module_banner_dirs]

# Allow modules to map original file name directories to subdirectories
# within the archive (e.g. { "src/mongo/db/modules/enterprise/docs": "snmp"})
archive_addition_transforms = []
for full_dir, archive_dir in env["ARCHIVE_ADDITION_DIR_MAP"].items():
  archive_addition_transforms.append("--transform \"%s=$SERVER_DIST_BASENAME/%s\"" %
                                     (full_dir, archive_dir))

for target in env["DIST_BINARIES"]:
    installBinary(env, "db/modules/" + target)

# Set the download url to the right place
compass_type = 'compass-community'
if 'enterprise' in env['MONGO_MODULES']:
    compass_type = 'compass'

compass_script = "install_compass"
if env.TargetOSIs('windows'):
    # On windows the .in needs to be explicitly added to the file.
    compass_script = "Install-Compass.ps1.in"

compass_python_interpreter = '/usr/bin/env python2'
if env.TargetOSIs('darwin'):
    compass_python_interpreter = '/usr/bin/env python'

compass_installer = env.Substfile('#/src/mongo/installer/compass/' + compass_script,
                                  SUBST_DICT=[
                                      ('@compass_type@', compass_type),
                                      ('@python_interpreter@', compass_python_interpreter),
                                  ])
distBinaries.append(compass_installer)

if not hygienic:
    compass_script_installer = env.Install("$INSTALL_DIR/bin", compass_installer)
else:
    compass_script_installer = env.AutoInstall(
        'bin',
        source=[
            compass_installer,
        ],
        INSTALL_ALIAS=[
            'tools',
        ],
    )

if env.TargetOSIs('posix'):
    env.AddPostAction( compass_script_installer, 'chmod 755 $TARGET' )
    env.AddPostAction( compass_installer, 'chmod 755 $TARGET' )

# "dist" target is valid only when --use-new-tools is specified
# Attempts to build release artifacts without tools must fail
if has_option("use-new-tools"):
    env.Command(
        target='#/${SERVER_ARCHIVE}',
        source=['#buildscripts/make_archive.py'] + env["MODULE_BANNERS"] + env["ARCHIVE_ADDITIONS"] + distBinaries,
        action=' '.join(
            ['$PYTHON ${SOURCES[0]} -o $TARGET'] +
            archive_addition_transforms +
            module_banner_transforms +
            [
                '--transform $BUILD_DIR/mongo/db/modules/enterprise=$SERVER_DIST_BASENAME/bin',
                '--transform $BUILD_DIR/mongo/stripped/db/modules/enterprise=$SERVER_DIST_BASENAME/bin',
                '--transform $BUILD_DIR/mongo/stripped=$SERVER_DIST_BASENAME/bin',
                '--transform $BUILD_DIR/mongo=$SERVER_DIST_BASENAME/bin',
                '--transform $BUILD_DIR/mongo/stripped/src/mongo-tools=$SERVER_DIST_BASENAME/bin',
                '--transform src/mongo-tools=$SERVER_DIST_BASENAME/bin',
                '--transform src/mongo/installer/compass=$SERVER_DIST_BASENAME/bin',
                '${TEMPFILE(SOURCES[1:])}'
            ],
        ),
        BUILD_DIR=env.Dir('$BUILD_DIR').path
    )

    env.Alias("dist", source='#/${SERVER_ARCHIVE}')
else:
    def failDist(env, target, source):
        env.FatalError("ERROR: 'dist' target only valid with --use-new-tools.")
    env.Alias("dist", [], [ failDist ] )
    env.AlwaysBuild("dist")

debug_symbols_dist = env.Command(
    target='#/${SERVER_DIST_BASENAME}-debugsymbols${DIST_ARCHIVE_SUFFIX}',
    source=['#buildscripts/make_archive.py'] + distDebugSymbols,
    action=' '.join(
        [
            '$PYTHON ${SOURCES[0]} -o $TARGET',
            '--transform $BUILD_DIR/mongo/db/modules/enterprise=$SERVER_DIST_BASENAME',
            '--transform $BUILD_DIR/mongo=$SERVER_DIST_BASENAME',
            '${TEMPFILE(SOURCES[1:])}',
        ]
    ),
    BUILD_DIR=env.Dir('$BUILD_DIR').path
)

env.Alias('dist-debugsymbols', debug_symbols_dist)

#final alias
if not hygienic:
    env.Alias( "install", "$INSTALL_DIR" )
