summaryrefslogtreecommitdiff
path: root/site_scons
diff options
context:
space:
mode:
Diffstat (limited to 'site_scons')
-rw-r--r--site_scons/libdeps_next.py539
1 files changed, 323 insertions, 216 deletions
diff --git a/site_scons/libdeps_next.py b/site_scons/libdeps_next.py
index 195567eda75..66671b5e969 100644
--- a/site_scons/libdeps_next.py
+++ b/site_scons/libdeps_next.py
@@ -52,11 +52,13 @@ automatically added when missing.
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
from collections import OrderedDict
+from functools import partial
+import enum
import copy
import os
+import sys
import textwrap
-
import SCons.Errors
import SCons.Scanner
import SCons.Util
@@ -69,6 +71,7 @@ class Constants:
Libdeps = "LIBDEPS"
LibdepsCached = "LIBDEPS_cached"
LibdepsDependents = "LIBDEPS_DEPENDENTS"
+ LibdepsGlobal = "LIBDEPS_GLOBAL"
LibdepsInterface ="LIBDEPS_INTERFACE"
LibdepsPrivate = "LIBDEPS_PRIVATE"
LibdepsTypeinfo = "LIBDEPS_TYPEINFO"
@@ -80,9 +83,27 @@ class Constants:
SysLibdepsCached = "SYSLIBDEPS_cached"
SysLibdepsPrivate = "SYSLIBDEPS_PRIVATE"
-class dependency:
- Public, Private, Interface, Typeinfo = list(range(4))
+class deptype(tuple, enum.Enum):
+ Global: tuple = (0, 'GLOBAL')
+ Public: tuple = (1, 'PUBLIC')
+ Private: tuple = (2, 'PRIVATE')
+ Interface: tuple = (3, 'INTERFACE')
+ Typeinfo: tuple = (4, 'TYPEINFO')
+
+ def __lt__(self, other):
+ if self.__class__ is other.__class__:
+ return self.value[0] < other.value[0]
+ return NotImplemented
+
+ def __str__(self):
+ return self.value[1]
+
+ def __int__(self):
+ return self.value[0]
+
+
+class dependency:
def __init__(self, value, deptype, listed_name):
self.target_node = value
self.dependency_type = deptype
@@ -91,6 +112,7 @@ class dependency:
def __str__(self):
return str(self.target_node)
+
class FlaggedLibdep:
"""
Utility class used for processing prefix and postfix flags on libdeps. The class
@@ -361,6 +383,11 @@ class LibdepLinter:
if self._check_for_lint_tags('lint-leaf-node-allowed-dep', libdep.target_node.env):
return
+ # Global dependencies will apply to leaf nodes, so they should
+ # be automatically exempted.
+ if libdep.dependency_type == deptype.Global:
+ return
+
target_type = self.target[0].builder.get_name(self.env)
lib = os.path.basename(str(libdep))
self._raise_libdep_lint_exception(
@@ -410,7 +437,7 @@ class LibdepLinter:
if not self._check_for_lint_tags('lint-no-public-deps', inclusive_tag=True):
return
- if libdep.dependency_type != dependency.Private:
+ if libdep.dependency_type not in (deptype.Global, deptype.Private):
# Check if the libdep exempts itself from this rule.
if self._check_for_lint_tags('lint-public-dep-allowed', libdep.target_node.env):
return
@@ -476,7 +503,7 @@ class LibdepLinter:
return
if (self.target[0].builder.get_name(self.env) == "Program"
- and libdep.dependency_type != dependency.Public):
+ and libdep.dependency_type not in (deptype.Global, deptype.Public)):
lib = os.path.basename(str(libdep))
self._raise_libdep_lint_exception(
@@ -522,7 +549,7 @@ class LibdepLinter:
if self._check_for_lint_tags('lint-allow-nonprivate-on-deps-dependents'):
return
- if (libdep.dependency_type != dependency.Private
+ if (libdep.dependency_type != deptype.Private
and len(self._get_deps_dependents()) > 0):
target_type = self.target[0].builder.get_name(self.env)
@@ -558,29 +585,33 @@ class LibdepLinter:
))
dependency_visibility_ignored = {
- dependency.Public: dependency.Public,
- dependency.Private: dependency.Public,
- dependency.Interface: dependency.Public,
+ deptype.Global: deptype.Public,
+ deptype.Interface: deptype.Public,
+ deptype.Public: deptype.Public,
+ deptype.Private: deptype.Public,
}
dependency_visibility_honored = {
- dependency.Public: dependency.Public,
- dependency.Private: dependency.Private,
- dependency.Interface: dependency.Interface,
+ deptype.Global: deptype.Private,
+ deptype.Interface: deptype.Interface,
+ deptype.Public: deptype.Public,
+ deptype.Private: deptype.Private,
}
dependency_visibility_typeinfo = {
- dependency.Public: dependency.Public,
- dependency.Private: dependency.Private,
- dependency.Interface: dependency.Interface,
- dependency.Typeinfo: dependency.Private,
+ deptype.Global: deptype.Private,
+ deptype.Interface: deptype.Interface,
+ deptype.Public: deptype.Public,
+ deptype.Private: deptype.Private,
+ deptype.Typeinfo: deptype.Private,
}
dep_type_to_env_var = {
- dependency.Public: Constants.Libdeps,
- dependency.Private: Constants.LibdepsPrivate,
- dependency.Interface: Constants.LibdepsInterface,
- dependency.Typeinfo: Constants.LibdepsTypeinfo,
+ deptype.Global: Constants.LibdepsGlobal,
+ deptype.Interface: Constants.LibdepsInterface,
+ deptype.Public: Constants.Libdeps,
+ deptype.Private: Constants.LibdepsPrivate,
+ deptype.Typeinfo: Constants.LibdepsTypeinfo,
}
class DependencyCycleError(SCons.Errors.UserError):
@@ -601,55 +632,75 @@ class LibdepLinterError(SCons.Errors.UserError):
class MissingSyslibdepError(SCons.Errors.UserError):
"""Exception representing a discongruent usages of libdeps"""
-def __get_sorted_direct_libdeps(node):
- direct_sorted = getattr(node.attributes, "libdeps_direct_sorted", False)
- if not direct_sorted:
+def _get_sorted_direct_libdeps(node):
+ direct_sorted = getattr(node.attributes, "libdeps_direct_sorted", None)
+ if direct_sorted is None:
direct = getattr(node.attributes, "libdeps_direct", [])
direct_sorted = sorted(direct, key=lambda t: str(t.target_node))
setattr(node.attributes, "libdeps_direct_sorted", direct_sorted)
return direct_sorted
-def __libdeps_visit(n, marked, tsorted, walking):
+def _libdeps_visit(n, tsorted, marked, walking=None, debug=False):
+ if walking is None:
+ walking = set()
+
if n.target_node in marked:
- return
+ return marked, tsorted
if n.target_node in walking:
raise DependencyCycleError(n.target_node)
walking.add(n.target_node)
+ if debug:
+ print(f" * {n.dependency_type} => {n.listed_name}")
+
try:
- for child in __get_sorted_direct_libdeps(n.target_node):
- if child.dependency_type != dependency.Private:
- __libdeps_visit(child, marked, tsorted, walking=walking)
+ for child in _get_sorted_direct_libdeps(n.target_node):
+ if child.dependency_type != deptype.Private:
+ marked, tsorted = _libdeps_visit(child, tsorted, marked, walking=walking)
marked.add(n.target_node)
- tsorted.append(n.target_node)
+
+ if getattr(n.target_node.attributes, "needs_link", True):
+ tsorted.append(n.target_node)
except DependencyCycleError as e:
if len(e.cycle_nodes) == 1 or e.cycle_nodes[0] != e.cycle_nodes[-1]:
e.cycle_nodes.insert(0, n.target_node)
raise
+ return marked, tsorted
+
-def __get_libdeps(node):
+def _get_libdeps(node, debug=False):
"""Given a SCons Node, return its library dependencies, topologically sorted.
Computes the dependencies if they're not already cached.
"""
+ tsorted = []
+ marked = set()
+
cache = getattr(node.attributes, Constants.LibdepsCached, None)
if cache is not None:
+ if debug:
+ print(" Cache:")
+ for dep in cache:
+ print(f" * {str(dep)}")
return cache
- tsorted = []
- marked = set()
- walking = set()
+ if debug:
+ print(f" Edges:")
- for child in __get_sorted_direct_libdeps(node):
- if child.dependency_type != dependency.Interface:
- __libdeps_visit(child, marked, tsorted, walking)
+ for child in _get_sorted_direct_libdeps(node):
+ if child.dependency_type == deptype.Interface:
+ tsorted.append(child.target_node)
+ if debug:
+ print(f" * {child.dependency_type} => {child.target_node}")
+ else:
+ _, tsorted = _libdeps_visit(child, tsorted, marked, debug=debug)
tsorted.reverse()
setattr(node.attributes, Constants.LibdepsCached, tsorted)
@@ -657,108 +708,122 @@ def __get_libdeps(node):
return tsorted
-def __missing_syslib(name):
+def _missing_syslib(name):
return Constants.MissingLibdep + name
-def update_scanner(builder):
+def update_scanner(env, builder_name=None, debug=False):
"""Update the scanner for "builder" to also scan library dependencies."""
+ builder = env["BUILDERS"][builder_name]
old_scanner = builder.target_scanner
if old_scanner:
path_function = old_scanner.path_function
-
- def new_scanner(node, env, path=()):
- result = old_scanner.function(node, env, path)
- result.extend(__get_libdeps(node))
- return result
-
else:
path_function = None
- def new_scanner(node, env, path=()):
- return __get_libdeps(node)
+ def new_scanner(node, env, path=(), old_scanner=None):
+ if debug:
+ print(f"LIBDEPS SCANNER: {str(node)}")
+ print(f" Declared dependencies:")
+ print(f" global: {env.get(Constants.LibdepsGlobal, None)}")
+ print(f" private: {env.get(Constants.LibdepsPrivate, None)}")
+ print(f" public: {env.get(Constants.Libdeps, None)}")
+ print(f" interface: {env.get(Constants.LibdepsInterface, None)}")
+ print(f" typeinfo: {env.get(Constants.LibdepsTypeinfo, None)}")
+ if old_scanner:
+ result = old_scanner.function(node, env, path)
+ else:
+ result = []
+ result.extend(_get_libdeps(node, debug=debug))
+ if debug:
+ print(f" Build dependencies:")
+ print('\n'.join([' * ' + str(t) for t in result]))
+ print('\n')
+ return result
builder.target_scanner = SCons.Scanner.Scanner(
function=new_scanner, path_function=path_function
)
-def get_libdeps(source, target, env, for_signature):
+def get_libdeps(source, target, env, for_signature, debug=False):
"""Implementation of the special _LIBDEPS environment variable.
Expands to the library dependencies for a target.
"""
target = env.Flatten([target])
- return __get_libdeps(target[0])
+ return _get_libdeps(target[0], debug=debug)
-def get_libdeps_objs(source, target, env, for_signature):
+def get_libdeps_objs(source, target, env, for_signature, debug=False):
objs = []
- for lib in get_libdeps(source, target, env, for_signature):
+ for lib in get_libdeps(source, target, env, for_signature, debug=debug):
# This relies on Node.sources being order stable build-to-build.
objs.extend(lib.sources)
return objs
-def make_get_syslibdeps_callable(shared):
- def get_syslibdeps(source, target, env, for_signature):
- """ Given a SCons Node, return its system library dependencies.
+def stringify_deps(env, deps):
+ lib_link_prefix = env.subst("$LIBLINKPREFIX")
+ lib_link_suffix = env.subst("$LIBLINKSUFFIX")
- These are the dependencies listed with SYSLIBDEPS, and are linked using -l.
- """
+ # Elements of libdeps are either strings (str or unicode), or they're File objects.
+ # If they're File objects, they can be passed straight through. If they're strings,
+ # they're believed to represent library short names, that should be prefixed with -l
+ # or the compiler-specific equivalent. I.e., 'm' becomes '-lm', but 'File("m.a") is passed
+ # through whole cloth.
+ return [f"{lib_link_prefix}{d}{lib_link_suffix}" if isinstance(d, str) else d for d in deps]
+
+
+def get_syslibdeps(source, target, env, for_signature, debug=False, shared=True):
+ """ Given a SCons Node, return its system library dependencies.
+
+ These are the dependencies listed with SYSLIBDEPS, and are linked using -l.
+ """
+
+ deps = getattr(target[0].attributes, Constants.SysLibdepsCached, None)
+ if deps is None:
+
+ # Get the syslibdeps for the current node
+ deps = target[0].get_env().Flatten(copy.copy(target[0].get_env().get(Constants.SysLibdepsPrivate)) or [])
+ deps += target[0].get_env().Flatten(target[0].get_env().get(Constants.SysLibdeps) or [])
+
+ for lib in _get_libdeps(target[0]):
+
+ # For each libdep get its syslibdeps, and then check to see if we can
+ # add it to the deps list. For static build we will also include private
+ # syslibdeps to be transitive. For a dynamic build we will only make
+ # public libdeps transitive.
+ syslibs = []
+ if not shared:
+ syslibs += lib.get_env().get(Constants.SysLibdepsPrivate) or []
+ syslibs += lib.get_env().get(Constants.SysLibdeps) or []
+
+ # Validate the libdeps, a configure check has already checked what
+ # syslibdeps are available so we can hard fail here if a syslibdep
+ # is being attempted to be linked with.
+ for syslib in syslibs:
+ if not syslib:
+ continue
+
+ if isinstance(syslib, str) and syslib.startswith(Constants.MissingLibdep):
+ raise MissingSyslibdepError(textwrap.dedent(f"""\
+ LibdepsError:
+ Target '{str(target[0])}' depends on the availability of a
+ system provided library for '{syslib[len(Constants.MissingLibdep):]}',
+ but no suitable library was found during configuration."""
+ ))
+
+ deps.append(syslib)
- deps = getattr(target[0].attributes, Constants.SysLibdepsCached, None)
- if deps is None:
-
- # Get the sys libdeps for the current node
- deps = target[0].get_env().Flatten(copy.copy(target[0].get_env().get(Constants.SysLibdepsPrivate)) or [])
- deps += target[0].get_env().Flatten(target[0].get_env().get(Constants.SysLibdeps) or [])
-
- for lib in __get_libdeps(target[0]):
-
- # For each libdep get its syslibdeps, and then check to see if we can
- # add it to the deps list. For static build we will also include private
- # syslibdeps to be transitive. For a dynamic build we will only make
- # public libdeps transitive.
- syslibs = []
- if not shared:
- syslibs += lib.get_env().get(Constants.SysLibdepsPrivate) or []
- syslibs += lib.get_env().get(Constants.SysLibdeps) or []
-
- # Validate the libdeps, a configure check has already checked what
- # syslibdeps are available so we can hard fail here if a syslibdep
- # is being attempted to be linked with.
- for syslib in syslibs:
- if not syslib:
- continue
-
- if isinstance(syslib, str) and syslib.startswith(Constants.MissingLibdep):
- raise MissingSyslibdepError(textwrap.dedent(f"""\
- LibdepsError:
- Target '{str(target[0])}' depends on the availability of a
- system provided library for '{syslib[len(Constants.MissingLibdep):]}',
- but no suitable library was found during configuration."""
- ))
-
- deps.append(syslib)
-
- setattr(target[0].attributes, Constants.SysLibdepsCached, deps)
-
- lib_link_prefix = env.subst("$LIBLINKPREFIX")
- lib_link_suffix = env.subst("$LIBLINKSUFFIX")
- # Elements of syslibdeps are either strings (str or unicode), or they're File objects.
- # If they're File objects, they can be passed straight through. If they're strings,
- # they're believed to represent library short names, that should be prefixed with -l
- # or the compiler-specific equivalent. I.e., 'm' becomes '-lm', but 'File("m.a") is passed
- # through whole cloth.
- return [f"{lib_link_prefix}{d}{lib_link_suffix}" if isinstance(d, str) else d for d in deps]
-
- return get_syslibdeps
-
-def __append_direct_libdeps(node, prereq_nodes):
+ setattr(target[0].attributes, Constants.SysLibdepsCached, deps)
+ return stringify_deps(env, deps)
+
+
+def _append_direct_libdeps(node, prereq_nodes):
# We do not bother to decorate nodes that are not actual Objects
if type(node) == str:
return
@@ -767,7 +832,7 @@ def __append_direct_libdeps(node, prereq_nodes):
node.attributes.libdeps_direct.extend(prereq_nodes)
-def __get_flagged_libdeps(source, target, env, for_signature):
+def _get_flagged_libdeps(source, target, env, for_signature):
for lib in get_libdeps(source, target, env, for_signature):
# Make sure lib is a Node so we can get the env to check for flags.
libnode = lib
@@ -814,101 +879,142 @@ def _get_node_with_ixes(env, node, node_builder_type):
_get_node_with_ixes.node_type_ixes = dict()
-def make_libdeps_emitter(
- dependency_builder,
- dependency_map=dependency_visibility_ignored,
- ignore_progdeps=False,
-):
- def libdeps_emitter(target, source, env):
- """SCons emitter that takes values from the LIBDEPS environment variable and
- converts them to File node objects, binding correct path information into
- those File objects.
-
- Emitters run on a particular "target" node during the initial execution of
- the SConscript file, rather than during the later build phase. When they
- run, the "env" environment's working directory information is what you
- expect it to be -- that is, the working directory is considered to be the
- one that contains the SConscript file. This allows specification of
- relative paths to LIBDEPS elements.
-
- This emitter also adds LIBSUFFIX and LIBPREFIX appropriately.
-
- NOTE: For purposes of LIBDEPS_DEPENDENTS propagation, only the first member
- of the "target" list is made a prerequisite of the elements of LIBDEPS_DEPENDENTS.
- """
- # Get all the libdeps from the env so we can
- # can append them to the current target_node.
- libdeps = []
- for dep_type in sorted(dependency_map.keys()):
+def add_libdeps_node(env, target, libdeps):
+ if str(target).endswith(env["SHLIBSUFFIX"]):
+ t_str = _get_node_with_ixes(env, str(target.abspath), target.get_builder().get_name(env)).abspath
+ env.GetLibdepsGraph().add_node(t_str)
+ for libdep in libdeps:
+ if str(libdep.target_node).endswith(env["SHLIBSUFFIX"]):
+ env.GetLibdepsGraph().add_edge(str(libdep.target_node.abspath), t_str, visibility=libdep.dependency_type)
- # Libraries may not be stored as a list in the env,
- # so we must convert single library strings to a list.
- libs = env.get(dep_type_to_env_var[dep_type], []).copy()
- if not SCons.Util.is_List(libs):
- libs = [libs]
- for lib in libs:
- if not lib:
- continue
- lib_with_ixes = _get_node_with_ixes(env, lib, dependency_builder)
- libdeps.append(dependency(lib_with_ixes, dep_type, lib))
-
- # Lint the libdeps to make sure they are following the rules.
- # This will skip some or all of the checks depending on the options
- # and LIBDEPS_TAGS used.
- if not any("conftest" in str(t) for t in target):
- LibdepLinter(env, target).lint_libdeps(libdeps)
-
- # We ignored the dependency_map until now because we needed to use
- # original dependency value for linting. Now go back through and
- # use the map to convert to the desired dependencies, for example
- # all Public in the static linking case.
- for libdep in libdeps:
- libdep.dependency_type = dependency_map[libdep.dependency_type]
+def get_libdeps_nodes(env, target, builder, debug=False, visibility_map=None):
+ if visibility_map is None:
+ visibility_map = dependency_visibility_ignored
+
+ if not SCons.Util.is_List(target):
+ target = [target]
+
+ # 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
+ continue
+
+ # Libraries may not be stored as a list in the env,
+ # so we must convert single library strings to a list.
+ libs = env.get(dep_type_to_env_var[dep_type], []).copy()
+ if not SCons.Util.is_List(libs):
+ libs = [libs]
+
+ for lib in libs:
+ 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))
+
+ return libdeps
+
+
+def libdeps_emitter(target, source, env, debug=False, builder=None, visibility_map=None, ignore_progdeps=False):
+ """SCons emitter that takes values from the LIBDEPS environment variable and
+ converts them to File node objects, binding correct path information into
+ those File objects.
+
+ Emitters run on a particular "target" node during the initial execution of
+ the SConscript file, rather than during the later build phase. When they
+ run, the "env" environment's working directory information is what you
+ expect it to be -- that is, the working directory is considered to be the
+ one that contains the SConscript file. This allows specification of
+ relative paths to LIBDEPS elements.
+ This emitter also adds LIBSUFFIX and LIBPREFIX appropriately.
+
+ NOTE: For purposes of LIBDEPS_DEPENDENTS propagation, only the first member
+ of the "target" list is made a prerequisite of the elements of LIBDEPS_DEPENDENTS.
+ """
+
+ if visibility_map is None:
+ visibility_map = dependency_visibility_ignored
+
+ if debug and not any("conftest" in str(t) for t in target):
+ print(f"LIBDEPS EMITTER: {str(target[0])}")
+ print(f" Declared dependencies:")
+ print(f" global: {env.get(Constants.LibdepsGlobal, None)}")
+ print(f" private: {env.get(Constants.LibdepsPrivate, None)}")
+ 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" 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")
+
+ # Lint the libdeps to make sure they are following the rules.
+ # This will skip some or all of the checks depending on the options
+ # and LIBDEPS_TAGS used.
+ if not any("conftest" in str(t) for t in target):
+ LibdepLinter(env, target).lint_libdeps(libdeps)
+
+ if env.get('SYMBOLDEPSSUFFIX', None):
for t in target:
- # target[0] must be a Node and not a string, or else libdeps will fail to
- # work properly.
- __append_direct_libdeps(t, libdeps)
+ add_libdeps_node(env, t, libdeps)
+
+ # We ignored the visibility_map until now because we needed to use
+ # original dependency value for linting. Now go back through and
+ # use the map to convert to the desired dependencies, for example
+ # all Public in the static linking case.
+ for libdep in libdeps:
+ libdep.dependency_type = visibility_map[libdep.dependency_type]
+
+ for t in target:
+ # target[0] must be a Node and not a string, or else libdeps will fail to
+ # work properly.
+ _append_direct_libdeps(t, libdeps)
+
+ for dependent in env.get(Constants.LibdepsDependents, []):
+ if dependent is None:
+ continue
+
+ visibility = deptype.Private
+ if isinstance(dependent, tuple):
+ visibility = dependent[1]
+ dependent = dependent[0]
+
+ dependentNode = _get_node_with_ixes(
+ env, dependent, builder
+ )
+ _append_direct_libdeps(
+ dependentNode, [dependency(target[0], visibility_map[visibility], dependent)]
+ )
- for dependent in env.get(Constants.LibdepsDependents, []):
+ if not ignore_progdeps:
+ for dependent in env.get(Constants.ProgdepsDependents, []):
if dependent is None:
continue
- visibility = dependency.Private
+ visibility = deptype.Public
if isinstance(dependent, tuple):
+ # TODO: Error here? Non-public PROGDEPS_DEPENDENTS probably are meaningless
visibility = dependent[1]
dependent = dependent[0]
dependentNode = _get_node_with_ixes(
- env, dependent, dependency_builder
+ env, dependent, "Program"
)
- __append_direct_libdeps(
- dependentNode, [dependency(target[0], dependency_map[visibility], dependent)]
+ _append_direct_libdeps(
+ dependentNode, [dependency(target[0], visibility_map[visibility], dependent)]
)
- if not ignore_progdeps:
- for dependent in env.get(Constants.ProgdepsDependents, []):
- if dependent is None:
- continue
-
- visibility = dependency.Public
- if isinstance(dependent, tuple):
- # TODO: Error here? Non-public PROGDEPS_DEPENDENTS probably are meaningless
- visibility = dependent[1]
- dependent = dependent[0]
-
- dependentNode = _get_node_with_ixes(
- env, dependent, "Program"
- )
- __append_direct_libdeps(
- dependentNode, [dependency(target[0], dependency_map[visibility], dependent)]
- )
-
- return target, source
-
- return libdeps_emitter
+ return target, source
def expand_libdeps_tags(source, target, env, for_signature):
@@ -927,7 +1033,7 @@ def expand_libdeps_with_flags(source, target, env, for_signature):
# below a bit cleaner.
prev_libdep = None
- for flagged_libdep in __get_flagged_libdeps(source, target, env, for_signature):
+ for flagged_libdep in _get_flagged_libdeps(source, target, env, for_signature):
# If there are no flags to process we can move on to the next lib.
# start_index wont mater in the case because if there are no flags
@@ -976,7 +1082,7 @@ def generate_libdeps_graph(env):
symbol_deps = []
for target, source in env.get('LIBDEPS_SYMBOL_DEP_FILES', []):
direct_libdeps = []
- for direct_libdep in __get_sorted_direct_libdeps(source):
+ for direct_libdep in _get_sorted_direct_libdeps(source):
env.GetLibdepsGraph().add_edges_from([(
str(direct_libdep.target_node.abspath),
str(source.abspath),
@@ -985,17 +1091,17 @@ def generate_libdeps_graph(env):
EdgeProps.visibility.name: int(direct_libdep.dependency_type)
})])
direct_libdeps.append(direct_libdep.target_node.abspath)
- for libdep in __get_libdeps(source):
+ for libdep in _get_libdeps(source):
if libdep.abspath not in direct_libdeps:
env.GetLibdepsGraph().add_edges_from([(
str(libdep.abspath),
str(source.abspath),
{
EdgeProps.direct.name: 0,
- EdgeProps.visibility.name: 0
+ EdgeProps.visibility.name: int(deptype.Public)
})])
- ld_path = ":".join([os.path.dirname(str(libdep)) for libdep in __get_libdeps(source)])
+ ld_path = ":".join([os.path.dirname(str(libdep)) for libdep in _get_libdeps(source)])
symbol_deps.append(env.Command(
target=target,
source=source,
@@ -1111,7 +1217,8 @@ def generate_graph(env, target, source):
for line in file:
print(line.replace(str(env.Dir("$BUILD_DIR").abspath + os.sep), ''), end='')
-def setup_environment(env, emitting_shared=False, linting='on', sanitize_typeinfo=False):
+
+def setup_environment(env, emitting_shared=False, debug='off', linting='on', sanitize_typeinfo=False):
"""Set up the given build environment to do LIBDEPS tracking."""
LibdepLinter.skip_linting = linting == 'off'
@@ -1123,10 +1230,10 @@ def setup_environment(env, emitting_shared=False, linting='on', sanitize_typeinf
env["_LIBDEPS"] = "$_LIBDEPS_LIBS"
env["_LIBDEPS_TAGS"] = expand_libdeps_tags
- env["_LIBDEPS_GET_LIBS"] = get_libdeps
- env["_LIBDEPS_OBJS"] = get_libdeps_objs
- env["_LIBDEPS_LD_PATH"] = get_libdeps_ld_path
- env["_SYSLIBDEPS"] = make_get_syslibdeps_callable(emitting_shared)
+ env["_LIBDEPS_GET_LIBS"] = partial(get_libdeps, debug=debug)
+ env["_LIBDEPS_OBJS"] = partial(get_libdeps_objs, debug=debug)
+ env["_LIBDEPS_LD_PATH"] = partial(get_libdeps_ld_path)
+ env["_SYSLIBDEPS"] = partial(get_syslibdeps, debug=debug, shared=emitting_shared)
env[Constants.Libdeps] = SCons.Util.CLVar()
env[Constants.SysLibdeps] = SCons.Util.CLVar()
@@ -1222,31 +1329,31 @@ def setup_environment(env, emitting_shared=False, linting='on', sanitize_typeinf
new_emitter = SCons.Builder.ListEmitter([base_emitter, libdeps_graph_emitter])
builder.emitter = new_emitter
- # We need a way for environments to alter just which libdeps
- # emitter they want, without altering the overall program or
- # library emitter which may have important effects. The
- # substitution rules for emitters are a little strange, so build
- # ourselves a little trampoline to use below so we don't have to
- # deal with it.
- def make_indirect_emitter(variable):
- def indirect_emitter(target, source, env):
- return env[variable](target, source, env)
-
- return indirect_emitter
env.Append(
- LIBDEPS_LIBEMITTER=make_libdeps_emitter("StaticLibrary"),
- LIBEMITTER=make_indirect_emitter("LIBDEPS_LIBEMITTER"),
- LIBDEPS_SHAREMITTER=make_libdeps_emitter("SharedArchive", ignore_progdeps=True),
- SHAREMITTER=make_indirect_emitter("LIBDEPS_SHAREMITTER"),
- LIBDEPS_SHLIBEMITTER=make_libdeps_emitter(
- "SharedLibrary", dependency_visibility_typeinfo if sanitize_typeinfo else dependency_visibility_honored
+ LIBDEPS_LIBEMITTER=partial(
+ libdeps_emitter,
+ debug=debug,
+ builder="StaticLibrary"),
+ LIBEMITTER=lambda target, source, env: env["LIBDEPS_LIBEMITTER"](target, source, env),
+ LIBDEPS_SHAREMITTER=partial(
+ libdeps_emitter,
+ debug=debug,
+ builder="SharedArchive", ignore_progdeps=True),
+ SHAREMITTER=lambda target, source, env: env["LIBDEPS_SHAREMITTER"](target, source, env),
+ LIBDEPS_SHLIBEMITTER=partial(
+ libdeps_emitter,
+ debug=debug,
+ builder="SharedLibrary",
+ visibility_map=dependency_visibility_typeinfo if sanitize_typeinfo else dependency_visibility_honored
),
- SHLIBEMITTER=make_indirect_emitter("LIBDEPS_SHLIBEMITTER"),
- LIBDEPS_PROGEMITTER=make_libdeps_emitter(
- "SharedLibrary" if emitting_shared else "StaticLibrary"
+ SHLIBEMITTER=lambda target, source, env: env["LIBDEPS_SHLIBEMITTER"](target, source, env),
+ LIBDEPS_PROGEMITTER=partial(
+ libdeps_emitter,
+ debug=debug,
+ builder="SharedLibrary" if emitting_shared else "StaticLibrary"
),
- PROGEMITTER=make_indirect_emitter("LIBDEPS_PROGEMITTER"),
+ PROGEMITTER=lambda target, source, env: env["LIBDEPS_PROGEMITTER"](target, source, env),
)
env["_LIBDEPS_LIBS_WITH_TAGS"] = expand_libdeps_with_flags
@@ -1261,7 +1368,7 @@ def setup_environment(env, emitting_shared=False, linting='on', sanitize_typeinf
env.Prepend(ARFLAGS="$_LIBDEPS_TAGS")
for builder_name in ("Program", "SharedLibrary", "LoadableModule", "SharedArchive"):
try:
- update_scanner(env["BUILDERS"][builder_name])
+ update_scanner(env, builder_name, debug=debug)
except KeyError:
pass
@@ -1276,7 +1383,7 @@ def setup_conftests(conf):
if result:
context.env[var] = lib
return context.Result(result)
- context.env[var] = __missing_syslib(name)
+ context.env[var] = _missing_syslib(name)
return context.Result(result)
conf.AddTest("FindSysLibDep", FindSysLibDep)