Skip to content
This repository has been archived by the owner on Dec 11, 2019. It is now read-only.

Commit

Permalink
SERVER-7410 Fix SYSLIBDEPS functionality
Browse files Browse the repository at this point in the history
The previous implementation was not recursively following the LIBDEPS hierarchy, looking for SYSLIBDEPS
to add.  Instead, it was trying to walk a hierachy like LIBDEPS rooted in the SYSLIBDEPS variable.  This
isn't really a meaningful behavior, since SYSLIBDEPS always list system libraries, which are always leaf
nodes in the dependency graph for our build system.
  • Loading branch information
Andy Schwerin authored and milkie committed Nov 6, 2012
1 parent f4270ab commit fdebd7b
Showing 1 changed file with 36 additions and 18 deletions.
54 changes: 36 additions & 18 deletions site_scons/libdeps.py
Expand Up @@ -51,6 +51,9 @@
import SCons.Scanner
import SCons.Util

libdeps_env_var = 'LIBDEPS'
syslibdeps_env_var = 'SYSLIBDEPS'

def sorted_by_str(iterable):
"""Shorthand for sorting an iterable according to its string representation.
Expand All @@ -71,19 +74,19 @@ def __init__(self, first_node ):
def __str__(self):
return " => ".join(str(n) for n in self.cycle_nodes)

def __get_libdeps(node, env_var):
def __get_libdeps(node):
"""Given a SCons Node, return its library dependencies.
Computes the dependencies if they're not already cached.
"""

cached_var_name = env_var + '_cached'
cached_var_name = libdeps_env_var + '_cached'

if not hasattr(node.attributes, cached_var_name):
setattr(node.attributes, cached_var_name, __compute_libdeps(node, env_var))
setattr(node.attributes, cached_var_name, __compute_libdeps(node))
return getattr(node.attributes, cached_var_name)

def __compute_libdeps(node, env_var):
def __compute_libdeps(node):
"""Recursively identify all library dependencies for a node."""

if getattr(node.attributes, 'libdeps_exploring', False):
Expand All @@ -94,11 +97,11 @@ def __compute_libdeps(node, env_var):
node.attributes.libdeps_exploring = True
try:
try:
for child in env.Flatten(env.get(env_var, [])):
for child in env.Flatten(env.get(libdeps_env_var, [])):
if not child:
continue
deps.add(child)
deps.update(__get_libdeps(child, env_var))
deps.update(__get_libdeps(child))

except DependencyCycleError, e:
if len(e.cycle_nodes) == 1 or e.cycle_nodes[0] != e.cycle_nodes[-1]:
Expand All @@ -109,6 +112,20 @@ def __compute_libdeps(node, env_var):

return deps

def __get_syslibdeps(node):
""" Given a SCons Node, return its system library dependencies.
These are the depencencies listed with SYSLIBDEPS, and are linked using -l.
"""
cached_var_name = syslibdeps_env_var + '_cached'
if not hasattr(node.attributes, cached_var_name):
syslibdeps = []
for lib in __get_libdeps(node):
for syslib in lib.get_env().get(syslibdeps_env_var, []):
syslibdeps.append(syslib)
setattr(node.attributes, cached_var_name, sorted(syslibdeps))
return getattr(node.attributes, cached_var_name)

def update_scanner(builder):
"""Update the scanner for "builder" to also scan library dependencies."""

Expand All @@ -118,14 +135,12 @@ def update_scanner(builder):
path_function = old_scanner.path_function
def new_scanner(node, env, path=()):
result = set(old_scanner.function(node, env, path))
result.update(__get_libdeps(node, 'LIBDEPS'))
result.update(__get_libdeps(node, 'SYSLIBDEPS'))
result.update(__get_libdeps(node))
return sorted_by_str(result)
else:
path_function = None
def new_scanner(node, env, path=()):
result = set(__get_libdeps(node, 'LIBDEPS'))
result.update(__get_libdeps(node, 'SYSLIBDEPS'))
result = set(__get_libdeps(node))
return sorted_by_str(result)

builder.target_scanner = SCons.Scanner.Scanner(function=new_scanner,
Expand All @@ -138,7 +153,7 @@ def get_libdeps(source, target, env, for_signature):
"""

target = env.Flatten([target])
return sorted_by_str(__get_libdeps(target[0], 'LIBDEPS'))
return sorted_by_str(__get_libdeps(target[0]))

def get_libdeps_objs(source, target, env, for_signature):
objs = set()
Expand All @@ -151,8 +166,11 @@ def get_libdeps_special_sun(source, target, env, for_signature):
return x + x + x

def get_syslibdeps(source, target, env, for_signature):
deps = list(__get_libdeps(target[0], 'SYSLIBDEPS'))
return deps
deps = __get_syslibdeps(target[0])
lib_link_prefix = env.subst('$LIBLINKPREFIX')
lib_link_suffix = env.subst('$LIBLINKSUFFIX')
result = ''.join([' %s%s%s' % (lib_link_prefix, d, lib_link_suffix) for d in deps])
return result

def libdeps_emitter(target, source, env):
"""SCons emitter that takes values from the LIBDEPS environment variable and
Expand All @@ -172,7 +190,7 @@ def libdeps_emitter(target, source, env):
libdep_files = []
lib_suffix = env.subst('$LIBSUFFIX', target=target, source=source)
lib_prefix = env.subst('$LIBPREFIX', target=target, source=source)
for dep in env.Flatten([env.get('LIBDEPS', [])]):
for dep in env.Flatten([env.get(libdeps_env_var, [])]):
full_path = env.subst(str(dep), target=target, source=source)
dir_name = os.path.dirname(full_path)
file_name = os.path.basename(full_path)
Expand All @@ -182,7 +200,7 @@ def libdeps_emitter(target, source, env):
file_name += '${LIBSUFFIX}'
libdep_files.append(env.File(os.path.join(dir_name, file_name)))

env['LIBDEPS'] = libdep_files
env[libdeps_env_var] = libdep_files

return target, source

Expand All @@ -203,11 +221,11 @@ def setup_environment(env):
env['_LIBDEPS_LIBS'] = get_libdeps

env['_LIBDEPS_OBJS'] = get_libdeps_objs
env['_SYSLIBDEPS'] = ' ${_stripixes(LIBLINKPREFIX, SYSLIBDEPS, LIBLINKSUFFIX, LIBPREFIXES, LIBSUFFIXES, __env__)} '
env['_SYSLIBDEPS'] = get_syslibdeps
env['_SHLIBDEPS'] = '$SHLIBDEP_GROUP_START ${_concat(SHLIBDEPPREFIX, __env__.subst(_LIBDEPS, target=TARGET, source=SOURCE), SHLIBDEPSUFFIX, __env__, target=TARGET, source=SOURCE)} $SHLIBDEP_GROUP_END'

env['LIBDEPS'] = SCons.Util.CLVar()
env['SYSLIBDEPS'] = SCons.Util.CLVar()
env[libdeps_env_var] = SCons.Util.CLVar()
env[syslibdeps_env_var] = SCons.Util.CLVar()
env.Append(LIBEMITTER=libdeps_emitter,
PROGEMITTER=libdeps_emitter,
SHLIBEMITTER=libdeps_emitter)
Expand Down

0 comments on commit fdebd7b

Please sign in to comment.