diff options
-rw-r--r-- | SConstruct | 165 | ||||
-rw-r--r-- | site_scons/libdeps_next.py | 28 | ||||
-rw-r--r-- | src/SConscript | 187 | ||||
-rw-r--r-- | src/mongo/installer/msi/ca/SConscript | 8 | ||||
-rw-r--r-- | src/mongo/platform/SConscript | 30 | ||||
-rw-r--r-- | src/shim_crt.cpp | 3 | ||||
-rw-r--r-- | src/shim_cxx.cpp | 3 | ||||
-rw-r--r-- | src/third_party/SConscript | 124 | ||||
-rw-r--r-- | src/third_party/gperftools/SConscript | 9 | ||||
-rw-r--r-- | src/third_party/unwind/SConscript | 10 |
10 files changed, 434 insertions, 133 deletions
diff --git a/SConstruct b/SConstruct index 2f96c965b83..f1d4d225009 100644 --- a/SConstruct +++ b/SConstruct @@ -429,6 +429,15 @@ add_option("cxx-std", help="Select the C++ langauge standard to build with", ) +add_option("dynamic-runtime", + choices=["force", "off", "auto"], + const="on", + default="auto", + help="Force the static compiler and C++ runtimes to be linked dynamically", + nargs="?", + type="choice", +) + def find_mongo_custom_variables(): files = [] paths = [path for path in sys.path if 'site_scons' in path] @@ -1146,6 +1155,25 @@ for var in ['CC', 'CXX']: env.AddMethod(mongo_platform.env_os_is_wrapper, 'TargetOSIs') env.AddMethod(mongo_platform.env_get_os_name_wrapper, 'GetTargetOSName') + +def shim_library(env, name, needs_link=False, *args, **kwargs): + nodes = env.Library( + target=f"shim_{name}" if name else name, + source=[ + f"shim_{name}.cpp" if name else name, + ], + *args, + **kwargs + ) + + for n in nodes: + setattr(n.attributes, "needs_link", needs_link) + + return nodes + +env.AddMethod(shim_library, 'ShimLibrary') + + def conf_error(env, msg, *args): print(msg.format(*args)) print("See {0} for details".format(env.File('$CONFIGURELOG').abspath)) @@ -1634,6 +1662,122 @@ if link_model.startswith("dynamic"): return [] env['LIBDEPS_TAG_EXPANSIONS'].append(libdeps_tags_expand_incomplete) + +# If requested, wrap the static runtime libraries in shims and use those to link +# them dynamically. This allows us to "convert" runtimes in toolchains that have +# linker scripts in place of shared libraries which actually link the static +# library instead. The benefit of making this conversion is that shared +# libraries produced by these toolchains are smaller because we don't end up +# spreading runtime symbols all over the place, and in turn they should also +# get loaded by the dynamic linker more quickly as well. +dynamicRT = get_option("dynamic-runtime") + +if dynamicRT == "auto": + if env.ToolchainIs('msvc'): + # TODO: SERVER-53102 + # Windows Enterprise *requires* a dynamic CRT because it needs to have + # shared state in order to load the external libraries required for SSL, + # LDAP, etc. This state of affairs may eventually change as Windows + # dynamic builds improve, but for now we just force a dynamic CRT with + # Windows until we have some way of detecting when we can get away with + # a static CRT. + # + # Ideally, we should be determining whether a static build is requested, + # and if so, whether a dynamic CRT *must* be used in such a case. + + dynamicRT = "force" + + elif get_option("link-model") != "dynamic": + dynamicRT = "off" + + elif env.TargetOSIs('linux') and env.ToolchainIs('gcc', 'clang'): + def CheckRuntimeLibraries(context): + context.Message("Checking whether any runtime libraries are linker scripts... ") + + result = {} + libs = [ 'libgcc', 'libgcc_s', 'libgcc_eh' ] + + if get_option('libc++'): + libs.append('libc++') + else: + libs.append('libstdc++') + + compiler = subprocess.Popen( + [context.env['CXX'], "-print-search-dirs"], + stdout=subprocess.PIPE + ) + + # This just pulls out the library paths and *only* the library + # paths, deleting all other lines. It also removes the leading + # "libraries" tag from the line so only the paths are left in + # the output. + sed = subprocess.Popen( + [ + "sed", + "/^lib/b 1;d;:1;s,.*:[^=]*=,,", + ], + stdin=compiler.stdout, + stdout=subprocess.PIPE + ) + compiler.stdout.close() + + search_paths = sed.communicate()[0].decode('utf-8').split(':') + + for lib in libs: + for search_path in search_paths: + lib_file = os.path.join(search_path, lib + ".so") + if os.path.exists(lib_file): + file_type = subprocess.check_output(["file", lib_file]).decode('utf-8') + match = re.search('ASCII text', file_type) + result[lib] = bool(match) + break + if any(result.values()): + ret = "yes" + else: + ret = "no" + context.Result(ret) + return ret + + detectStaticRuntime = Configure(detectEnv, help=False, custom_tests = { + 'CheckRuntimeLibraries' : CheckRuntimeLibraries, + }) + + if detectStaticRuntime.CheckRuntimeLibraries() == "yes": + # TODO: SERVER-48291 + # Set this to "force" when the issue with jsCore test failures with + # dynamic runtime have been resolved. + dynamicRT = "off" + else: + dynamicRT = "off" + + detectStaticRuntime.Finish() + +if dynamicRT == "force": + if not (env.TargetOSIs('linux') or env.TargetOSIs('windows')): + env.FatalError("A dynamic runtime can be forced only on Windows and Linux at this time.") + + # GCC and Clang get configured in src/SConscript so as to avoid affecting + # the conftests. + if env.ToolchainIs('msvc'): + if debugBuild: + env.Append(CCFLAGS=["/MDd"]) + else: + env.Append(CCFLAGS=["/MD"]) + + else: + if get_option("link-model") != "dynamic": + env.FatalError("A dynamic runtime can only be forced with dynamic linking on this toolchain.") + + if not env.ToolchainIs('gcc', 'clang'): + env.FatalError("Don't know how to force a dynamic runtime on this toolchain.") + +if dynamicRT == "off" and env.ToolchainIs('msvc'): + if debugBuild: + env.Append(CCFLAGS=["/MTd"]) + else: + env.Append(CCFLAGS=["/MT"]) + + if optBuild: env.SetConfigHeaderDefine("MONGO_CONFIG_OPTIMIZED_BUILD") @@ -2090,11 +2234,6 @@ elif env.TargetOSIs('windows'): if not any(flag.startswith('/DEBUG') for flag in env['LINKFLAGS']): env.Append(LINKFLAGS=["/DEBUG"]) - # /MD: use the multithreaded, DLL version of the run-time library (MSVCRT.lib/MSVCR###.DLL) - # /MDd: Defines _DEBUG, _MT, _DLL, and uses MSVCRTD.lib/MSVCRD###.DLL - - env.Append(CCFLAGS=["/MDd" if debugBuild else "/MD"]) - if optBuild: # /O1: optimize for size # /O2: optimize for speed (as opposed to size) @@ -2226,7 +2365,6 @@ if env.TargetOSIs('posix'): "-fno-strict-aliasing", "-fasynchronous-unwind-tables", "-ggdb" if not env.TargetOSIs('emscripten') else "-g", - "-pthread", "-Wall", "-Wsign-compare", "-Wno-unknown-pragmas", @@ -2243,8 +2381,14 @@ if env.TargetOSIs('posix'): # On OS X, clang doesn't want the pthread flag at link time, or it # issues warnings which make it impossible for us to declare link # warnings as errors. See http://stackoverflow.com/a/19382663. - if not (env.TargetOSIs('darwin') and env.ToolchainIs('clang')): - env.Append( LINKFLAGS=["-pthread"] ) + # + # We don't need it anyway since we explicitly link to -lpthread, + # so all we need beyond that is the preprocessor variable. + if not env.ToolchainIs('clang'): + env.Append( + CPPDEFINES=[("_REENTRANT", "1")], + LINKFLAGS=["-pthread"] + ) # SERVER-9761: Ensure early detection of missing symbols in dependent libraries at program # startup. @@ -3810,8 +3954,10 @@ def doConfigure(myenv): language='C++') if posix_system: conf.env.SetConfigHeaderDefine("MONGO_CONFIG_HAVE_HEADER_UNISTD_H") + conf.CheckLib('c') conf.CheckLib('rt') conf.CheckLib('dl') + conf.CheckLib('pthread') if posix_monotonic_clock: conf.env.SetConfigHeaderDefine("MONGO_CONFIG_HAVE_POSIX_MONOTONIC_CLOCK") @@ -4777,6 +4923,7 @@ module_sconscripts = moduleconfig.get_module_sconscripts(mongo_modules) # and they are exported here, as well. Export([ 'debugBuild', + 'dynamicRT', 'endian', 'free_monitoring', 'get_option', @@ -5007,4 +5154,4 @@ for i, s in enumerate(BUILD_TARGETS): # SConscripts have been read but before building begins. if get_option('build-tools') == 'next': libdeps.LibdepLinter(env).final_checks() - libdeps.generate_libdeps_graph(env)
\ No newline at end of file + libdeps.generate_libdeps_graph(env) diff --git a/site_scons/libdeps_next.py b/site_scons/libdeps_next.py index 66671b5e969..1df8f33b4d4 100644 --- a/site_scons/libdeps_next.py +++ b/site_scons/libdeps_next.py @@ -72,6 +72,7 @@ class Constants: LibdepsCached = "LIBDEPS_cached" LibdepsDependents = "LIBDEPS_DEPENDENTS" LibdepsGlobal = "LIBDEPS_GLOBAL" + LibdepsNoInherit = "LIBDEPS_NO_INHERIT" LibdepsInterface ="LIBDEPS_INTERFACE" LibdepsPrivate = "LIBDEPS_PRIVATE" LibdepsTypeinfo = "LIBDEPS_TYPEINFO" @@ -580,8 +581,8 @@ class LibdepLinter: target_type = self.target[0].builder.get_name(self.env) self._raise_libdep_lint_exception(textwrap.dedent(f"""\ - Found non-list type '{libdeps_list}' while evaluating {dep_type_val} for {target_type} '{self.target[0]}' - {dep_type_val} must be setup as a list.""" + Found non-list type '{libdeps_list}' while evaluating {dep_type_val[1]} for {target_type} '{self.target[0]}' + {dep_type_val[1]} must be setup as a list.""" )) dependency_visibility_ignored = { @@ -732,6 +733,8 @@ def update_scanner(env, builder_name=None, debug=False): print(f" public: {env.get(Constants.Libdeps, None)}") print(f" interface: {env.get(Constants.LibdepsInterface, None)}") print(f" typeinfo: {env.get(Constants.LibdepsTypeinfo, None)}") + print(f" no_inherit: {env.get(Constants.LibdepsNoInherit, None)}") + if old_scanner: result = old_scanner.function(node, env, path) else: @@ -896,10 +899,14 @@ def get_libdeps_nodes(env, target, builder, debug=False, visibility_map=None): if not SCons.Util.is_List(target): target = [target] + # Get the current list of nodes not to inherit on each target + no_inherit = set(env.get(Constants.LibdepsNoInherit, [])) + # Get all the libdeps from the env so we can # can append them to the current target_node. libdeps = [] for dep_type in sorted(visibility_map.keys()): + if dep_type == deptype.Global: if any("conftest" in str(t) for t in target): # Ignore global dependencies for conftests @@ -915,11 +922,17 @@ def get_libdeps_nodes(env, target, builder, debug=False, visibility_map=None): if not lib: continue - if debug and not any("conftest" in str(t) for t in target): - print(f" {dep_type} => {lib}") - lib_with_ixes = _get_node_with_ixes(env, lib, builder) - libdeps.append(dependency(lib_with_ixes, dep_type, lib)) + + if lib in no_inherit: + if debug and not any("conftest" in str(t) for t in target): + print(f" {dep_type[1]} =/> {lib}") + + else: + if debug and not any("conftest" in str(t) for t in target): + print(f" {dep_type[1]} => {lib}") + + libdeps.append(dependency(lib_with_ixes, dep_type, lib)) return libdeps @@ -953,8 +966,11 @@ def libdeps_emitter(target, source, env, debug=False, builder=None, visibility_m print(f" public: {env.get(Constants.Libdeps, None)}") print(f" interface: {env.get(Constants.LibdepsInterface, None)}") print(f" typeinfo: {env.get(Constants.LibdepsTypeinfo, None)}") + print(f" no_inherit: {env.get(Constants.LibdepsNoInherit, None)}") print(f" Edges:") + libdeps = get_libdeps_nodes(env, target, builder, debug, visibility_map) + if debug and not any("conftest" in str(t) for t in target): print(f"\n") diff --git a/src/SConscript b/src/SConscript index fbf8e1fcecb..28c848a675e 100644 --- a/src/SConscript +++ b/src/SConscript @@ -3,21 +3,206 @@ # This is the principle SConscript file, invoked by the SConstruct. Its job is # to delegate to any and all per-module SConscript files. +from functools import partial + +from site_scons.mongo import insort_wrapper + +import SCons + +Import('dynamicRT') Import('env') Import('get_option') +Import('has_option') Import('module_sconscripts') -env = env.Clone() +def shim_hack(target, source, env, inject_target=None, exclusions=None): + if exclusions is None: + exclusions = set(inject_target) + elif isinstance(exclusions, str): + exclusions = {exclusions, inject_target} + elif isinstance(exclusions, (list, set)): + exclusions = set(exclusions) + exclusions.add(inject_target) + + # If we allowed conftests to become dependent, any TryLink + # that happened after we made the below modifications would + # cause the configure steps to try to compile tcmalloc and any + # of its dependencies. Oops! + if any('conftest' in str(t) for t in target): + return target, source + + # It is possible that 'env' isn't a unique + # OverrideEnvironment, since if you didn't pass any kw args + # into your builder call, you just reuse the env you were + # called with. That could mean that we see the same + # environment here multiple times. But that is really OK, + # since the operation we are performing would be performed on + # all of them anyway. + libdeps_no_inherit = set(env.get('LIBDEPS_NO_INHERIT', [])) + exclusions.update(libdeps_no_inherit) + + if f"$BUILD_DIR/{inject_target}" not in exclusions: + lds = env.get('LIBDEPS', []) + shim_target = f"$BUILD_DIR/{inject_target}" + if shim_target not in lds: + insort_wrapper(lds, shim_target) + env['LIBDEPS'] = lds + + return target, source + + +def nodefaultlibs_hack(target, source, env): + if any('conftest' in str(t) for t in target): + return target, source + + runtime_shim_names = [ + 'shim_crt', + 'shim_cxx', + ] + runtime_shims = [f"$BUILD_DIR/{name}" for name in runtime_shim_names] + + # If we're building either the CRT or CXX shim, don't insert the + # nodefaultlibs argument because it makes static library insertion not work + # in clang and gcc. + if any(name in str(t) for name in runtime_shim_names for t in target): + return target, source + + libdeps_no_inherit = set(env.get('LIBDEPS_NO_INHERIT', [])) + + if not any(shim in libdeps_no_inherit for shim in runtime_shims): + linkflags = env.get('LINKFLAGS', []) + if '-nodefaultlibs' not in linkflags: + linkflags = ['-nodefaultlibs'] + linkflags + + env['LINKFLAGS'] = linkflags + + return target, source + + +def hack_builder_emitters(env, hack_method): + for builder_name in ('Program', 'SharedLibrary', 'LoadableModule', 'StaticLibrary'): + builder = env['BUILDERS'][builder_name] + base_emitter = builder.emitter + builder.emitter = SCons.Builder.ListEmitter([hack_method, base_emitter]) + + +# Here, we "hoist" libgcc*.a symbols out of the toolchain and stuff them into +# our own library so they don't get added piecemeal to every shared object and +# executable in a build directly out of the toolchain. +libcrtEnv = env.Clone(LIBS=[]) +libcxxEnv = env.Clone(LIBS=[]) +if dynamicRT == "force": + + if env.ToolchainIs('gcc', 'clang'): + # Clang ang GCC get configured here because the dynamic runtimes are + # injected in ways that would not be fully applied to conftests. The + # only way to fix that means running part of the build before we can + # run conftests. It may be worth it to do that at some point, but it's + # complexity we should consider later if it's determined we need it. + + hack_builder_emitters(env, nodefaultlibs_hack) + + libcrtEnv.AppendUnique( + LINKFLAGS=[ + "-Wl,-z,muldefs", + "-static-libgcc", + "-Wl,--push-state", + "-Wl,-Bstatic", + "-Wl,--no-warn-execstack", + "-Wl,--whole-archive", + "-lgcc", + "-lgcc_eh", + "-Wl,--no-whole-archive", + "-Wl,--pop-state", + ], + SYSLIBDEPS=[ + ':libgcc_s.so', + ] + ) + + if has_option("libc++"): + cxx_lib = "c++" + else: + cxx_lib = "stdc++" + + libcxxEnv.AppendUnique( + LINKFLAGS=[ + "-Wl,-z,muldefs", + f"-static-lib{cxx_lib}", + "-Wl,--push-state", + "-Wl,-Bstatic", + "-Wl,--no-warn-execstack", + "-Wl,--whole-archive", + f"-l{cxx_lib}", + "-Wl,--no-whole-archive", + "-Wl,--pop-state", + ] + ) + +libcrtEnv.ShimLibrary( + name="crt", + needs_link=(dynamicRT == "force"), + LIBDEPS_TAGS=[ + # TODO: Remove when SERVER-48291 is merged into stable build tools. + # An inserted dependency must be linked to every node, including what would + # be considered a leaf node to ensure that a system dependency is not linked + # in before this one. This tag allows nodes tagged as leaf nodes to still + # get the correct allocator. + 'lint-leaf-node-allowed-dep', + # This tag allows this dependency to be linked to nodes marked as not + # allowed to have public dependencies. + 'lint-public-dep-allowed' + ] +) + +libcxxEnv.ShimLibrary( + name="cxx", + needs_link=(dynamicRT == "force"), + LIBDEPS_TAGS=[ + # TODO: Remove when SERVER-48291 is merged into stable build tools. + # An inserted dependency must be linked to every node, including what would + # be considered a leaf node to ensure that a system dependency is not linked + # in before this one. This tag allows nodes tagged as leaf nodes to still + # get the correct allocator. + 'lint-leaf-node-allowed-dep', + # This tag allows this dependency to be linked to nodes marked as not + # allowed to have public dependencies. + 'lint-public-dep-allowed' + ] +) + + if get_option("build-tools") == "next": # Add any "global" dependencies here. This is where we make every build node # depend on a list of other build nodes, such as an allocator or libunwind # or libstdx or similar. env.AppendUnique( LIBDEPS_GLOBAL=[ + '$BUILD_DIR/shim_crt' if dynamicRT == "force" else [], + '$BUILD_DIR/shim_cxx' if dynamicRT == "force" else [], '$BUILD_DIR/third_party/shim_allocator', ], ) +else: + if dynamicRT == "force": + hack_builder_emitters( + env, + partial( + shim_hack, + inject_target='shim_crt')) + hack_builder_emitters( + env, + partial( + shim_hack, + inject_target='shim_cxx')) + hack_builder_emitters( + env, + partial( + shim_hack, + inject_target='third_party/shim_allocator', + exclusions='gperftools/gperftools')) + # NOTE: We must do third_party first as it adds methods to the environment # that we need in the mongo sconscript diff --git a/src/mongo/installer/msi/ca/SConscript b/src/mongo/installer/msi/ca/SConscript index 01068b4a3ce..ac30011b240 100644 --- a/src/mongo/installer/msi/ca/SConscript +++ b/src/mongo/installer/msi/ca/SConscript @@ -31,11 +31,7 @@ ca = env.SharedLibrary( 'customaction.def', ], # We don't want any special allocator here either. - LIBDEPS_GLOBAL=[ - dep - for dep in env.get('LIBDEPS_GLOBAL', []) - if not dep.endswith('shim_allocator') + LIBDEPS_NO_INHERIT=[ + '$BUILD_DIR/third_party/shim_allocator', ], - # TODO: Remove when SERVER-48291 is merged into stable build tools - DISABLE_ALLOCATOR_SHIM_INJECTION=True, ) diff --git a/src/mongo/platform/SConscript b/src/mongo/platform/SConscript index e898e9642e7..193a62de65c 100644 --- a/src/mongo/platform/SConscript +++ b/src/mongo/platform/SConscript @@ -41,8 +41,12 @@ env.Library( source=[ "visibility_test_libcommon.cpp", ], + LIBDEPS_NO_INHERIT=[ + '$BUILD_DIR/third_party/shim_allocator', + '$BUILD_DIR/shim_crt', + '$BUILD_DIR/shim_cxx', + ], LIBDEPS=[], - DISABLE_ALLOCATOR_SHIM_INJECTION=True, MONGO_API_NAME="visibility_test_libcommon", ) @@ -51,11 +55,15 @@ env.Library( source=[ "visibility_test_lib1.cpp" ], + LIBDEPS_NO_INHERIT=[ + '$BUILD_DIR/third_party/shim_allocator', + '$BUILD_DIR/shim_crt', + '$BUILD_DIR/shim_cxx', + ], LIBDEPS=[], LIBDEPS_PRIVATE=[ "visibility_test_libcommon", ], - DISABLE_ALLOCATOR_SHIM_INJECTION=True, MONGO_API_NAME="visibility_test_lib1", ) @@ -64,13 +72,17 @@ env.Library( source=[ "visibility_test_lib2.cpp" ], + LIBDEPS_NO_INHERIT=[ + '$BUILD_DIR/third_party/shim_allocator', + '$BUILD_DIR/shim_crt', + '$BUILD_DIR/shim_cxx', + ], LIBDEPS=[ "visibility_test_lib1", ], LIBDEPS_PRIVATE=[ "visibility_test_libcommon", ], - DISABLE_ALLOCATOR_SHIM_INJECTION=True, MONGO_API_NAME="visibility_test_lib2", ) @@ -79,10 +91,14 @@ visibility_test1 = env.Program( source=[ "visibility_test1.cpp", ], + LIBDEPS_NO_INHERIT=[ + '$BUILD_DIR/third_party/shim_allocator', + '$BUILD_DIR/shim_crt', + '$BUILD_DIR/shim_cxx', + ], LIBDEPS=[ "visibility_test_lib1", ], - DISABLE_ALLOCATOR_SHIM_INJECTION=True, AIB_COMPONENT="visibility-test", AIB_COMPONENTS_EXTRA=[ "unittests", @@ -96,10 +112,14 @@ visibility_test2 = env.Program( source=[ "visibility_test2.cpp", ], + LIBDEPS_NO_INHERIT=[ + '$BUILD_DIR/third_party/shim_allocator', + '$BUILD_DIR/shim_crt', + '$BUILD_DIR/shim_cxx', + ], LIBDEPS=[ "visibility_test_lib2", ], - DISABLE_ALLOCATOR_SHIM_INJECTION=True, AIB_COMPONENT="visibility-test", AIB_COMPONENTS_EXTRA=[ "unittests", diff --git a/src/shim_crt.cpp b/src/shim_crt.cpp new file mode 100644 index 00000000000..4c49e6668c1 --- /dev/null +++ b/src/shim_crt.cpp @@ -0,0 +1,3 @@ +// This file intentionally blank. shim_crt.cpp rolls together the compiler +// runtime libraries to provide a single source of those symbols to other +// compiled objects in a dynamically linked build. diff --git a/src/shim_cxx.cpp b/src/shim_cxx.cpp new file mode 100644 index 00000000000..d18e22432d7 --- /dev/null +++ b/src/shim_cxx.cpp @@ -0,0 +1,3 @@ +// This file intentionally blank. shim_cxx.cpp rolls together the C++ +// runtime libraries to provide a single source of those symbols to other +// compiled objects in a dynamically linked build. diff --git a/src/third_party/SConscript b/src/third_party/SConscript index 0c2674ff356..fbd884fbf1e 100644 --- a/src/third_party/SConscript +++ b/src/third_party/SConscript @@ -1,12 +1,8 @@ # -*- mode: python -*- -import SCons - -from site_scons.mongo import insort_wrapper import json Import("env use_system_version_of_library usemozjs get_option") -Import("get_option") Import("use_libunwind") Import("use_system_libunwind") Import("use_vendored_libunwind") @@ -85,59 +81,6 @@ def injectMozJS(thisEnv): env.AddMethod(injectMozJS, 'InjectMozJS'); -def add_shim_allocator_hack(target, source, env): - - # If we allowed conftests to become dependent, any TryLink - # that happened after we made the below modifications would - # cause the configure steps to try to compile tcmalloc and any - # of its dependencies. Oops! - if any('conftest' in str(t) for t in target): - return target, source - - # It is possible that 'env' isn't a unique - # OverrideEnvironment, since if you didn't pass any kw args - # into your builder call, you just reuse the env you were - # called with. That could mean that we see the same - # environment here multiple times. But that is really OK, - # since the operation we are performing would be performed on - # all of them anyway. The flag serves as a way to disable the - # auto-injection for the handful of libraries where we must do - # so to avoid forming a cycle. - if not env.get('DISABLE_ALLOCATOR_SHIM_INJECTION', False): - lds = env.get('LIBDEPS', []) - shim_allocator = '$BUILD_DIR/third_party/shim_allocator' - if shim_allocator not in lds: - insort_wrapper(lds, shim_allocator) - env['LIBDEPS'] = lds - - return target, source - - -if get_option("build-tools") == "stable": - for builder_name in ('Program', 'SharedLibrary', 'LoadableModule', 'StaticLibrary'): - builder = env['BUILDERS'][builder_name] - base_emitter = builder.emitter - builder.emitter = SCons.Builder.ListEmitter([add_shim_allocator_hack, base_emitter]) - - -def shim_library(env, name, needs_link=False, *args, **kwargs): - nodes = env.Library( - target=f"shim_{name}" if name else name, - source=[ - f"shim_{name}.cpp" if name else name, - ], - *args, - **kwargs - ) - - for n in nodes: - setattr(n.attributes, "needs_link", needs_link) - - return nodes - -env.AddMethod(shim_library, 'ShimLibrary') - - if not use_system_version_of_library('tcmalloc'): # GPerftools does this slightly differently than the others. thirdPartyEnvironmentModifications['gperftools'] = {} @@ -287,11 +230,11 @@ s2Env.SConscript('s2/SConscript', exports={'env' : s2Env}) if use_libunwind: unwindEnv = env.Clone( - LIBDEPS_GLOBAL=[ - dep - for dep in env.get('LIBDEPS_GLOBAL', []) - if not dep.endswith('shim_allocator') - ] + LIBDEPS_NO_INHERIT=[ + '$BUILD_DIR/shim_crt', + '$BUILD_DIR/shim_cxx', + '$BUILD_DIR/third_party/shim_allocator', + ], ) if use_system_libunwind: unwindEnv = unwindEnv.Clone( @@ -319,11 +262,6 @@ if use_libunwind: unwindEnv.ShimLibrary( name="unwind", - # We don't want the shim_allocator hack to apply to this library, since - # otherwise we would create a loop, since tcmalloc might use us. That should - # be OK, unless libunwind had static initializers that invoked malloc. - # TODO: Remove when SERVER-48291 is merged into stable build tools - DISABLE_ALLOCATOR_SHIM_INJECTION=True, ) fmtEnv = env.Clone() @@ -447,7 +385,9 @@ else: 'zlib' + zlibSuffix + '/zlib', ]) -zlibEnv.ShimLibrary(name="zlib") +zlibEnv.ShimLibrary( + name="zlib", +) zstdEnv = env.Clone() if use_system_version_of_library("zstd"): @@ -464,7 +404,9 @@ else: 'zstandard' + zstdSuffix + '/zstd', ]) -zstdEnv.ShimLibrary(name="zstd") +zstdEnv.ShimLibrary( + name="zstd", +) benchmarkEnv = env.Clone() if use_system_version_of_library("google-benchmark"): @@ -504,14 +446,16 @@ if "tom" in env["MONGO_CRYPTO"]: 'tomcrypt' + tomcryptSuffix + '/tomcrypt', ]) - tomcryptEnv.ShimLibrary(name="tomcrypt") + tomcryptEnv.ShimLibrary( + name="tomcrypt", + ) gperftoolsEnv = env.Clone( - LIBDEPS_GLOBAL=[ - dep - for dep in env.get('LIBDEPS_GLOBAL', []) - if not dep.endswith('shim_allocator') + LIBDEPS_NO_INHERIT=[ + '$BUILD_DIR/shim_crt', + '$BUILD_DIR/shim_cxx', + '$BUILD_DIR/third_party/shim_allocator', ], ) if gperftoolsEnv['MONGO_ALLOCATOR'] in ["tcmalloc", "tcmalloc-experimental"]: @@ -539,19 +483,17 @@ if gperftoolsEnv['MONGO_ALLOCATOR'] in ["tcmalloc", "tcmalloc-experimental"]: gperftoolsEnv.ShimLibrary( name="allocator", - # TODO: Remove when SERVER-48291 is merged into stable build tools - DISABLE_ALLOCATOR_SHIM_INJECTION=True, LIBDEPS_TAGS=[ - # TODO: Remove all of these when SERVER-48291 is merged into stable build tools - # The shim allocator must be linked to every node, including what would - # be considered a leaf node to ensure the system allocator - # is not linked in before tcmalloc. This tag allows nodes tagged as - # leaf nodes to still get the correct allocator. + # TODO: Remove when SERVER-48291 is merged into stable build tools. + # An inserted dependency must be linked to every node, including what would + # be considered a leaf node to ensure that a system dependency is not linked + # in before this one. This tag allows nodes tagged as leaf nodes to still + # get the correct allocator. 'lint-leaf-node-allowed-dep', - # This tag allows the allocator to be linked to nodes marked as not + # This tag allows this dependency to be linked to nodes marked as not # allowed to have public dependencies. 'lint-public-dep-allowed' - ], + ] ) @@ -598,7 +540,9 @@ timelibEnv = timelibEnv.Clone( 'timelib' + timelibSuffix + '/timelib', ]) -timelibEnv.ShimLibrary(name='timelib') +timelibEnv.ShimLibrary( + name='timelib', +) wiredtigerEnv = env.Clone() if wiredtiger: @@ -650,7 +594,9 @@ else: 'IntelRDFPMathLib20U1/intel_decimal128', ]) -intelDecimal128Env.ShimLibrary(name="intel_decimal128") +intelDecimal128Env.ShimLibrary( + name="intel_decimal128", +) icuEnv = env.Clone() if use_system_version_of_library("icu"): @@ -669,7 +615,9 @@ else: 'icu4c' + icuSuffix + '/source/icu_i18n', ]) -icuEnv.ShimLibrary(name="icu") +icuEnv.ShimLibrary( + name="icu", +) kmsEnv = env.Clone() if get_option('ssl') == 'on': @@ -687,5 +635,7 @@ if get_option('ssl') == 'on': 'kms-message/kms-message', ]) - kmsEnv.ShimLibrary(name="kms_message") + kmsEnv.ShimLibrary( + name="kms_message", + ) diff --git a/src/third_party/gperftools/SConscript b/src/third_party/gperftools/SConscript index 2025d7a9ea6..4cc7596feb4 100644 --- a/src/third_party/gperftools/SConscript +++ b/src/third_party/gperftools/SConscript @@ -123,13 +123,4 @@ env.Library( LIBDEPS_PRIVATE=[ '$BUILD_DIR/third_party/shim_unwind' if use_libunwind else [], ], - # We don't want the shim_allocator hack to apply to this library, since - # otherwise we would create a loop. - LIBDEPS_GLOBAL=[ - dep - for dep in env.get('LIBDEPS_GLOBAL', []) - if not dep.endswith('shim_allocator') - ], - # TODO: Remove when SERVER-48291 is merged into stable build tools - DISABLE_ALLOCATOR_SHIM_INJECTION=True, ) diff --git a/src/third_party/unwind/SConscript b/src/third_party/unwind/SConscript index 983478dd22a..adbd0114832 100644 --- a/src/third_party/unwind/SConscript +++ b/src/third_party/unwind/SConscript @@ -125,14 +125,4 @@ env.Append( env.Library( target='unwind', source=env.File(unwind_sources, unwind_src_dir), - # We don't want the shim_allocator hack to apply to this library, since - # otherwise we would create a loop, since tcmalloc might use us. That should - # be OK, unless libunwind had static initializers that invoked malloc. - LIBDEPS_GLOBAL=[ - dep - for dep in env.get('LIBDEPS_GLOBAL', []) - if not dep.endswith('shim_allocator') - ], - # TODO: Remove when SERVER-48291 is merged into stable build tools - DISABLE_ALLOCATOR_SHIM_INJECTION=True, ) |