From e9fc3c3ae2b83539d36856d2f1b5794019b6b41b Mon Sep 17 00:00:00 2001 From: Andrew Morrow Date: Fri, 24 Jul 2015 15:37:27 -0400 Subject: [PATCH] SERVER-9564 When libabigail utils are present, minimize relinking --- SConstruct | 10 +++++ site_scons/libdeps.py | 8 +++- site_scons/site_tools/abilink.py | 66 ++++++++++++++++++++++++++++++++ 3 files changed, 82 insertions(+), 2 deletions(-) create mode 100644 site_scons/site_tools/abilink.py diff --git a/SConstruct b/SConstruct index e3700eb5398c3..e60a7f350c87d 100644 --- a/SConstruct +++ b/SConstruct @@ -564,6 +564,9 @@ env_vars = Variables( args=ARGUMENTS ) +env_vars.Add('ABIDW', + help="Configures the path to the 'abidw' (a libabigail) utility") + env_vars.Add('ARFLAGS', help='Sets flags for the archiver', converter=variable_shlex_converter) @@ -1028,6 +1031,13 @@ env['_LIBDEPS'] = '$_LIBDEPS_OBJS' if link_model == "object" else '$_LIBDEPS_LIB if link_model.startswith("dynamic"): + # Add in the abi linking tool if the user requested and it is + # supported on this platform. + if env.get('ABIDW'): + abilink = Tool('abilink') + if abilink.exists(env): + abilink(env) + # 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'] diff --git a/site_scons/libdeps.py b/site_scons/libdeps.py index 4c8dbf1b24f5b..87d96606cef95 100644 --- a/site_scons/libdeps.py +++ b/site_scons/libdeps.py @@ -235,7 +235,9 @@ def libdeps_emitter(target, source, env): file_name = '${LIBPREFIX}' + file_name if not file_name.endswith(lib_suffix): file_name += '${LIBSUFFIX}' - libdep_files.append(env.File(os.path.join(dir_name, file_name))) + + node_factory = env['BUILDERS']['StaticLibrary'].target_factory or env.File + libdep_files.append(node_factory(os.path.join(dir_name, file_name))) for t in target: # target[0] must be a Node and not a string, or else libdeps will fail to @@ -276,7 +278,9 @@ def shlibdeps_emitter(target, source, env): file_name = '${SHLIBPREFIX}' + file_name if not file_name.endswith(lib_suffix): file_name += '${SHLIBSUFFIX}' - libdep_files.append(env.File(os.path.join(dir_name, file_name))) + + node_factory = env['BUILDERS']['SharedLibrary'].target_factory or env.File + libdep_files.append(node_factory(os.path.join(dir_name, file_name))) for t in target: # target[0] must be a Node and not a string, or else libdeps will fail to diff --git a/site_scons/site_tools/abilink.py b/site_scons/site_tools/abilink.py new file mode 100644 index 0000000000000..9f7bad3dce50f --- /dev/null +++ b/site_scons/site_tools/abilink.py @@ -0,0 +1,66 @@ +# Copyright (C) 2015 MongoDB Inc. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License, version 3, +# as published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . + +import SCons +import subprocess + +def _detect(env): + try: + abidw = env['ABIDW'] + if not abidw: + return None + except KeyError: + pass + + return env.WhereIs('abidw') + +def generate(env): + + class AbilinkNode(SCons.Node.FS.File): + def __init__(self, name, directory, fs): + SCons.Node.FS.File.__init__(self, name, directory, fs) + + def get_contents(self): + if not self.rexists(): + return '' + fname = self.rfile().abspath + try: + # TODO: If there were python bindings for libabigail, we + # could avoid the shell out (and probably be faster, as we + # could get exactly the information we want). + contents = subprocess.check_output([env.subst('$ABIDW'), fname]) + except EnvironmentError, e: + if not e.filename: + e.filename = fname + raise + return contents + + def get_content_hash(self): + return SCons.Util.MD5signature(self.get_contents()) + + env['ABIDW'] = _detect(env) + + def ShlibNode(env, name, directory = None, create = 1): + return env.fs._lookup(env.subst(name), directory, AbilinkNode, create) + + env.AddMethod(ShlibNode, 'ShlibNode') + + def shlib_target_factory(arg): + return env.ShlibNode(arg) + + env['BUILDERS']['SharedLibrary'].target_factory = shlib_target_factory + +def exists(env): + result = _detect(env) != None + return result