summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--SConstruct165
-rw-r--r--site_scons/libdeps_next.py28
-rw-r--r--src/SConscript187
-rw-r--r--src/mongo/installer/msi/ca/SConscript8
-rw-r--r--src/mongo/platform/SConscript30
-rw-r--r--src/shim_crt.cpp3
-rw-r--r--src/shim_cxx.cpp3
-rw-r--r--src/third_party/SConscript124
-rw-r--r--src/third_party/gperftools/SConscript9
-rw-r--r--src/third_party/unwind/SConscript10
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,
)