# -*- mode: python -*- import SCons import json Import([ 'env', 'get_option', 'jsEngine', 'use_libunwind', 'use_system_version_of_library', 'wiredtiger', 'releaseBuild', 'ssl_provider', ]) icuSuffix = '-57.1' tomcryptSuffix = '-1.18.2' thirdPartyEnvironmentModifications = { 'abseil-cpp': {'CPPPATH': ['#/src/third_party/abseil-cpp/dist'], }, 'cares': { 'CPPPATH': [ '#src/third_party/cares/dist/include', '#src/third_party/cares/platform/${TARGET_OS}_${TARGET_ARCH}/install/include' ], }, 'croaring': {'CPPPATH': ['#src/third_party/croaring/dist'], }, 'fmt': {'CPPPATH': ['#src/third_party/fmt/dist/include'], }, 'immer': {'CPPPATH': ['#src/third_party/immer/dist'], }, 's2': {'CPPPATH': ['#src/third_party/s2'], }, 'safeint': { 'CPPPATH': ['#src/third_party/SafeInt'], # SAFEINT_USE_INTRINSICS=0 for overflow-safe constexpr multiply. See comment in SafeInt.hpp. 'CPPDEFINES': [('SAFEINT_USE_INTRINSICS', 0)], }, 'timelib': {'CPPPATH': ['#/src/third_party/timelib/dist'], }, 'unwind': { 'CPPPATH': [ "#/src/third_party/unwind/platform/${TARGET_OS}_${TARGET_ARCH}/install/include", ] }, 'mozjs': { 'CPPPATH': [ '#/src/third_party/mozjs/include', '#/src/third_party/mozjs/mongo_sources', '#/src/third_party/mozjs/platform/' + env["TARGET_ARCH"] + "/" + env["TARGET_OS"] + "/include", ], 'FORCEINCLUDES': ['js-config.h', ], }, 'murmurhash3': {'CPPPATH': ['#src/third_party/murmurhash3', ], }, 'librdkafka': { 'CPPPATH': [ '#/src/third_party/librdkafka/dist/src', '#/src/third_party/librdkafka/dist/src-cpp', ], 'SYSLIBDEPS_PRIVATE': [ 'curl', ], }, } def injectMozJS(thisEnv): thisEnv.InjectThirdParty(libraries=['mozjs']) if thisEnv.TargetOSIs('windows'): thisEnv.Append(CPPDEFINES=[ '_SILENCE_CXX17_ITERATOR_BASE_CLASS_DEPRECATION_WARNING', ], ) else: thisEnv.Append(CXXFLAGS=[ '-Wno-non-virtual-dtor', '-Wno-invalid-offsetof', ], ) thisEnv.Prepend(CPPDEFINES=[ 'JS_USE_CUSTOM_ALLOCATOR', 'STATIC_JS_API=1', ]) if get_option('spider-monkey-dbg') == "on": thisEnv.Prepend(CPPDEFINES=[ 'DEBUG', 'JS_DEBUG', 'JS_GC_ZEAL' ]) env.AddMethod(injectMozJS, 'InjectMozJS') if not use_system_version_of_library('tcmalloc-gperf'): # GPerftools does this slightly differently than the others. thirdPartyEnvironmentModifications['gperftools'] = { 'CPPPATH': ["#/src/third_party/gperftools/platform/${TARGET_OS}_${TARGET_ARCH}/include"] } if not use_system_version_of_library('tcmalloc-google'): thirdPartyEnvironmentModifications['tcmalloc'] = { 'CPPPATH': ['#/src/third_party/tcmalloc/dist'], } if get_option('link-model') == 'dynamic': thirdPartyEnvironmentModifications['tcmalloc']['CPPDEFINES'] = [ ('MONGO_TCMALLOC_DYNAMIC_BUILD', 1) ] if not use_system_version_of_library('pcre2'): thirdPartyEnvironmentModifications['pcre2'] = { 'CPPPATH': ['#/src/third_party/pcre2/src'], } if not use_system_version_of_library('boost'): # On at least Apple clang, proto throws this error. # # See https://github.com/boostorg/proto/issues/30. # # We use a generator so we can filter out conf tests, where applying this # flag could change their meaning. def NoErrorForUnknownWarningOptionGenerator(target, source, env, for_signature): if 'conftest' in str(target[0]): return str() return '-Wno-error=unknown-warning-option' thirdPartyEnvironmentModifications['boost'] = { 'CPPPATH': ['#/src/third_party/boost'], # We could narror further to just clang on Darwin, but there is # little harm in applying for all clang. 'NOERROR_FOR_UNKNOWN_WARNING_OPTION_GEN': NoErrorForUnknownWarningOptionGenerator, 'CCFLAGS': ['$NOERROR_FOR_UNKNOWN_WARNING_OPTION_GEN'] if env.ToolchainIs('clang') else [], 'SYSLIBDEPS': ['synchronization'] if env.ToolchainIs('msvc') else [], } if not use_system_version_of_library('snappy'): platform_directory = "build_posix" if env.TargetOSIs('linux'): platform_directory = "build_linux_" + env['TARGET_ARCH'] elif env.TargetOSIs('windows'): platform_directory = "build_windows" elif env.TargetOSIs('darwin'): platform_directory = "build_" + env["TARGET_OS"] + "_" + env["TARGET_ARCH"] thirdPartyEnvironmentModifications['snappy'] = { 'CPPPATH': [ '#/src/third_party/snappy/dist', '#/src/third_party/snappy/platform/build_all', '#/src/third_party/snappy/platform/' + platform_directory, ], } # Valgrind is a header only include as valgrind.h includes everything we need if not use_system_version_of_library('valgrind'): thirdPartyEnvironmentModifications['valgrind'] = { 'CPPPATH': ['#/src/third_party/valgrind/include'], } if not use_system_version_of_library('zlib'): thirdPartyEnvironmentModifications['zlib'] = { 'CPPPATH': ['#/src/third_party/zlib'], } if not use_system_version_of_library('zstd'): thirdPartyEnvironmentModifications['zstd'] = { 'CPPPATH': ['#/src/third_party/zstandard/zstd/lib'], } if not use_system_version_of_library('google-benchmark'): thirdPartyEnvironmentModifications['benchmark'] = { 'CPPPATH': ['#/src/third_party/benchmark/dist/include'], } if "tom" in env["MONGO_CRYPTO"]: thirdPartyEnvironmentModifications['tomcrypt'] = { 'CPPPATH': ['#/src/third_party/tomcrypt' + tomcryptSuffix + '/src/headers'], } if not use_system_version_of_library('tomcrypt'): thirdPartyEnvironmentModifications['tomcrypt_md5'] = { 'CPPPATH': ['#/src/third_party/tomcrypt' + tomcryptSuffix + '/src/headers'], 'CPPDEFINES': ['LTC_NO_PROTOTYPES'] if env.TargetOSIs('windows') else [], } if not use_system_version_of_library('stemmer'): thirdPartyEnvironmentModifications['stemmer'] = { 'CPPPATH': ['#/src/third_party/libstemmer_c/include'], } # Note that the wiredtiger.h header is generated, so # we want to look for it in the build directory not # the source directory. if wiredtiger and not use_system_version_of_library('wiredtiger'): thirdPartyEnvironmentModifications['wiredtiger'] = { 'CPPPATH': ["#$BAZEL_OUT_DIR/src/third_party/wiredtiger"], } if not use_system_version_of_library('yaml'): thirdPartyEnvironmentModifications['yaml'] = { 'CPPPATH': ['#/src/third_party/yaml-cpp/yaml-cpp/include'], 'CPPDEFINES': ['_SILENCE_CXX17_ITERATOR_BASE_CLASS_DEPRECATION_WARNING'] if env.ToolchainIs('msvc') else [], } if not use_system_version_of_library('asio'): thirdPartyEnvironmentModifications['asio'] = { 'CPPPATH': ['#/src/third_party/asio-master/asio/include'], } if not use_system_version_of_library('intel_decimal128'): thirdPartyEnvironmentModifications['intel_decimal128'] = { 'CPPPATH': ['#/src/third_party/IntelRDFPMathLib20U1/LIBRARY/src'], } if not use_system_version_of_library('icu'): thirdPartyEnvironmentModifications['icu'] = { 'CPPPATH': [ '#/src/third_party/icu4c' + icuSuffix + '/source/common', '#/src/third_party/icu4c' + icuSuffix + '/source/i18n', ], } if not use_system_version_of_library('bson'): platform_directory = "build_linux" if env['TARGET_ARCH'] == 's390x': platform_directory = "build_linux_s390x" if env.TargetOSIs('windows'): platform_directory = "build_windows" elif env.TargetOSIs('darwin'): platform_directory = "build_osx" thirdPartyEnvironmentModifications['bson'] = { 'CPPPATH': [ '#/src/third_party/libbson/dist/src/libbson/src', '#/src/third_party/libbson/' + platform_directory, '#/src/third_party/libbson/' + platform_directory + '/bson', ], 'CPPDEFINES': ['BSON_STATIC'], } if not use_system_version_of_library('libmongocrypt'): platform_directory = "build_linux" crypto_directory = "build_libcrypto" if env.TargetOSIs('windows'): platform_directory = "build_windows" crypto_directory = "build_cng" elif env.TargetOSIs('darwin'): platform_directory = "build_osx" crypto_directory = "build_commoncrypto" if get_option('ssl') == 'off': crypto_directory = "build_none" thirdPartyEnvironmentModifications['libmongocrypt'] = { 'CPPPATH': [ '#/src/third_party/libmongocrypt/dist/src', '#/src/third_party/libmongocrypt/dist/kms-message/src', '#/src/third_party/libmongocrypt/' + platform_directory, '#/src/third_party/libmongocrypt/' + crypto_directory, ], 'CPPDEFINES': [ 'KMS_MSG_STATIC', 'MONGOCRYPT_STATIC_DEFINE', ], } if not use_system_version_of_library('protobuf'): thirdPartyEnvironmentModifications['protobuf'] = { 'CPPPATH': ['#src/third_party/protobuf/dist/src'], } if not use_system_version_of_library('grpc'): thirdPartyEnvironmentModifications['grpc'] = { 'CPPPATH': ['#src/third_party/grpc/dist/include', '#src/third_party/grpc/dist/'], } thirdPartyEnvironmentModifications['re2'] = { 'CPPPATH': ['#src/third_party/re2/dist'], } thirdPartyEnvironmentModifications['cares'] = { 'CPPPATH': [ '#src/third_party/cares/dist/include', '#src/third_party/cares/platform/${TARGET_OS}_${TARGET_ARCH}/install/include' ], } # Vendored libunwind can be configured to use liblzma for decompressing # minidebuginfo sections, but we disable that feature via # `unwind/scripts/host-config.sh`. If vendored libunwind ever needs # minidebuginfo support, we'd say so here, and we'd dynamically link with # system lzma. Until then, it would be an unnecessary dynamic dependency. # However, the system libunwind is assumed to need `lzma` unconditionally. vendored_libunwind_needs_lzma = False if vendored_libunwind_needs_lzma: thirdPartyEnvironmentModifications['unwind'] = { 'SYSLIBDEPS_PRIVATE': [env['LIBDEPS_LZMA_SYSLIBDEP']], } def injectThirdParty(thisEnv, libraries=[], parts=[]): libraries = thisEnv.Flatten([libraries]) parts = thisEnv.Flatten([parts]) for lib in libraries: mods = thirdPartyEnvironmentModifications.get(lib, None) if mods is None: continue if not parts: thisEnv.PrependUnique(**mods) else: for part in parts: thisEnv.PrependUnique({part: mods[part]}) env.AddMethod(injectThirdParty, 'InjectThirdParty') env = env.Clone() # Construct an empty object file that we can use to produce the # library for every shim. This avoids the need to create and name a # different empty source file for every third-party library, as we did # in the past. empty_source = env.Textfile( target='third_party_shim.cpp', source=str(), ) env.Alias('generated-sources', empty_source) empty_object = env.LibraryObject(target='third_party_shim', source=empty_source, NINJA_GENSOURCE_INDEPENDENT=True) def shim_library(env, name, **kwargs): # Add the 'virtual-libdep' tag, which will prevent shim libraries # from actually being linked to. They don't provide any symbols, # so there is no need to do so. Instead, they just act as a node # in the library dependency graph to reach other libraries. libdeps_tags = kwargs.get('LIBDEPS_TAGS', env.get('LIBDEPS_TAGS', [])).copy() libdeps_tags.append('virtual-libdep') kwargs['LIBDEPS_TAGS'] = libdeps_tags return env.Library( target=f'shim_{name}', source=empty_object[0], # Since nothing will link to this library per the # `virtual-libdep` tag above, we can also skip installing it. AIB_IGNORE=True, **kwargs, ) env.AddMethod(shim_library, 'ShimLibrary') if jsEngine: mozjsEnv = env.Clone() wiredtigerEnv = env.Clone() if wiredtiger: if use_system_version_of_library("wiredtiger"): wiredtigerEnv = wiredtigerEnv.Clone(SYSLIBDEPS=[ env['LIBDEPS_WIREDTIGER_SYSLIBDEP'], ]) else: wiredtigerEnv = wiredtigerEnv.Clone() wiredtigerEnv.InjectThirdParty(libraries=['wiredtiger']) wiredtigerEnv.SConscript('wiredtiger/SConscript', must_exist=1, exports={'env': wiredtigerEnv}) wiredtigerEnv = wiredtigerEnv.Clone(LIBDEPS_INTERFACE=[ 'wiredtiger/wiredtiger', ]) if env.TargetOSIs('linux') and env['ENABLE_GRPC_BUILD']: protobufEnv = env.Clone(NINJA_GENSOURCE_INDEPENDENT=True) if use_system_version_of_library("protobuf"): protobufEnv = protobufEnv.Clone( SYSLIBDEPS=[ env['LIBDEPS_PROTOBUF_SYSLIBDEP'], env['LIBDEPS_PROTOC_SYSLIBDEP'], ], ) else: protobufEnv.SConscript(dirs=[ 'protobuf', ], duplicate=False, exports={'env': env}, must_exist=1,) protobufEnv = protobufEnv.Clone(LIBDEPS_INTERFACE=[ 'protobuf/protoc', ]) protobufEnv.ShimLibrary(name="protobuf", ) grpcEnv = env.Clone() if use_system_version_of_library("grpc"): grpcEnv = grpcEnv.Clone(SYSLIBDEPS=[ env['LIBDEPS_GRPC_SYSLIBDEP'], env['LIBDEPS_GRPCXX_SYSLIBDEP'], env['LIBDEPS_GRPCXX_REFLECTION_SYSLIBDEP'], ]) else: grpcEnv.SConscript( dirs=[ 'grpc', ], duplicate=False, exports={'env': env}, must_exist=1,) grpcEnv = grpcEnv.Clone(LIBDEPS_INTERFACE=[ 'grpc/grpc++_reflection', ]) grpcEnv.ShimLibrary(name="grpc", ) if env.ShouldBuildStreams(): libKafkaEnv = env.Clone() libKafkaEnv.InjectThirdParty(libraries=['librdkafka'])