mirror of
https://gitlab.com/buildroot.org/buildroot.git
synced 2026-08-08 00:20:38 -09:00
support/scripts/graph-depends allow for forward and reverse depends on same graph
The current implementation of buildroot depe dependency graphing
either does forward- or reverse-dependency traversal.
This patch enables buildroot to graph forward and reverse dependencies
on the graph for the same package: (Diagram Credit: Yann E. MORIN)
$ make pkg-d-graph-both-depends
pkg A -. .-> pkg E
\ /
pkg B ----> pkg D ----> pkg F
/ \
pkg C -' '-> pkg G
In the above example a single graph shows pkg {A,B,C} are needed
by pkg D, and pkg D is a dependency of pkg {E,F,G}.
Makefile help and manual are also updated.
Signed-off-by: Steve Hay <me@stevenhay.com>
[Arnout:
- remove DEPTH and RDEPTH, their functionality is already covered by
BR2_GRAPH_DEPS_OPTS;
- remove --rdepth, it was felt to not add sufficient added value;
- add the new target to the manual;
- fix flake8 errors.
]
Signed-off-by: Arnout Vandecappelle <arnout@mind.be>
This commit is contained in:
committed by
Arnout Vandecappelle
parent
0c2e6050cc
commit
ca6c896bdd
3
Makefile
3
Makefile
@@ -1171,6 +1171,9 @@ help:
|
||||
@echo ' - Recursively list packages which have <pkg> as a dependency'
|
||||
@echo ' <pkg>-graph-depends - Generate a graph of <pkg>'\''s dependencies'
|
||||
@echo ' <pkg>-graph-rdepends - Generate a graph of <pkg>'\''s reverse dependencies'
|
||||
@echo ' <pkg>-graph-both-depends'
|
||||
@echo ' - Generate a graph of both <pkg>'\''s forward and'
|
||||
@echo ' reverse dependencies.
|
||||
@echo ' <pkg>-dirclean - Remove <pkg> build directory'
|
||||
@echo ' <pkg>-reconfigure - Restart the build from the configure step'
|
||||
@echo ' <pkg>-rebuild - Restart the build from the build step'
|
||||
|
||||
@@ -81,6 +81,10 @@ graphs.
|
||||
dependencies (i.e the packages that depend on it, directly or
|
||||
indirectly)
|
||||
|
||||
| +graph-both-depends+ | Generate a graph of this package in both
|
||||
directions (i.e the packages that depend on it and on which it
|
||||
depends, directly or indirectly)
|
||||
|
||||
| +dirclean+ | Remove the whole package build directory
|
||||
|
||||
| +reinstall+ | Re-run the install commands
|
||||
|
||||
@@ -1042,6 +1042,9 @@ $(1)-graph-depends: graph-depends-requirements
|
||||
$(1)-graph-rdepends: graph-depends-requirements
|
||||
$(call pkg-graph-depends,$(1),--reverse)
|
||||
|
||||
$(1)-graph-both-depends: graph-depends-requirements
|
||||
$(call pkg-graph-depends,$(1),--direct --reverse)
|
||||
|
||||
$(1)-all-source: $(1)-source
|
||||
$(1)-all-source: $$(foreach p,$$($(2)_FINAL_ALL_DEPENDENCIES),$$(p)-all-source)
|
||||
|
||||
|
||||
@@ -159,11 +159,11 @@ def check_circular_deps(deps):
|
||||
|
||||
# This functions trims down the dependency list of all packages.
|
||||
# It applies in sequence all the dependency-elimination methods.
|
||||
def remove_extra_deps(deps, rootpkg, transitive, arrow_dir):
|
||||
def remove_extra_deps(deps, rootpkg, transitive, direct):
|
||||
# For the direct dependencies, find and eliminate mandatory
|
||||
# deps, and add them to the root package. Don't do it for a
|
||||
# reverse graph, because mandatory deps are only direct deps.
|
||||
if arrow_dir == "forward":
|
||||
if direct:
|
||||
for pkg in list(deps.keys()):
|
||||
if not pkg == rootpkg:
|
||||
for d in get_mandatory_deps(pkg, deps):
|
||||
@@ -199,12 +199,13 @@ def print_attrs(outfile, pkg, pkg_type, pkg_version, depth, colors):
|
||||
|
||||
# Print the dependency graph of a package
|
||||
def print_pkg_deps(outfile, dict_deps, dict_types, dict_versions, stop_list, exclude_list,
|
||||
arrow_dir, draw_graph, depth, max_depth, pkg, colors, done_deps=None):
|
||||
direct, draw_graph, depth, max_depth, pkg, colors, done_deps=None):
|
||||
if done_deps is None:
|
||||
done_deps = []
|
||||
if pkg in done_deps:
|
||||
return
|
||||
done_deps.append(pkg)
|
||||
|
||||
if draw_graph:
|
||||
print_attrs(outfile, pkg, dict_types[pkg], dict_versions[pkg], depth, colors)
|
||||
elif depth != 0:
|
||||
@@ -231,9 +232,12 @@ def print_pkg_deps(outfile, dict_deps, dict_types, dict_versions, stop_list, exc
|
||||
break
|
||||
if add:
|
||||
if draw_graph:
|
||||
outfile.write("%s -> %s [dir=%s]\n" % (pkg_node_name(pkg), pkg_node_name(d), arrow_dir))
|
||||
if direct:
|
||||
outfile.write("%s -> %s [dir=%s]\n" % (pkg_node_name(pkg), pkg_node_name(d), "forward"))
|
||||
else:
|
||||
outfile.write("%s -> %s [dir=%s]\n" % (pkg_node_name(d), pkg_node_name(pkg), "forward"))
|
||||
print_pkg_deps(outfile, dict_deps, dict_types, dict_versions, stop_list, exclude_list,
|
||||
arrow_dir, draw_graph, depth + 1, max_depth, d, colors, done_deps)
|
||||
direct, draw_graph, depth + 1, max_depth, d, colors, done_deps)
|
||||
|
||||
|
||||
def parse_args():
|
||||
@@ -265,9 +269,9 @@ def parse_args():
|
||||
default=False)
|
||||
parser.add_argument("--no-transitive", dest="transitive", action='store_false',
|
||||
help="Draw (do not draw) transitive dependencies")
|
||||
parser.add_argument("--direct", dest="direct", action='store_true', default=True,
|
||||
parser.add_argument("--direct", dest="direct", action='store_true', default=False,
|
||||
help="Draw direct dependencies (the default)")
|
||||
parser.add_argument("--reverse", dest="direct", action='store_false',
|
||||
parser.add_argument("--reverse", dest="reverse", action='store_true', default=False,
|
||||
help="Draw reverse dependencies")
|
||||
parser.add_argument("--quiet", '-q', dest="quiet", action='store_true',
|
||||
help="Quiet")
|
||||
@@ -292,6 +296,9 @@ def main():
|
||||
sys.exit(1)
|
||||
outfile = open(args.outfile, "w")
|
||||
|
||||
if not args.direct and not args.reverse:
|
||||
args.direct = True
|
||||
|
||||
if args.package is None:
|
||||
mode = MODE_FULL
|
||||
rootpkg = 'all'
|
||||
@@ -312,13 +319,9 @@ def main():
|
||||
if args.exclude_mandatory:
|
||||
exclude_list += MANDATORY_DEPS
|
||||
|
||||
if args.direct:
|
||||
arrow_dir = "forward"
|
||||
else:
|
||||
if mode == MODE_FULL:
|
||||
logging.error("--reverse needs a package")
|
||||
sys.exit(1)
|
||||
arrow_dir = "back"
|
||||
if args.reverse and mode == MODE_FULL:
|
||||
logging.error("--reverse needs a package")
|
||||
sys.exit(1)
|
||||
|
||||
draw_graph = not args.flat_list
|
||||
|
||||
@@ -330,23 +333,33 @@ def main():
|
||||
logging.error("Error: incorrect color list '%s'" % args.colors)
|
||||
sys.exit(1)
|
||||
|
||||
deps, rdeps, dict_types, dict_versions = brpkgutil.get_dependency_tree()
|
||||
dict_deps = deps if args.direct else rdeps
|
||||
|
||||
check_circular_deps(dict_deps)
|
||||
if check_only:
|
||||
sys.exit(0)
|
||||
|
||||
dict_deps = remove_extra_deps(dict_deps, rootpkg, args.transitive, arrow_dir)
|
||||
|
||||
# Start printing the graph data
|
||||
if draw_graph:
|
||||
if not check_only and draw_graph:
|
||||
outfile.write("digraph G {\n")
|
||||
|
||||
print_pkg_deps(outfile, dict_deps, dict_types, dict_versions, stop_list, exclude_list,
|
||||
arrow_dir, draw_graph, 0, args.depth, rootpkg, colors)
|
||||
deps, rdeps, dict_types, dict_versions = brpkgutil.get_dependency_tree()
|
||||
|
||||
if draw_graph:
|
||||
# forward
|
||||
if args.direct:
|
||||
dict_deps = deps
|
||||
direct = True
|
||||
check_circular_deps(dict_deps)
|
||||
if not check_only:
|
||||
dict_deps = remove_extra_deps(dict_deps, rootpkg, args.transitive, direct)
|
||||
print_pkg_deps(outfile, dict_deps, dict_types, dict_versions, stop_list, exclude_list,
|
||||
direct, draw_graph, 0, args.depth, rootpkg, colors)
|
||||
|
||||
# reverse
|
||||
if args.reverse:
|
||||
dict_deps = rdeps
|
||||
direct = False
|
||||
check_circular_deps(dict_deps)
|
||||
if not check_only:
|
||||
dict_deps = remove_extra_deps(dict_deps, rootpkg, args.transitive, direct)
|
||||
print_pkg_deps(outfile, dict_deps, dict_types, dict_versions, stop_list, exclude_list,
|
||||
direct, draw_graph, 0, args.depth, rootpkg, colors)
|
||||
|
||||
if not check_only and draw_graph:
|
||||
outfile.write("}\n")
|
||||
else:
|
||||
outfile.write("\n")
|
||||
|
||||
Reference in New Issue
Block a user