summaryrefslogtreecommitdiff
path: root/SConstruct
diff options
context:
space:
mode:
authorAndrew Morrow <acm@mongodb.com>2015-03-22 19:06:54 -0400
committerAndrew Morrow <acm@mongodb.com>2015-07-23 19:07:11 -0400
commit92f1bacdb1dbc17919e7a0f77f0d6c5b981933da (patch)
treec3f4a03e330525bcac588072b594fa0552fb528e /SConstruct
parent4e2ef9c48e7df15e5e55afcc985f4b501c69e52d (diff)
downloadmongo-92f1bacdb1dbc17919e7a0f77f0d6c5b981933da.tar.gz
SERVER-9564 Expose linking model choice as a build option
Diffstat (limited to 'SConstruct')
-rw-r--r--SConstruct77
1 files changed, 71 insertions, 6 deletions
diff --git a/SConstruct b/SConstruct
index 0a3273a7158..e3700eb5398 100644
--- a/SConstruct
+++ b/SConstruct
@@ -455,6 +455,14 @@ add_option('variables-files',
help="Specify variables files to load",
)
+link_model_choices = ['auto', 'object', 'static', 'dynamic', 'dynamic-strict']
+add_option('link-model',
+ choices=link_model_choices,
+ default='object',
+ help='Select the linking model for the project',
+ type='choice'
+)
+
variable_parse_mode_choices=['auto', 'posix', 'other']
add_option('variable-parse-mode',
choices=variable_parse_mode_choices,
@@ -992,6 +1000,59 @@ if has_option("cache"):
env.FatalError("Mixing --cache and --gcov doesn't work correctly yet. See SERVER-11084")
env.CacheDir(str(env.Dir(cacheDir)))
+# Normalize the link model. If it is auto, then a release build uses 'object' mode. Otherwise
+# we automatically select the 'static' model on non-windows platforms, or 'object' if on
+# Windows. If the user specified, honor the request, unless it conflicts with the requirement
+# that release builds use the 'object' mode, in which case, error out.
+#
+# We require the use of the 'object' mode for release builds because it is the only linking
+# model that works across all of our platforms. We would like to ensure that all of our
+# released artifacts are built with the same known-good-everywhere model.
+link_model = get_option('link-model')
+
+if link_model == "auto":
+ link_model = "object" if (env.TargetOSIs('windows') or has_option("release")) else "static"
+elif has_option("release") and link_model != "object":
+ print("The link model for release builds is required to be 'object'")
+ Exit(1)
+
+# The only link model currently supported on Windows is 'object', since there is no equivalent
+# to --whole-archive.
+if env.TargetOSIs('windows') and link_model != 'object':
+ print("Windows builds must use the 'object' link model");
+ Exit(1);
+
+# The 'object' mode for libdeps is enabled by setting _LIBDEPS to $_LIBDEPS_OBJS. The other two
+# modes operate in library mode, enabled by setting _LIBDEPS to $_LIBDEPS_LIBS.
+env['_LIBDEPS'] = '$_LIBDEPS_OBJS' if link_model == "object" else '$_LIBDEPS_LIBS'
+
+if link_model.startswith("dynamic"):
+
+ # Redirect the 'Library' target, which we always use instead of 'StaticLibrary' for things
+ # that can be built in either mode, to point to SharedLibrary.
+ env['BUILDERS']['Library'] = env['BUILDERS']['SharedLibrary']
+
+ # TODO: Ideally, the conditions below should be based on a detection of what linker we are
+ # using, not the local OS, but I doubt very much that we will see the mach-o linker on
+ # anything other than Darwin, or a BFD/sun-esque linker elsewhere.
+
+ # On Darwin, we need to tell the linker that undefined symbols are resolved via dynamic
+ # lookup; otherwise we get build failures. On other unixes, we need to suppress as-needed
+ # behavior so that initializers are ensured present, even if there is no visible edge to
+ # the library in the symbol graph.
+ #
+ # NOTE: The darwin linker flag is only needed because the library graph is not a DAG. Once
+ # the graph is a DAG, we will require all edges to be expressed, and we should drop the
+ # flag. When that happens, we should also add -z,defs flag on ELF platforms to ensure that
+ # missing symbols due to unnamed dependency edges result in link errors.
+ if env.TargetOSIs('osx'):
+ if link_model != "dynamic-strict":
+ env.AppendUnique(SHLINKFLAGS=["-Wl,-undefined,dynamic_lookup"])
+ else:
+ env.AppendUnique(SHLINKFLAGS=["-Wl,--no-as-needed"])
+ if link_model == "dynamic-strict":
+ env.AppendUnique(SHLINKFLAGS=["-Wl,-z,defs"])
+
if optBuild:
env.SetConfigHeaderDefine("MONGO_CONFIG_OPTIMIZED_BUILD")
@@ -1022,8 +1083,6 @@ if endian == "little":
elif endian == "big":
env.SetConfigHeaderDefine("MONGO_CONFIG_BYTE_ORDER", "4321")
-env['_LIBDEPS'] = '$_LIBDEPS_OBJS'
-
if env['_LIBDEPS'] == '$_LIBDEPS_OBJS':
# The libraries we build in LIBDEPS_OBJS mode are just placeholders for tracking dependencies.
# This avoids wasting time and disk IO on them.
@@ -1040,17 +1099,23 @@ if env['_LIBDEPS'] == '$_LIBDEPS_OBJS':
env['RANLIBCOM'] = noop_action
env['RANLIBCOMSTR'] = 'Skipping ranlib for $TARGET'
-libdeps.setup_environment( env )
+libdeps.setup_environment(env, emitting_shared=(link_model.startswith("dynamic")))
-if env.TargetOSIs('linux', 'freebsd'):
+if env.TargetOSIs('linux', 'freebsd', 'openbsd'):
env['LINK_LIBGROUP_START'] = '-Wl,--start-group'
env['LINK_LIBGROUP_END'] = '-Wl,--end-group'
+ env['LINK_WHOLE_ARCHIVE_START'] = '-Wl,--whole-archive'
+ env['LINK_WHOLE_ARCHIVE_END'] = '-Wl,--no-whole-archive'
elif env.TargetOSIs('osx'):
env['LINK_LIBGROUP_START'] = ''
env['LINK_LIBGROUP_END'] = ''
+ env['LINK_WHOLE_ARCHIVE_START'] = '-Wl,-all_load'
+ env['LINK_WHOLE_ARCHIVE_END'] = '-Wl,-noall_load'
elif env.TargetOSIs('solaris'):
- env['LINK_LIBGROUP_START'] = '-z rescan'
- env['LINK_LIBGROUP_END'] = ''
+ env['LINK_LIBGROUP_START'] = '-z rescan-start'
+ env['LINK_LIBGROUP_END'] = '-z rescan-end'
+ env['LINK_WHOLE_ARCHIVE_START'] = '-z allextract'
+ env['LINK_WHOLE_ARCHIVE_END'] = '-z defaultextract'
# ---- other build setup -----
if debugBuild: