summaryrefslogtreecommitdiff
path: root/site_scons/site_tools/dagger
diff options
context:
space:
mode:
Diffstat (limited to 'site_scons/site_tools/dagger')
-rw-r--r--site_scons/site_tools/dagger/__init__.py36
-rw-r--r--site_scons/site_tools/dagger/dagger.py37
-rw-r--r--site_scons/site_tools/dagger/graph.py79
-rw-r--r--site_scons/site_tools/dagger/graph_consts.py1
-rw-r--r--site_scons/site_tools/dagger/graph_test.py147
5 files changed, 190 insertions, 110 deletions
diff --git a/site_scons/site_tools/dagger/__init__.py b/site_scons/site_tools/dagger/__init__.py
index c63bfc6967e..2e82ebeb058 100644
--- a/site_scons/site_tools/dagger/__init__.py
+++ b/site_scons/site_tools/dagger/__init__.py
@@ -7,6 +7,7 @@ import SCons
from . import dagger
+
def generate(env, **kwargs):
"""The entry point for our tool. However, the builder for
the JSON file is not actually run until the Dagger method is called
@@ -14,28 +15,43 @@ def generate(env, **kwargs):
to the native builders for object/libraries.
"""
- env.Replace(LIBEMITTER=SCons.Builder.ListEmitter([env['LIBEMITTER'], dagger.emit_lib_db_entry]))
+ env.Replace(
+ LIBEMITTER=SCons.Builder.ListEmitter(
+ [env["LIBEMITTER"], dagger.emit_lib_db_entry]
+ )
+ )
running_os = os.sys.platform
- if not (running_os.startswith('win') or running_os.startswith('sun')):
+ if not (running_os.startswith("win") or running_os.startswith("sun")):
env.Replace(
- PROGEMITTER=SCons.Builder.ListEmitter([env['PROGEMITTER'], dagger.emit_prog_db_entry]))
+ PROGEMITTER=SCons.Builder.ListEmitter(
+ [env["PROGEMITTER"], dagger.emit_prog_db_entry]
+ )
+ )
static_obj, shared_obj = SCons.Tool.createObjBuilders(env)
- suffixes = ['.c', '.cc', '.cxx', '.cpp']
+ suffixes = [".c", ".cc", ".cxx", ".cpp"]
obj_builders = [static_obj, shared_obj]
- default_emitters = [SCons.Defaults.StaticObjectEmitter, SCons.Defaults.SharedObjectEmitter]
+ default_emitters = [
+ SCons.Defaults.StaticObjectEmitter,
+ SCons.Defaults.SharedObjectEmitter,
+ ]
for suffix in suffixes:
for i in range(len(obj_builders)):
obj_builders[i].add_emitter(
- suffix, SCons.Builder.ListEmitter([dagger.emit_obj_db_entry, default_emitters[i]]))
+ suffix,
+ SCons.Builder.ListEmitter(
+ [dagger.emit_obj_db_entry, default_emitters[i]]
+ ),
+ )
- env['BUILDERS']['__OBJ_DATABASE'] = SCons.Builder.Builder(
- action=SCons.Action.Action(dagger.write_obj_db, None))
+ env["BUILDERS"]["__OBJ_DATABASE"] = SCons.Builder.Builder(
+ action=SCons.Action.Action(dagger.write_obj_db, None)
+ )
def Dagger(env, target="library_dependency_graph.json"):
- if running_os.startswith('win') or running_os.startswith('sun'):
+ if running_os.startswith("win") or running_os.startswith("sun"):
logging.error("Dagger is only supported on OSX and Linux")
return
result = env.__OBJ_DATABASE(target=target, source=[])
@@ -44,7 +60,7 @@ def generate(env, **kwargs):
return result
- env.AddMethod(Dagger, 'Dagger')
+ env.AddMethod(Dagger, "Dagger")
def exists(env):
diff --git a/site_scons/site_tools/dagger/dagger.py b/site_scons/site_tools/dagger/dagger.py
index cc208dd23c2..061401e9bd7 100644
--- a/site_scons/site_tools/dagger/dagger.py
+++ b/site_scons/site_tools/dagger/dagger.py
@@ -44,9 +44,12 @@ from . import graph
from . import graph_consts
-LIB_DB = [] # Stores every SCons library nodes
-OBJ_DB = [] # Stores every SCons object file node
-EXE_DB = {} # Stores every SCons executable node, with the object files that build into it {Executable: [object files]}
+LIB_DB = [] # Stores every SCons library nodes
+OBJ_DB = [] # Stores every SCons object file node
+EXE_DB = (
+ {}
+) # Stores every SCons executable node, with the object files that build into it {Executable: [object files]}
+
def list_process(items):
"""From WIL, converts lists generated from an NM command with unicode strings to lists
@@ -57,12 +60,12 @@ def list_process(items):
for l in items:
if isinstance(l, list):
for i in l:
- if i.startswith('.L'):
+ if i.startswith(".L"):
continue
else:
r.append(str(i))
else:
- if l.startswith('.L'):
+ if l.startswith(".L"):
continue
else:
r.append(str(l))
@@ -75,26 +78,26 @@ def get_symbol_worker(object_file, task):
"""From WIL, launches a worker subprocess which collects either symbols defined
or symbols required by an object file"""
- platform = 'linux' if sys.platform.startswith('linux') else 'darwin'
+ platform = "linux" if sys.platform.startswith("linux") else "darwin"
- if platform == 'linux':
- if task == 'used':
+ if platform == "linux":
+ if task == "used":
cmd = r'nm "' + object_file + r'" | grep -e "U " | c++filt'
- elif task == 'defined':
+ elif task == "defined":
cmd = r'nm "' + object_file + r'" | grep -v -e "U " | c++filt'
- elif platform == 'darwin':
- if task == 'used':
+ elif platform == "darwin":
+ if task == "used":
cmd = "nm -u " + object_file + " | c++filt"
- elif task == 'defined':
+ elif task == "defined":
cmd = "nm -jU " + object_file + " | c++filt"
p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE)
uses = p.communicate()[0].decode()
- if platform == 'linux':
- return list_process([use[19:] for use in uses.split('\n') if use != ''])
- elif platform == 'darwin':
- return list_process([use.strip() for use in uses.split('\n') if use != ''])
+ if platform == "linux":
+ return list_process([use[19:] for use in uses.split("\n") if use != ""])
+ elif platform == "darwin":
+ return list_process([use.strip() for use in uses.split("\n") if use != ""])
def emit_obj_db_entry(target, source, env):
@@ -135,7 +138,7 @@ def __compute_libdeps(node):
env = node.get_env()
deps = set()
- for child in env.Flatten(getattr(node.attributes, 'libdeps_direct', [])):
+ for child in env.Flatten(getattr(node.attributes, "libdeps_direct", [])):
if not child:
continue
deps.add(child)
diff --git a/site_scons/site_tools/dagger/graph.py b/site_scons/site_tools/dagger/graph.py
index d8d1e6938ee..fdbc4dc98ba 100644
--- a/site_scons/site_tools/dagger/graph.py
+++ b/site_scons/site_tools/dagger/graph.py
@@ -6,6 +6,7 @@ import copy
from . import graph_consts
+
class Graph(object):
"""Graph class for storing the build dependency graph. The graph stores the
directed edges as a nested dict of { RelationshipType: {From_Node: Set of
@@ -18,8 +19,8 @@ class Graph(object):
A graph can be initialized with a .json file, graph object, or with no args
"""
if isinstance(input, str):
- if input.endswith('.json'):
- with open(input, 'r') as f:
+ if input.endswith(".json"):
+ with open(input, "r") as f:
data = json.load(f, encoding="ascii")
nodes = {}
should_fail = False
@@ -27,8 +28,9 @@ class Graph(object):
for node in data["nodes"]:
id = str(node["id"])
try:
- nodes[id] = node_factory(id, int(node["node"]["type"]),
- dict_source=node["node"])
+ nodes[id] = node_factory(
+ id, int(node["node"]["type"]), dict_source=node["node"]
+ )
except Exception as e:
logging.warning("Malformed Data: " + id)
should_fail = True
@@ -116,7 +118,9 @@ class Graph(object):
if from_node not in self._edges[relationship]:
self._edges[relationship][from_node] = set()
- if any(item is None for item in (from_node, to_node, from_node_obj, to_node_obj)):
+ if any(
+ item is None for item in (from_node, to_node, from_node_obj, to_node_obj)
+ ):
raise ValueError
self._edges[relationship][from_node].add(to_node)
@@ -150,21 +154,28 @@ class Graph(object):
edges_dict = self._edges[edge_type]
for node in list(edges_dict.keys()):
to_nodes = list(self._edges[edge_type][node])
- to_nodes_dicts = [{"index": node_index[to_node], "id": to_node}
- for to_node in to_nodes]
-
- data["edges"].append({"type": edge_type,
- "from_node": {"id": node,
- "index": node_index[node]},
- "to_node": to_nodes_dicts})
-
- with open(filename, 'w', encoding="ascii") as outfile:
+ to_nodes_dicts = [
+ {"index": node_index[to_node], "id": to_node}
+ for to_node in to_nodes
+ ]
+
+ data["edges"].append(
+ {
+ "type": edge_type,
+ "from_node": {"id": node, "index": node_index[node]},
+ "to_node": to_nodes_dicts,
+ }
+ )
+
+ with open(filename, "w", encoding="ascii") as outfile:
json.dump(data, outfile, indent=4)
def __str__(self):
- return ("<Number of Nodes : {0}, Number of Edges : {1}, "
- "Hash: {2}>").format(len(list(self._nodes.keys())),
- sum(len(x) for x in list(self._edges.values())), hash(self))
+ return ("<Number of Nodes : {0}, Number of Edges : {1}, " "Hash: {2}>").format(
+ len(list(self._nodes.keys())),
+ sum(len(x) for x in list(self._edges.values())),
+ hash(self),
+ )
class NodeInterface(object, metaclass=abc.ABCMeta):
@@ -183,6 +194,7 @@ class NodeInterface(object, metaclass=abc.ABCMeta):
class NodeLib(NodeInterface):
"""NodeLib class which represents a library within the graph
"""
+
def __init__(self, id, name, input=None):
if isinstance(input, dict):
should_fail = False
@@ -283,10 +295,13 @@ class NodeLib(NodeInterface):
def __eq__(self, other):
if isinstance(other, NodeLib):
- return (self._id == other._id and self._defined_symbols == other._defined_symbols
- and self._defined_files == other._defined_files
- and self._dependent_libs == other._dependent_libs
- and self._dependent_files == other._dependent_files)
+ return (
+ self._id == other._id
+ and self._defined_symbols == other._defined_symbols
+ and self._defined_files == other._defined_files
+ and self._dependent_libs == other._dependent_libs
+ and self._dependent_files == other._dependent_files
+ )
else:
return False
@@ -409,10 +424,13 @@ class NodeSymbol(NodeInterface):
def __eq__(self, other):
if isinstance(other, NodeSymbol):
- return (self.id == other.id and self._libs == other._libs
- and self._files == other._files
- and self._dependent_libs == other._dependent_libs
- and self._dependent_files == other._dependent_files)
+ return (
+ self.id == other.id
+ and self._libs == other._libs
+ and self._files == other._files
+ and self._dependent_libs == other._dependent_libs
+ and self._dependent_files == other._dependent_files
+ )
else:
return False
@@ -527,10 +545,13 @@ class NodeFile(NodeInterface):
def __eq__(self, other):
if isinstance(other, NodeSymbol):
- return (self.id == other.id and self._lib == other._lib
- and self._dependent_libs == other._dependent_libs
- and self._dependent_files == other._dependent_files
- and self._defined_symbols == other._defined_symbols)
+ return (
+ self.id == other.id
+ and self._lib == other._lib
+ and self._dependent_libs == other._dependent_libs
+ and self._dependent_files == other._dependent_files
+ and self._defined_symbols == other._defined_symbols
+ )
else:
return False
diff --git a/site_scons/site_tools/dagger/graph_consts.py b/site_scons/site_tools/dagger/graph_consts.py
index eae5db9b6c6..a2077675463 100644
--- a/site_scons/site_tools/dagger/graph_consts.py
+++ b/site_scons/site_tools/dagger/graph_consts.py
@@ -22,4 +22,3 @@ NODE_TYPES = list(range(1, 5))
"""Error/query codes"""
NODE_NOT_FOUND = 1
-
diff --git a/site_scons/site_tools/dagger/graph_test.py b/site_scons/site_tools/dagger/graph_test.py
index 39bdf77ab7c..e532386f852 100644
--- a/site_scons/site_tools/dagger/graph_test.py
+++ b/site_scons/site_tools/dagger/graph_test.py
@@ -73,22 +73,33 @@ class CustomAssertions:
raise AssertionError("Nodes not of same type")
if node1.type == graph_consts.NODE_LIB:
- if (node1._defined_symbols != node2._defined_symbols
- or node1._defined_files != node2._defined_files
- or node1._dependent_libs != node2._dependent_libs
- or node1._dependent_files != node2._dependent_files or node1._id != node2._id):
+ if (
+ node1._defined_symbols != node2._defined_symbols
+ or node1._defined_files != node2._defined_files
+ or node1._dependent_libs != node2._dependent_libs
+ or node1._dependent_files != node2._dependent_files
+ or node1._id != node2._id
+ ):
raise AssertionError("Nodes not equal")
elif node1.type == graph_consts.NODE_SYM:
- if (node1._libs != node2._libs or node1._files != node2._files
- or node1._dependent_libs != node2._dependent_libs
- or node1._dependent_files != node2._dependent_files or node1.id != node2.id):
+ if (
+ node1._libs != node2._libs
+ or node1._files != node2._files
+ or node1._dependent_libs != node2._dependent_libs
+ or node1._dependent_files != node2._dependent_files
+ or node1.id != node2.id
+ ):
raise AssertionError("Nodes not equal")
else:
- if (node1._lib != node2._lib or node1._dependent_libs != node2._dependent_libs
- or node1._dependent_files != node2._dependent_files or node1.id != node2.id
- or node1._defined_symbols != node2._defined_symbols):
+ if (
+ node1._lib != node2._lib
+ or node1._dependent_libs != node2._dependent_libs
+ or node1._dependent_files != node2._dependent_files
+ or node1.id != node2.id
+ or node1._defined_symbols != node2._defined_symbols
+ ):
raise AssertionError("Nodes not equal")
@@ -131,51 +142,80 @@ class TestGraphMethods(unittest.TestCase, CustomAssertions):
self.assertRaises(TypeError, self.g.add_node, "not a node")
def test_add_edge_exceptions(self):
- self.assertRaises(TypeError, self.g.add_edge, "NOT A RELATIONSHIP",
- self.from_node_lib.id, self.to_node_lib.id)
-
- self.assertRaises(ValueError, self.g.add_edge,
- graph_consts.LIB_LIB, "not a node", "not a node")
+ self.assertRaises(
+ TypeError,
+ self.g.add_edge,
+ "NOT A RELATIONSHIP",
+ self.from_node_lib.id,
+ self.to_node_lib.id,
+ )
+
+ self.assertRaises(
+ ValueError,
+ self.g.add_edge,
+ graph_consts.LIB_LIB,
+ "not a node",
+ "not a node",
+ )
def test_add_edge_libs(self):
- self.g.add_edge(graph_consts.LIB_LIB, self.from_node_lib.id,
- self.to_node_lib.id)
- self.g.add_edge(graph_consts.LIB_LIB, self.from_node_lib.id,
- self.to_node_lib.id)
- self.g.add_edge(graph_consts.LIB_SYM, self.from_node_lib.id,
- self.to_node_sym.id)
- self.g.add_edge(graph_consts.LIB_FIL, self.from_node_lib.id,
- self.to_node_file.id)
-
- self.assertEqual(self.g.edges[graph_consts.LIB_LIB][
- self.from_node_lib.id], set([self.to_node_lib.id]))
-
- self.assertEqual(self.g.edges[graph_consts.LIB_SYM][
- self.from_node_lib.id], set([self.to_node_sym.id]))
-
- self.assertEqual(self.g.edges[graph_consts.LIB_FIL][
- self.from_node_lib.id], set([self.to_node_file.id]))
-
- self.assertEqual(self.to_node_lib.dependent_libs,
- set([self.from_node_lib.id]))
+ self.g.add_edge(
+ graph_consts.LIB_LIB, self.from_node_lib.id, self.to_node_lib.id
+ )
+ self.g.add_edge(
+ graph_consts.LIB_LIB, self.from_node_lib.id, self.to_node_lib.id
+ )
+ self.g.add_edge(
+ graph_consts.LIB_SYM, self.from_node_lib.id, self.to_node_sym.id
+ )
+ self.g.add_edge(
+ graph_consts.LIB_FIL, self.from_node_lib.id, self.to_node_file.id
+ )
+
+ self.assertEqual(
+ self.g.edges[graph_consts.LIB_LIB][self.from_node_lib.id],
+ set([self.to_node_lib.id]),
+ )
+
+ self.assertEqual(
+ self.g.edges[graph_consts.LIB_SYM][self.from_node_lib.id],
+ set([self.to_node_sym.id]),
+ )
+
+ self.assertEqual(
+ self.g.edges[graph_consts.LIB_FIL][self.from_node_lib.id],
+ set([self.to_node_file.id]),
+ )
+
+ self.assertEqual(self.to_node_lib.dependent_libs, set([self.from_node_lib.id]))
def test_add_edge_files(self):
- self.g.add_edge(graph_consts.FIL_FIL, self.from_node_file.id,
- self.to_node_file.id)
- self.g.add_edge(graph_consts.FIL_SYM, self.from_node_file.id,
- self.to_node_sym.id)
- self.g.add_edge(graph_consts.FIL_LIB, self.from_node_file.id,
- self.to_node_lib.id)
-
- self.assertEqual(self.g.edges[graph_consts.FIL_FIL][
- self.from_node_file.id], set([self.to_node_file.id]))
- self.assertEqual(self.g.edges[graph_consts.FIL_SYM][
- self.from_node_file.id], set([self.to_node_sym.id]))
- self.assertEqual(self.g.edges[graph_consts.FIL_LIB][
- self.from_node_file.id], set([self.to_node_lib.id]))
-
- self.assertEqual(self.to_node_file.dependent_files,
- set([self.from_node_file.id]))
+ self.g.add_edge(
+ graph_consts.FIL_FIL, self.from_node_file.id, self.to_node_file.id
+ )
+ self.g.add_edge(
+ graph_consts.FIL_SYM, self.from_node_file.id, self.to_node_sym.id
+ )
+ self.g.add_edge(
+ graph_consts.FIL_LIB, self.from_node_file.id, self.to_node_lib.id
+ )
+
+ self.assertEqual(
+ self.g.edges[graph_consts.FIL_FIL][self.from_node_file.id],
+ set([self.to_node_file.id]),
+ )
+ self.assertEqual(
+ self.g.edges[graph_consts.FIL_SYM][self.from_node_file.id],
+ set([self.to_node_sym.id]),
+ )
+ self.assertEqual(
+ self.g.edges[graph_consts.FIL_LIB][self.from_node_file.id],
+ set([self.to_node_lib.id]),
+ )
+
+ self.assertEqual(
+ self.to_node_file.dependent_files, set([self.from_node_file.id])
+ )
def test_export_to_json(self):
generated_graph = generate_graph()
@@ -197,10 +237,11 @@ class TestGraphMethods(unittest.TestCase, CustomAssertions):
# the need for a custom assertion
self.assertNodeEquals(
- graph_fromJSON.get_node(id), correct_graph.get_node(id))
+ graph_fromJSON.get_node(id), correct_graph.get_node(id)
+ )
self.assertEqual(graph_fromJSON.edges, correct_graph.edges)
-if __name__ == '__main__':
+if __name__ == "__main__":
unittest.main()