diff options
Diffstat (limited to 'SConstruct')
| -rw-r--r-- | SConstruct | 510 |
1 files changed, 337 insertions, 173 deletions
diff --git a/SConstruct b/SConstruct index d1a1f821d09..bfbfddcb17a 100644 --- a/SConstruct +++ b/SConstruct @@ -3,6 +3,7 @@ import atexit import copy import errno +import functools import json import os import re @@ -30,6 +31,7 @@ import mongo.platform as mongo_platform import mongo.toolchain as mongo_toolchain import mongo.generators as mongo_generators import mongo.install_actions as install_actions +from mongo.build_profiles import BUILD_PROFILES EnsurePythonVersion(3, 6) EnsureSConsVersion(3, 1, 1) @@ -104,9 +106,23 @@ SetOption('random', 1) # using the nargs='const' mechanism. # -add_option('ninja', +add_option( + 'build-profile', + choices=list(BUILD_PROFILES.keys()), + default='default', + type='choice', + help='''Short hand for common build options. These profiles are well supported by SDP and are + kept up to date. Unless you need something specific, it is recommended that you only build with + these. san is the recommeneded profile since it exposes bugs before they are found in patch + builds. Check out site_scons/mongo/build_profiles.py to see each profile.''', +) + +build_profile = BUILD_PROFILES[get_option('build-profile')] + +add_option( + 'ninja', choices=['enabled', 'disabled'], - default='disabled', + default=build_profile.ninja, nargs='?', const='enabled', type='choice', @@ -151,8 +167,9 @@ add_option('install-mode', add_option('install-action', choices=([*install_actions.available_actions] + ['default']), - default='default', - help='select mechanism to use to install files (advanced option to reduce disk IO and utilization)', + default='hardlink', + help= + 'select mechanism to use to install files (advanced option to reduce disk IO and utilization)', nargs=1, type='choice', ) @@ -244,7 +261,7 @@ add_option('noshell', add_option('dbg', choices=['on', 'off'], const='on', - default='off', + default=build_profile.dbg, help='Enable runtime debugging checks', nargs='?', type='choice', @@ -269,8 +286,9 @@ add_option('spider-monkey-dbg', ) add_option('opt', - choices=['on', 'size', 'off'], + choices=['on', 'size', 'off', 'auto'], const='on', + default=build_profile.opt, help='Enable compile-time optimization', nargs='?', type='choice', @@ -311,6 +329,7 @@ add_option('debug-compress', add_option('sanitize', help='enable selected sanitizers', metavar='san1,san2,...sanN', + default=build_profile.sanitize, ) add_option('sanitize-coverage', @@ -320,7 +339,7 @@ add_option('sanitize-coverage', add_option('allocator', choices=["auto", "system", "tcmalloc", "tcmalloc-experimental"], - default="auto", + default=build_profile.allocator, help='allocator to use (use "auto" for best choice for current platform)', type='choice', ) @@ -340,13 +359,6 @@ add_option('gcov', nargs=0, ) -add_option('enable-free-mon', - choices=["auto", "on", "off"], - default="auto", - help='Disable support for Free Monitoring to avoid HTTP client library dependencies', - type='choice', -) - add_option('enable-http-client', choices=["auto", "on", "off"], default="auto", @@ -425,8 +437,9 @@ add_option("disable-warnings-as-errors", action="append", choices=["configure", "source"], const="source", - default=[], - help="Don't add a warnings-as-errors flag to compiler command lines in selected contexts; defaults to 'source' if no argument is provided", + default=build_profile.disable_warnings_as_errors, + help= + "Don't add a warnings-as-errors flag to compiler command lines in selected contexts; defaults to 'source' if no argument is provided", nargs="?", type="choice", ) @@ -493,8 +506,9 @@ def find_mongo_custom_variables(): files.append(probe) return files -add_option('variables-files', - default=[], +add_option( + 'variables-files', + default=build_profile.variables_files, action="append", help="Specify variables files to load.", ) @@ -502,7 +516,7 @@ add_option('variables-files', link_model_choices = ['auto', 'object', 'static', 'dynamic', 'dynamic-strict', 'dynamic-sdk'] add_option('link-model', choices=link_model_choices, - default='auto', + default=build_profile.link_model, help='Select the linking model for the project', type='choice' ) @@ -665,6 +679,17 @@ except ValueError as e: print(("Error decoding version.json: {0}".format(e))) Exit(1) + +def to_boolean(s): + if isinstance(s, bool): + return s + elif s.lower() in ('1', "on", "true", "yes"): + return True + elif s.lower() in ('0', "off", "false", "no"): + return False + raise ValueError(f'Invalid value {s}, must be a boolean-like string') + + # Setup the command-line variables def variable_shlex_converter(val): # If the argument is something other than a string, propagate @@ -696,6 +721,17 @@ def variable_arch_converter(val): # Return whatever val is passed in - hopefully it's legit return val + +def bool_var_converter(val, var): + try: + return to_boolean(val) + except ValueError as exc: + if val.lower() != "auto": + raise ValueError( + f'Invalid {var} value {s}, must be a boolean-like string or "auto"') from exc + return "auto" + + # The Scons 'default' tool enables a lot of tools that we don't actually need to enable. # On platforms like Solaris, it actually does the wrong thing by enabling the sunstudio # toolchain first. As such it is simpler and more efficient to manually load the precise @@ -776,8 +812,11 @@ env_vars.Add('ARFLAGS', help='Sets flags for the archiver', converter=variable_shlex_converter) -env_vars.Add('CCACHE', - help='Tells SCons where the ccache binary is') +env_vars.Add( + 'CCACHE', + help='Tells SCons where the ccache binary is', + default=build_profile.CCACHE, +) env_vars.Add( 'CACHE_SIZE', @@ -824,16 +863,11 @@ env_vars.Add('CXXFLAGS', help='Sets flags for the C++ compiler', converter=variable_shlex_converter) -default_destdir = '$BUILD_ROOT/install' -if get_option('ninja') != 'disabled': - # Workaround for SERVER-53952 where issues wih different - # ninja files building to the same install dir. Different - # ninja files need to build to different install dirs. - default_destdir = '$BUILD_DIR/install' - -env_vars.Add('DESTDIR', +env_vars.Add( + 'DESTDIR', help='Where builds will install files', - default=default_destdir) + default='$BUILD_ROOT/install', +) env_vars.Add('DSYMUTIL', help='Path to the dsymutil utility', @@ -869,8 +903,11 @@ env_vars.Add('HOST_ARCH', converter=variable_arch_converter, default=None) -env_vars.Add('ICECC', - help='Tells SCons where icecream icecc tool is') +env_vars.Add( + 'ICECC', + help='Tells SCons where icecream icecc tool is', + default=build_profile.ICECC, +) env_vars.Add('ICERUN', help='Tells SCons where icecream icerun tool is') @@ -963,11 +1000,12 @@ env_vars.Add('MSVC_VERSION', env_vars.Add('NINJA_BUILDDIR', help="Location for shared Ninja state", - default="$BUILD_DIR/ninja", + default="$BUILD_ROOT/ninja", ) -env_vars.Add('NINJA_PREFIX', - default="build", +env_vars.Add( + 'NINJA_PREFIX', + default=build_profile.NINJA_PREFIX, help="""A prefix to add to the beginning of generated ninja files. Useful for when compiling multiple build ninja files for different configurations, for instance: @@ -980,7 +1018,7 @@ Will generate the files (respectively): asan.ninja tsan.ninja -Defaults to build. Best used with the generate-ninja alias so you don't have to +Defaults to build. Best used with the --ninja flag so you don't have to reiterate the prefix in the target name and variable. """) @@ -1052,8 +1090,18 @@ env_vars.Add('STRIP', help='Path to the strip utility (non-darwin platforms probably use OBJCOPY for this)', ) -env_vars.Add('TAPI', - help="Configures the path to the 'tapi' (an Xcode) utility") +env_vars.Add( + 'ENABLE_OOM_RETRY', + help= + 'Set the boolean (auto, on/off true/false 1/0) to enable retrying a compile or link commands from "out of memory" failures.', + converter=functools.partial(bool_var_converter, var='ENABLE_OOM_RETRY'), + default="False", +) + +env_vars.Add( + 'TAPI', + help="Configures the path to the 'tapi' (an Xcode) utility", +) env_vars.Add('TARGET_ARCH', help='Sets the architecture to build for', @@ -1071,7 +1119,7 @@ env_vars.Add('TOOLS', env_vars.Add('VARIANT_DIR', help='Sets the name (or generator function) for the variant directory', - default=mongo_generators.default_variant_dir_generator, + default=build_profile.VARIANT_DIR, ) env_vars.Add('VERBOSE', @@ -1160,6 +1208,8 @@ dbg_opt_mapping = { ( "off", "off" ) : ( False, False ), ( "on", "size" ) : ( True, True ), ( "off", "size" ) : ( False, True ), + ( "on", "auto" ) : ( True, False ), + ( "off", "auto" ) : ( False, True ), } debugBuild, optBuild = dbg_opt_mapping[(get_option('dbg'), get_option('opt'))] optBuildForSize = True if optBuild and get_option('opt') == "size" else False @@ -1288,15 +1338,6 @@ def conf_error(env, msg, *args): env.AddMethod(fatal_error, 'FatalError') env.AddMethod(conf_error, 'ConfError') -def to_boolean(s): - if isinstance(s, bool): - return s - elif s.lower() in ('1', "on", "true", "yes"): - return True - elif s.lower() in ('0', "off", "false", "no"): - return False - raise ValueError(f'Invalid value {s}, must be a boolean-like string') - # Normalize the VERBOSE Option, and make its value available as a # function. if env['VERBOSE'] == "auto": @@ -1322,8 +1363,6 @@ unknown_vars = env_vars.UnknownVariables() if unknown_vars: env.FatalError("Unknown variables specified: {0}", ", ".join(list(unknown_vars.keys()))) -if get_option('install-action') != 'default' and get_option('ninja') != "disabled": - env.FatalError("Cannot use non-default install actions when generating Ninja.") install_actions.setup(env, get_option('install-action')) def set_config_header_define(env, varname, varval = 1): @@ -1496,6 +1535,34 @@ def is_toolchain(self, *args): env.AddMethod(get_toolchain_name, 'ToolchainName') env.AddMethod(is_toolchain, 'ToolchainIs') +if env.get('ENABLE_OOM_RETRY'): + if get_option('ninja') != 'disabled': + print('ENABLE_OOM_RETRY not compatible with ninja, disabling ENABLE_OOM_RETRY.') + else: + env['OOM_RETRY_ATTEMPTS'] = 10 + env['OOM_RETRY_MAX_DELAY_SECONDS'] = 120 + + if env.ToolchainIs('clang', 'gcc'): + env['OOM_RETRY_MESSAGES'] = [ + ': out of memory', + 'virtual memory exhausted: Cannot allocate memory', + ': fatal error: Killed signal terminated program cc1', + # TODO: SERVER-77322 remove this non memory related ICE. + r'during IPA pass: cp.+g\+\+: internal compiler error', + 'ld terminated with signal 9', + ] + elif env.ToolchainIs('msvc'): + env['OOM_RETRY_MESSAGES'] = [ + 'LNK1102: out of memory', + 'C1060: compiler is out of heap space', + 'c1xx : fatal error C1063: INTERNAL COMPILER ERROR', + r'LNK1171: unable to load mspdbcore\.dll', + "LNK1201: error writing to program database ''", + ] + env['OOM_RETRY_RETURNCODES'] = [1102] + + env.Tool('oom_auto_retry') + if env['TARGET_ARCH']: if not detectSystem.CheckForProcessor(env['TARGET_ARCH']): env.ConfError("Could not detect processor specified in TARGET_ARCH variable") @@ -2092,6 +2159,15 @@ for suboption in get_option('experimental-runtime-hardening'): elif suboption.startswith('+'): selected_experimental_runtime_hardenings.add(suboption[1:]) +# Disable floating-point contractions such as forming of fused multiply-add operations. +if env.ToolchainIs('clang', 'gcc'): + env.Append(CCFLAGS=["-ffp-contract=off"]) +else: + # msvc defaults to /fp:precise. Visual Studio 2022 does not emit floating-point contractions + # with /fp:precise, but previous versions can. Disable contractions altogether by using + # /fp:strict. + env.Append(CCFLAGS=["/fp:strict"]) + if env.TargetOSIs('linux'): env.Append( LIBS=["m"] ) if not env.TargetOSIs('android'): @@ -2622,17 +2698,28 @@ if get_option("system-boost-lib-search-suffixes") is not None: # discover modules, and load the (python) module for each module's build.py mongo_modules = moduleconfig.discover_modules('src/mongo/db/modules', get_option('modules')) -if get_option('ninja') != 'disabled': - for module in mongo_modules: - if hasattr(module, 'NinjaFile'): - env.FatalError(textwrap.dedent("""\ - ERROR: Ninja tool option '--ninja' should not be used with the ninja module. - Remove the ninja module directory or use '--modules= ' to select no modules. - If using enterprise module, explicitly set '--modules=<name-of-enterprise-module>' to exclude the ninja module.""")) +has_ninja_module = False +for module in mongo_modules: + if hasattr(module, 'NinjaFile'): + has_ninja_module = True + break + +if get_option('ninja') != 'disabled' and has_ninja_module: + env.FatalError( + textwrap.dedent("""\ + ERROR: Ninja tool option '--ninja' should not be used with the ninja module. + Using both options simultaneously may clobber build.ninja files. + Remove the ninja module directory or use '--modules= ' to select no modules. + If using enterprise module, explicitly set '--modules=<name-of-enterprise-module>' to exclude the ninja module.""" + )) + +if has_ninja_module: + print( + "WARNING: You are attempting to use the unsupported/legacy ninja module, instead of the integrated ninja generator. You are strongly encouraged to remove the ninja module from your module list and invoke scons with --ninja generate-ninja" + ) # --- check system --- ssl_provider = None -free_monitoring = get_option("enable-free-mon") http_client = get_option("enable-http-client") def isSanitizerEnabled(self, sanitizerName): @@ -2647,7 +2734,6 @@ env.AddMethod(isSanitizerEnabled, 'IsSanitizerEnabled') def doConfigure(myenv): global wiredtiger global ssl_provider - global free_monitoring global http_client # Check that the compilers work. @@ -2824,7 +2910,7 @@ def doConfigure(myenv): conf.Finish() - def AddFlagIfSupported(env, tool, extension, flag, link, **mutation): + def CheckFlag(env, flag, tool, extension, link, **mutation): def CheckFlagTest(context, tool, extension, flag): if link: if tool == 'C': @@ -2896,24 +2982,33 @@ def doConfigure(myenv): }) available = conf.CheckFlag() conf.Finish() - if available: - env.Append(**mutation) return available - def AddToCFLAGSIfSupported(env, flag): - return AddFlagIfSupported(env, 'C', '.c', flag, False, CFLAGS=[flag]) + def AddFlagIfSupported(env, flag, tool, extension, link, **mutation): - def AddToCCFLAGSIfSupported(env, flag): - return AddFlagIfSupported(env, 'C', '.c', flag, False, CCFLAGS=[flag]) + available = CheckFlag(env, flag, tool, extension, link, **mutation) - def AddToCXXFLAGSIfSupported(env, flag): - return AddFlagIfSupported(env, 'C++', '.cpp', flag, False, CXXFLAGS=[flag]) + if available: + env.Append(**mutation) + return available + + conf_check_vars = { + 'CFLAGS': {'tool': 'C', 'extension': '.c', 'link': False}, + 'CCFLAGS': {'tool': 'C', 'extension': '.c', 'link': False}, + 'CXXFLAGS': {'tool': 'C++', 'extension': '.cpp', 'link': False}, + 'LINKFLAGS': {'tool': 'C', 'extension': '.c', 'link': True}, + 'SHLINKFLAGS': {'tool': 'C', 'extension': '.c', 'link': True}, + } - def AddToLINKFLAGSIfSupported(env, flag): - return AddFlagIfSupported(env, 'C', '.c', flag, True, LINKFLAGS=[flag]) + def var_func(env, flag, var, func): + kwargs = dict({var: [flag]}, **conf_check_vars[var]) + return func(env, flag, **kwargs) - def AddToSHLINKFLAGSIfSupported(env, flag): - return AddFlagIfSupported(env, 'C', '.c', flag, True, SHLINKFLAGS=[flag]) + for var in conf_check_vars: + myenv.AddMethod( + functools.partial(var_func, var=var, func=AddFlagIfSupported), f"AddTo{var}IfSupported") + myenv.AddMethod( + functools.partial(var_func, var=var, func=CheckFlag), f"Check{var}Supported") if myenv.ToolchainIs('gcc', 'clang'): # This tells clang/gcc to use the gold linker if it is available - we prefer the gold linker @@ -2936,20 +3031,20 @@ def doConfigure(myenv): # # We should revisit all of these issues the next time we upgrade our clang minimum. if get_option('separate-debug') == 'off' and get_option('link-model') != 'dynamic': - if not AddToLINKFLAGSIfSupported(myenv, '-fuse-ld=lld'): - AddToLINKFLAGSIfSupported(myenv, '-fuse-ld=gold') + if not myenv.AddToLINKFLAGSIfSupported('-fuse-ld=lld'): + myenv.AddToLINKFLAGSIfSupported('-fuse-ld=gold') else: - AddToLINKFLAGSIfSupported(myenv, '-fuse-ld=gold') + myenv.AddToLINKFLAGSIfSupported('-fuse-ld=gold') elif link_model.startswith("dynamic") and linker_ld == 'bfd': # BFD is not supported due to issues with it causing warnings from some of # the third party libraries that mongodb is linked with: # https://jira.mongodb.org/browse/SERVER-49465 myenv.FatalError(f"Linker {linker_ld} is not supported with dynamic link model builds.") else: - if not AddToLINKFLAGSIfSupported(myenv, f'-fuse-ld={linker_ld}'): + if not myenv.AddToLINKFLAGSIfSupported(f'-fuse-ld={linker_ld}'): myenv.FatalError(f"Linker {linker_ld} could not be configured.") - if has_option('gcov') and AddToCCFLAGSIfSupported(myenv, '-fprofile-update=single'): + if has_option('gcov') and myenv.AddToCCFLAGSIfSupported('-fprofile-update=single'): myenv.AppendUnique(LINKFLAGS=['-fprofile-update=single']) detectCompiler = Configure(myenv, help=False, custom_tests = { @@ -2976,11 +3071,11 @@ def doConfigure(myenv): if myenv.ToolchainIs('clang', 'gcc'): # This warning was added in g++-4.8. - AddToCCFLAGSIfSupported(myenv, '-Wno-unused-local-typedefs') + myenv.AddToCCFLAGSIfSupported('-Wno-unused-local-typedefs') # Clang likes to warn about unused functions, which seems a tad aggressive and breaks # -Werror, which we want to be able to use. - AddToCCFLAGSIfSupported(myenv, '-Wno-unused-function') + myenv.AddToCCFLAGSIfSupported('-Wno-unused-function') # TODO: Note that the following two flags are added to CCFLAGS even though they are # really C++ specific. We need to do this because SCons passes CXXFLAGS *before* @@ -2990,79 +3085,79 @@ def doConfigure(myenv): # # Clang likes to warn about unused private fields, but some of our third_party # libraries have such things. - AddToCCFLAGSIfSupported(myenv, '-Wno-unused-private-field') + myenv.AddToCCFLAGSIfSupported('-Wno-unused-private-field') # Prevents warning about using deprecated features (such as auto_ptr in c++11) # Using -Wno-error=deprecated-declarations does not seem to work on some compilers, # including at least g++-4.6. - AddToCCFLAGSIfSupported(myenv, "-Wno-deprecated-declarations") + myenv.AddToCCFLAGSIfSupported("-Wno-deprecated-declarations") # As of clang-3.4, this warning appears in v8, and gets escalated to an error. - AddToCCFLAGSIfSupported(myenv, "-Wno-tautological-constant-out-of-range-compare") + myenv.AddToCCFLAGSIfSupported("-Wno-tautological-constant-out-of-range-compare") # As of clang in Android NDK 17, these warnings appears in boost and/or ICU, and get escalated to errors - AddToCCFLAGSIfSupported(myenv, "-Wno-tautological-constant-compare") - AddToCCFLAGSIfSupported(myenv, "-Wno-tautological-unsigned-zero-compare") - AddToCCFLAGSIfSupported(myenv, "-Wno-tautological-unsigned-enum-zero-compare") + myenv.AddToCCFLAGSIfSupported("-Wno-tautological-constant-compare") + myenv.AddToCCFLAGSIfSupported("-Wno-tautological-unsigned-zero-compare") + myenv.AddToCCFLAGSIfSupported("-Wno-tautological-unsigned-enum-zero-compare") # New in clang-3.4, trips up things mostly in third_party, but in a few places in the # primary mongo sources as well. - AddToCCFLAGSIfSupported(myenv, "-Wno-unused-const-variable") + myenv.AddToCCFLAGSIfSupported("-Wno-unused-const-variable") # Prevents warning about unused but set variables found in boost version 1.49 # in boost/date_time/format_date_parser.hpp which does not work for compilers # GCC >= 4.6. Error explained in https://svn.boost.org/trac/boost/ticket/6136 . - AddToCCFLAGSIfSupported(myenv, "-Wno-unused-but-set-variable") + myenv.AddToCCFLAGSIfSupported("-Wno-unused-but-set-variable") # This has been suppressed in gcc 4.8, due to false positives, but not in clang. So # we explicitly disable it here. - AddToCCFLAGSIfSupported(myenv, "-Wno-missing-braces") + myenv.AddToCCFLAGSIfSupported("-Wno-missing-braces") # Suppress warnings about not consistently using override everywhere in a class. It seems # very pedantic, and we have a fair number of instances. - AddToCCFLAGSIfSupported(myenv, "-Wno-inconsistent-missing-override") + myenv.AddToCCFLAGSIfSupported("-Wno-inconsistent-missing-override") # Don't issue warnings about potentially evaluated expressions - AddToCCFLAGSIfSupported(myenv, "-Wno-potentially-evaluated-expression") + myenv.AddToCCFLAGSIfSupported("-Wno-potentially-evaluated-expression") # Warn about moves of prvalues, which can inhibit copy elision. - AddToCXXFLAGSIfSupported(myenv, "-Wpessimizing-move") + myenv.AddToCXXFLAGSIfSupported("-Wpessimizing-move") # Disable warning about variables that may not be initialized # Failures are triggered in the case of boost::optional in GCC 4.8.x # TODO: re-evaluate when we move to GCC 5.3 # see: http://stackoverflow.com/questions/21755206/how-to-get-around-gcc-void-b-4-may-be-used-uninitialized-in-this-funct - AddToCXXFLAGSIfSupported(myenv, "-Wno-maybe-uninitialized") + myenv.AddToCXXFLAGSIfSupported("-Wno-maybe-uninitialized") # Disable warning about templates that can't be implicitly instantiated. It is an attempt to # make a link error into an easier-to-debug compiler failure, but it triggers false # positives if explicit instantiation is used in a TU that can see the full definition. This # is a problem at least for the S2 headers. - AddToCXXFLAGSIfSupported(myenv, "-Wno-undefined-var-template") + myenv.AddToCXXFLAGSIfSupported("-Wno-undefined-var-template") # This warning was added in clang-4.0, but it warns about code that is required on some # platforms. Since the warning just states that 'explicit instantiation of [a template] that # occurs after an explicit specialization has no effect', it is harmless on platforms where # it isn't required - AddToCXXFLAGSIfSupported(myenv, "-Wno-instantiation-after-specialization") + myenv.AddToCXXFLAGSIfSupported("-Wno-instantiation-after-specialization") # This warning was added in clang-5 and flags many of our lambdas. Since it isn't actively # harmful to capture unused variables we are suppressing for now with a plan to fix later. - AddToCCFLAGSIfSupported(myenv, "-Wno-unused-lambda-capture") + myenv.AddToCCFLAGSIfSupported("-Wno-unused-lambda-capture") # Enable sized deallocation support. - AddToCXXFLAGSIfSupported(myenv, '-fsized-deallocation') + myenv.AddToCXXFLAGSIfSupported('-fsized-deallocation') # This warning was added in Apple clang version 11 and flags many explicitly defaulted move # constructors and assignment operators for being implicitly deleted, which is not useful. - AddToCXXFLAGSIfSupported(myenv, "-Wno-defaulted-function-deleted") + myenv.AddToCXXFLAGSIfSupported("-Wno-defaulted-function-deleted") # SERVER-44856: Our windows builds complain about unused # exception parameters, but GCC and clang don't seem to do # that for us automatically. In the interest of making it more # likely to catch these errors early, add the (currently clang # only) flag that turns it on. - AddToCXXFLAGSIfSupported(myenv, "-Wunused-exception-parameter") + myenv.AddToCXXFLAGSIfSupported("-Wunused-exception-parameter") # TODO(SERVER-60151): Avoid the dilemma identified in # https://gcc.gnu.org/bugzilla/show_bug.cgi?id=100493. Unfortunately, @@ -3074,7 +3169,7 @@ def doConfigure(myenv): # TODO(SERVER-60175): In fact we will want to explicitly opt # in to -Wdeprecated, since clang doesn't include it in -Wall. if get_option('cxx-std') == "20": - AddToCXXFLAGSIfSupported(myenv, '-Wno-deprecated') + myenv.AddToCXXFLAGSIfSupported('-Wno-deprecated') # Check if we can set "-Wnon-virtual-dtor" when "-Werror" is set. The only time we can't set it is on # clang 3.4, where a class with virtual function(s) and a non-virtual destructor throws a warning when @@ -3118,25 +3213,21 @@ def doConfigure(myenv): # by -Wall), in order to enforce that -mXXX-version-min=YYY # will enforce that you don't use APIs from ZZZ. if env.TargetOSIs('darwin'): - AddToCCFLAGSIfSupported(env, '-Wunguarded-availability') + env.AddToCCFLAGSIfSupported('-Wunguarded-availability') if get_option('runtime-hardening') == "on": # Enable 'strong' stack protection preferentially, but fall back to 'all' if it is not # available. Note that we need to add these to the LINKFLAGS as well, since otherwise we # might not link libssp when we need to (see SERVER-12456). if myenv.ToolchainIs('gcc', 'clang'): - if AddToCCFLAGSIfSupported(myenv, '-fstack-protector-strong'): - myenv.Append( - LINKFLAGS=[ - '-fstack-protector-strong', - ] - ) - elif AddToCCFLAGSIfSupported(myenv, '-fstack-protector-all'): - myenv.Append( - LINKFLAGS=[ - '-fstack-protector-all', - ] - ) + if myenv.AddToCCFLAGSIfSupported('-fstack-protector-strong'): + myenv.Append(LINKFLAGS=[ + '-fstack-protector-strong', + ], ) + elif myenv.AddToCCFLAGSIfSupported('-fstack-protector-all'): + myenv.Append(LINKFLAGS=[ + '-fstack-protector-all', + ], ) if 'cfex' in selected_experimental_runtime_hardenings: myenv.Append( @@ -3144,10 +3235,10 @@ def doConfigure(myenv): ) if 'stackclash' in selected_experimental_runtime_hardenings: - AddToCCFLAGSIfSupported(myenv, "-fstack-clash-protection") + myenv.AddToCCFLAGSIfSupported("-fstack-clash-protection") if 'controlflow' in selected_experimental_runtime_hardenings: - AddToCCFLAGSIfSupported(myenv, "-fcf-protection=full") + myenv.AddToCCFLAGSIfSupported("-fcf-protection=full") if myenv.ToolchainIs('clang'): # TODO: There are several interesting things to try here, but they each have @@ -3190,7 +3281,7 @@ def doConfigure(myenv): if has_option('libc++'): if not myenv.ToolchainIs('clang'): myenv.FatalError('libc++ is currently only supported for clang') - if AddToCXXFLAGSIfSupported(myenv, '-stdlib=libc++'): + if myenv.AddToCXXFLAGSIfSupported('-stdlib=libc++'): myenv.Append(LINKFLAGS=['-stdlib=libc++']) else: myenv.ConfError('libc++ requested, but compiler does not support -stdlib=libc++' ) @@ -3221,14 +3312,13 @@ def doConfigure(myenv): myenv.AppendUnique(CCFLAGS=['/std:c++20']) else: if get_option('cxx-std') == "17": - if not AddToCXXFLAGSIfSupported(myenv, '-std=c++17'): + if not myenv.AddToCXXFLAGSIfSupported('-std=c++17'): myenv.ConfError('Compiler does not honor -std=c++17') elif get_option('cxx-std') == "20": - if not AddToCXXFLAGSIfSupported(myenv, '-std=c++20'): + if not myenv.AddToCXXFLAGSIfSupported('-std=c++20'): myenv.ConfError('Compiler does not honor -std=c++20') - - if not AddToCFLAGSIfSupported(myenv, '-std=c11'): + if not myenv.AddToCFLAGSIfSupported('-std=c11'): myenv.ConfError("C++17 mode selected for C++ files, but can't enable C11 for C files") if using_system_version_of_cxx_libraries(): @@ -3501,7 +3591,7 @@ def doConfigure(myenv): sanitizer_option = '-fsanitize=' + ','.join(sanitizer_list) - if AddToCCFLAGSIfSupported(myenv, sanitizer_option): + if myenv.AddToCCFLAGSIfSupported(sanitizer_option): myenv.Append(LINKFLAGS=[sanitizer_option]) myenv.Append(CCFLAGS=['-fno-omit-frame-pointer']) else: @@ -3512,7 +3602,7 @@ def doConfigure(myenv): if has_option('sanitize-coverage') and using_fsan: sanitize_coverage_list = get_option('sanitize-coverage') sanitize_coverage_option = '-fsanitize-coverage=' + sanitize_coverage_list - if AddToCCFLAGSIfSupported(myenv,sanitize_coverage_option): + if myenv.AddToCCFLAGSIfSupported(sanitize_coverage_option): myenv.Append(LINKFLAGS=[sanitize_coverage_option]) else: myenv.ConfError('Failed to enable -fsanitize-coverage with flag: {0}', sanitize_coverage_option ) @@ -3534,7 +3624,7 @@ def doConfigure(myenv): supportedDenyfiles = [] denyfilesTestEnv = myenv.Clone() for denyfile in denyfiles: - if AddToCCFLAGSIfSupported(denyfilesTestEnv, f"-fsanitize-blacklist={denyfile}"): + if denyfilesTestEnv.AddToCCFLAGSIfSupported(f"-fsanitize-blacklist={denyfile}"): supportedDenyfiles.append(denyfile) denyfilesTestEnv = None supportedDenyfiles = sorted(supportedDenyfiles) @@ -3669,8 +3759,8 @@ def doConfigure(myenv): # have renamed the flag. # However, this flag cannot be included when using the fuzzer sanitizer # if we want to suppress errors to uncover new ones. - if not using_fsan and not AddToCCFLAGSIfSupported(myenv, "-fno-sanitize-recover"): - AddToCCFLAGSIfSupported(myenv, "-fno-sanitize-recover=undefined") + if not using_fsan and not myenv.AddToCCFLAGSIfSupported("-fno-sanitize-recover"): + myenv.AddToCCFLAGSIfSupported("-fno-sanitize-recover=undefined") myenv.AppendUnique(CPPDEFINES=['UNDEFINED_BEHAVIOR_SANITIZER']) # If anything is changed, added, or removed in ubsan_options, be @@ -3692,7 +3782,7 @@ def doConfigure(myenv): # same as the correct link graph for a regular dynamic # build. if link_model == "dynamic": - if AddToCCFLAGSIfSupported(myenv, "-fno-sanitize=vptr"): + if myenv.AddToCCFLAGSIfSupported("-fno-sanitize=vptr"): myenv.AppendUnique(LINKFLAGS=["-fno-sanitize=vptr"]) if myenv.ToolchainIs('msvc') and optBuild: @@ -3711,21 +3801,28 @@ def doConfigure(myenv): # Usually, --gdb-index is too expensive in big static binaries, but for dynamic # builds it works well. if link_model.startswith("dynamic"): - AddToLINKFLAGSIfSupported(myenv, '-Wl,--gdb-index') + myenv.AddToLINKFLAGSIfSupported('-Wl,--gdb-index') + + if link_model != 'dynamic': + # This will create an extra section where debug types can be referred from, + # reducing other section sizes. This helps most with big static links as there + # will be lots of duplicate debug type info. + myenv.AddToCCFLAGSIfSupported('-fdebug-types-section') + myenv.AddToLINKFLAGSIfSupported('-fdebug-types-section') # Our build is already parallel. - AddToLINKFLAGSIfSupported(myenv, '-Wl,--no-threads') + myenv.AddToLINKFLAGSIfSupported('-Wl,--no-threads') # Explicitly enable GNU build id's if the linker supports it. - AddToLINKFLAGSIfSupported(myenv, '-Wl,--build-id') + myenv.AddToLINKFLAGSIfSupported('-Wl,--build-id') # Explicitly use the new gnu hash section if the linker offers # it, except on android since older runtimes seem to not # support it. For that platform, use 'both'. if env.TargetOSIs('android'): - AddToLINKFLAGSIfSupported(myenv, '-Wl,--hash-style=both') + myenv.AddToLINKFLAGSIfSupported('-Wl,--hash-style=both') else: - AddToLINKFLAGSIfSupported(myenv, '-Wl,--hash-style=gnu') + myenv.AddToLINKFLAGSIfSupported('-Wl,--hash-style=gnu') # Try to have the linker tell us about ODR violations. Don't # use it when using clang with libstdc++, as libstdc++ was @@ -3737,17 +3834,17 @@ def doConfigure(myenv): env.FatalError('The --detect-odr-violations flag does not work with clang and libstdc++') if optBuild: env.FatalError('The --detect-odr-violations flag is expected to only be reliable with --opt=off') - AddToLINKFLAGSIfSupported(myenv, '-Wl,--detect-odr-violations') + myenv.AddToLINKFLAGSIfSupported('-Wl,--detect-odr-violations') # Disallow an executable stack. Also, issue a warning if any files are found that would # cause the stack to become executable if the noexecstack flag was not in play, so that we # can find them and fix them. We do this here after we check for ld.gold because the # --warn-execstack is currently only offered with gold. - AddToLINKFLAGSIfSupported(myenv, "-Wl,-z,noexecstack") - AddToLINKFLAGSIfSupported(myenv, "-Wl,--warn-execstack") + myenv.AddToLINKFLAGSIfSupported("-Wl,-z,noexecstack") + myenv.AddToLINKFLAGSIfSupported("-Wl,--warn-execstack") # If possible with the current linker, mark relocations as read-only. - AddToLINKFLAGSIfSupported(myenv, "-Wl,-z,relro") + myenv.AddToLINKFLAGSIfSupported("-Wl,-z,relro") # As far as we know these flags only apply on posix-y systems, # and not on Darwin. @@ -3780,9 +3877,9 @@ def doConfigure(myenv): compress_type="zlib-gabi" compress_flag="compress-debug-sections" - AddToCCFLAGSIfSupported( - myenv, - f"-Wa,--{compress_flag}={compress_type}" if "as" in debug_compress else f"-Wa,--no{compress_flag}") + myenv.AddToCCFLAGSIfSupported( + f"-Wa,--{compress_flag}={compress_type}" + if "as" in debug_compress else f"-Wa,--no{compress_flag}", ) # We shouldn't enable debug compression in the linker # (meaning our final binaries contain compressed debug @@ -3814,20 +3911,16 @@ def doConfigure(myenv): conf.Finish() if have_shf_compressed and 'ld' in debug_compress: - AddToLINKFLAGSIfSupported( - myenv, - f"-Wl,--{compress_flag}={compress_type}") + myenv.AddToLINKFLAGSIfSupported(f"-Wl,--{compress_flag}={compress_type}", ) else: - AddToLINKFLAGSIfSupported( - myenv, - f"-Wl,--{compress_flag}=none") + myenv.AddToLINKFLAGSIfSupported(f"-Wl,--{compress_flag}=none", ) if "fnsi" in selected_experimental_optimizations: - AddToCCFLAGSIfSupported(myenv, "-fno-semantic-interposition") + myenv.AddToCCFLAGSIfSupported("-fno-semantic-interposition") # Avoid deduping symbols on OS X debug builds, as it takes a long time. if not optBuild and myenv.ToolchainIs('clang') and env.TargetOSIs('darwin'): - AddToLINKFLAGSIfSupported(myenv, "-Wl,-no_deduplicate") + myenv.AddToLINKFLAGSIfSupported("-Wl,-no_deduplicate") # Apply any link time optimization settings as selected by the 'lto' option. if has_option('lto'): @@ -3844,13 +3937,13 @@ def doConfigure(myenv): elif myenv.ToolchainIs('gcc', 'clang'): # For GCC and clang, the flag is -flto, and we need to pass it both on the compile # and link lines. - if not AddToCCFLAGSIfSupported(myenv, '-flto') or \ - not AddToLINKFLAGSIfSupported(myenv, '-flto'): + if not myenv.AddToCCFLAGSIfSupported('-flto') or \ + not myenv.AddToLINKFLAGSIfSupported('-flto'): myenv.ConfError("Link time optimization requested, " "but selected compiler does not honor -flto" ) if myenv.TargetOSIs('darwin'): - AddToLINKFLAGSIfSupported(myenv, '-Wl,-object_path_lto,${TARGET}.lto') + myenv.AddToLINKFLAGSIfSupported('-Wl,-object_path_lto,${TARGET}.lto') else: myenv.ConfError("Don't know how to enable --lto on current toolchain") @@ -3961,7 +4054,7 @@ def doConfigure(myenv): # https://gcc.gnu.org/bugzilla/show_bug.cgi?id=43052 if myenv.ToolchainIs('gcc') and (env['TARGET_ARCH'] in ['i386', 'x86_64']): if not 'builtin-memcmp' in selected_experimental_optimizations: - AddToCCFLAGSIfSupported(myenv, '-fno-builtin-memcmp') + myenv.AddToCCFLAGSIfSupported('-fno-builtin-memcmp') # pthread_setname_np was added in GLIBC 2.12, and Solaris 11.3 if posix_system: @@ -4504,16 +4597,6 @@ def doConfigure(myenv): # ask each module to configure itself and the build environment. moduleconfig.configure_modules(mongo_modules, conf) - # Resolve --enable-free-mon - if free_monitoring == "auto": - if 'enterprise' not in conf.env['MONGO_MODULES']: - free_monitoring = "on" - else: - free_monitoring = "off" - - if free_monitoring == "on": - checkHTTPLib(required=True) - # Resolve --enable-http-client if http_client == "auto": if checkHTTPLib(): @@ -4524,12 +4607,6 @@ def doConfigure(myenv): elif http_client == "on": checkHTTPLib(required=True) - # Sanity check. - # We know that http_client was explicitly disabled here, - # because the free_monitoring check would have failed if no http lib were available. - if (free_monitoring == "on") and (http_client == "off"): - env.ConfError("FreeMonitoring requires an HTTP client which has been explicitly disabled") - if env['TARGET_ARCH'] == "ppc64le": # This checks for an altivec optimization we use in full text search. # Different versions of gcc appear to put output bytes in different @@ -4590,7 +4667,7 @@ def doConfigure(myenv): myenv = conf.Finish() if env['TARGET_ARCH'] == "aarch64": - AddToCCFLAGSIfSupported(myenv, "-moutline-atomics") + myenv.AddToCCFLAGSIfSupported("-moutline-atomics") conf = Configure(myenv) usdt_enabled = get_option('enable-usdt-probes') @@ -4741,6 +4818,54 @@ if get_option('ninja') != 'disabled': env['NINJA_REGENERATE_DEPS'] = ninja_generate_deps + if env.TargetOSIs('windows'): + # The /b option here will make sure that windows updates the mtime + # when copying the file. This allows to not need to use restat for windows + # copy commands. + copy_install_cmd = "cmd.exe /c copy /b $in $out 1>NUL" + else: + copy_install_cmd = "install $in $out" + + if env.GetOption('install-action') == 'hardlink': + if env.TargetOSIs('windows'): + install_cmd = f"cmd.exe /c mklink /h $out $in 1>nul || {copy_install_cmd}" + else: + install_cmd = f"ln $in $out || {copy_install_cmd}" + + elif env.GetOption('install-action') == 'symlink': + + # macOS's ln and Windows mklink command do not support relpaths + # out of the box so we will precompute during generation in a + # custom handler. + def symlink_install_action_function(_env, node): + # should only be one output and input for this case + output_file = _env.NinjaGetOutputs(node)[0] + input_file = _env.NinjaGetDependencies(node)[0] + try: + relpath = os.path.relpath(input_file, os.path.dirname(output_file)) + except ValueError: + relpath = os.path.abspath(input_file) + + return { + "outputs": [output_file], + "rule": "INSTALL", + "inputs": [input_file], + "implicit": _env.NinjaGetDependencies(node), + "variables": {"precious": node.precious, "relpath": relpath}, + } + + env.NinjaRegisterFunctionHandler("installFunc", symlink_install_action_function) + + if env.TargetOSIs('windows'): + install_cmd = "cmd.exe /c mklink $out $relpath 1>nul" + else: + install_cmd = "ln -s $relpath $out" + + else: + install_cmd = copy_install_cmd + + env.NinjaRule("INSTALL", install_cmd, description="Installed $out", pool="install_pool") + if env.TargetOSIs("windows"): # This is a workaround on windows for SERVER-48691 where the line length # in response files is too long: @@ -5060,7 +5185,10 @@ env.AddPackageNameAlias( name="mh-debugsymbols", ) -def rpath_generator(env, source, target, for_signature): +env['RPATH_ESCAPED_DOLLAR_ORIGIN'] = '\\$$$$ORIGIN' + + +def prefix_libdir_rpath_generator(env, source, target, for_signature): # If the PREFIX_LIBDIR has an absolute path, we will use that directly as # RPATH because that indicates the final install destination of the libraries. prefix_libdir = env.subst('$PREFIX_LIBDIR') @@ -5072,16 +5200,18 @@ def rpath_generator(env, source, target, for_signature): lib_rel = os.path.relpath(prefix_libdir, env.subst('$PREFIX_BINDIR')) if env['PLATFORM'] == 'posix':\ - return [env.Literal(f"\\$$ORIGIN/{lib_rel}")] + return f"$RPATH_ESCAPED_DOLLAR_ORIGIN/{lib_rel}" if env['PLATFORM'] == 'darwin': - return [f"@loader_path/{lib_rel}",] + return f"@loader_path/{lib_rel}" + -env['RPATH_GENERATOR'] = rpath_generator +if get_option('link-model').startswith('dynamic'): + env['PREFIX_LIBDIR_RPATH_GENERATOR'] = prefix_libdir_rpath_generator if env['PLATFORM'] == 'posix': env.AppendUnique( - RPATH='$RPATH_GENERATOR', + RPATH=['$PREFIX_LIBDIR_RPATH_GENERATOR'], LINKFLAGS=[ # Most systems *require* -z,origin to make origin work, but android # blows up at runtime if it finds DF_ORIGIN_1 in DT_FLAGS_1. @@ -5102,12 +5232,12 @@ elif env['PLATFORM'] == 'darwin': # so we setup RPATH and LINKFLAGS ourselves. env['RPATHPREFIX'] = '-Wl,-rpath,' env['RPATHSUFFIX'] = '' - env['RPATH'] = '$RPATH_GENERATOR' env.AppendUnique( LINKFLAGS="${_concat(RPATHPREFIX, RPATH, RPATHSUFFIX, __env__)}", SHLINKFLAGS=[ "-Wl,-install_name,@rpath/${TARGET.file}", ], + RPATH=['$PREFIX_LIBDIR_RPATH_GENERATOR'], ) env.Default(env.Alias("install-default")) @@ -5314,7 +5444,6 @@ version_parts = [ int(x) for x in version_parts[:4]] Export([ 'debugBuild', 'endian', - 'free_monitoring', 'get_option', 'has_option', 'http_client', @@ -5423,6 +5552,41 @@ if has_option('jlink'): new_emitter = SCons.Builder.ListEmitter([base_emitter, jlink_emitter]) builder.emitter = new_emitter +first_half_flag = False + + +def half_source_emitter(target, source, env): + global first_half_flag + if first_half_flag: + first_half_flag = False + if not 'conftest' in str(target[0]) and not str(source[0]).endswith('_test.cpp'): + env.Alias('compile_first_half_non_test_source', target) + else: + first_half_flag = True + return target, source + + +# Cribbed from Tool/cc.py and Tool/c++.py. It would be better if +# we could obtain this from SCons. +_CSuffixes = [".c"] +if not SCons.Util.case_sensitive_suffixes(".c", ".C"): + _CSuffixes.append(".C") + +_CXXSuffixes = [".cpp", ".cc", ".cxx", ".c++", ".C++"] +if SCons.Util.case_sensitive_suffixes(".c", ".C"): + _CXXSuffixes.append(".C") + +for object_builder in SCons.Tool.createObjBuilders(env): + emitterdict = object_builder.builder.emitter + for suffix in emitterdict.keys(): + if not suffix in _CSuffixes + _CXXSuffixes: + continue + base = emitterdict[suffix] + emitterdict[suffix] = SCons.Builder.ListEmitter([ + base, + half_source_emitter, + ]) + # Keep this late in the game so that we can investigate attributes set by all the tools that have run. if has_option("cache"): if get_option("cache") == "nolinked": |
