Tools to interrogate and detangle dependency graphs
- depconv - convert dependency graphs between formats
- depfilter - filter or select subsets of dependency graphs
- deptransform - transform dependency graphs
- depquery - query properties of dependency graphs
- depcluster - cluster dependency graphs using community detection
- graphdiff - compare two dependency graphs
- minpath - shorten file paths to minimal unique suffixes
- bbclasses - generate BitBake recipe inheritance diagrams
Rather than build an infinitely flexible, does-everything-and-more graph toolkit, these are targeted tools to solve specific dependency graph problems I frequently encounter.
All tools operate on stdin/stdout in addition to files, and are designed to be chained together with pipes. Any ancillary output is emitted on stderr.
Use the install script to install the tools from this project.
./install --prefix ~/.local
./install --uninstall --prefix ~/.localSee developer-guide.md for more details.
Convert dependency graphs between formats. Input and output formats are auto-detected from file
extensions or by probing the file content when --input-format/--output-format are not specified.
Defaults to DOT output when no output format can be inferred.
$ echo -e "a Node A\nb Node B\n#\na b depends on" | depconv --output-format dot
digraph {
a [label="Node A"];
b [label="Node B"];
a -> b [label="depends on"];
}
$ cargo tree --depth 1 | depconv --output-format tgf
deptangle v0.1.0
clap v4.6.6
...
#
deptangle v0.1.0 clap v4.6.6
...| Format | --input-format |
--output-format |
Description |
|---|---|---|---|
| DOT (GraphViz) | yes | yes | digraph / graph syntax. Parses cmake, ninja, bitbake, and ad-hoc DOT output |
| Mermaid | yes | yes | flowchart / graph graph types |
| TGF | yes | yes | Trivial Graph Format |
| Depfile | yes | yes | Makefile .d depfile |
| Tree | yes | yes | tree CLI output, both ascii and unicode output formats |
| Pathlist | yes | yes | One path per line; hierarchy inferred from / separators |
| Cargo tree | yes | no | cargo tree output |
| Cargo metadata | yes | no | cargo metadata --format-version=1 JSON |
Not every format can represent the same information. The table below shows what each format preserves when parsing (P) and emitting (E):
| Format | Labels | Node type | Attrs | Edge labels | Subgraphs |
|---|---|---|---|---|---|
| DOT | P+E | P+E | P+E | P+E | P+E |
| Mermaid | P+E | partial | partial | P+E | P+E |
| TGF | P+E | -- | -- | P+E | -- |
| Depfile | -- | -- | -- | -- | -- |
| Tree | P+E | -- | -- | -- | -- |
| Pathlist | P+E | -- | -- | -- | -- |
| Cargo tree | P | P | P | -- | -- |
| Cargo metadata | P | P | P | -- | -- |
Converting from a rich format (DOT, cargo metadata) to a simpler one (TGF, depfile) silently drops unsupported attributes. Converting in the other direction preserves graph topology but cannot recover lost metadata.
Filter or select subsets of dependency graphs. Works on the same graph formats as depconv, and is
designed to be chained with pipes.
depfilter selectkeeps nodes matching--includepatterns and/or removes--excludepatternsdepfilter betweenselect nodes connecting multiple sets of query nodesdepfilter cyclesselect any cycles in the graphdepfilter slicecut edges between subgraphs, isolating each subgraph
Each subcommand has extra options to tune its behavior.
# From a cargo dependency tree, select the subtree rooted at "clap", excluding all the proc-macro crates:
$ cargo tree --depth 10 \
| depfilter select -g "clap*" --deps -x "*derive*" -x "*proc*" -I cargo-tree -O dot
digraph {
clap [label="v4.6.6 clap"];
clap_builder [label="v4.6.6 clap_builder"];
anstream [label="v0.6.21 anstream"];
...
}Structural transformations on dependency graphs. Works on the same formats as depconv, and is
designed to be chained with pipes.
The deptransform tool supports the following subcommands:
deptransform reverse- reverse the direction of all edges in the graphdeptransform simplify- remove redundant edges (e.g. if A->B and B->C, then A->C is redundant)deptransform shorten- shorten node IDs that look like paths (minpath, but for node IDs)deptransform sub-sed, but for node IDs and node / edge attributesdeptransform merge- merge multiple graphs into onedeptransform flatten- recursively flatten subgraphs into the parent graph
# Collapse bitbake task-level nodes IDs (acl-native.do_* -> acl-native), then remove the
# now-misleading node labels
$ cat data/depconv/bitbake.curl.task-depends.dot |
deptransform sub --key=id 's/\.do_.*//' |
deptransform sub --key=node:label 's/.*//'Query properties of dependency graphs.
# Show the 5 crates with the most dependencies:
$ cargo metadata --format-version=1 |
depquery nodes --sort out-degree --limit 5
deptangle-io 12
deptangle-cli 11
deptangle-ops 11
graphrs 11
tracing-subscriber 10The depquery tool supports outputting nodes, edges, and metrics. The output is intended to
be machine-readable, and is tab-separated.
Run community detection on a dependency graph to identify clusters of related nodes. Each cluster becomes a subgraph in the output, with cross-cluster edges at the top level. Supports Louvain (default), Leiden, and Label Propagation algorithms.
$ echo -e "a\nb\nc\nd\ne\nf\n#\na b\na c\nb c\nd e\nd f\ne f" |
depcluster -I tgf -O mermaidflowchart LR
subgraph cluster_0
a["a"]
b["b"]
c["c"]
a --> b
a --> c
b --> c
end
subgraph cluster_1
d["d"]
e["e"]
f["f"]
d --> e
d --> f
e --> f
end
Compare two dependency graphs and report what changed. Nodes are matched by ID, and edges by their endpoints.
graphdiff supports several subcommands:
graphdiff annotate- output the combined graph with changes highlighted (added, removed, changed nodes/edges get distinct attributes)graphdiff list- tab-delimited list of changes (+added,-removed,~changed,>moved)graphdiff summary- tab-delimited counts of each change typegraphdiff subtract- set difference: nodes and edges only in the first graph
$ cat before.tgf
a Alpha
b Bravo
#
a b
$ cat after.tgf
b Bravo
c Charlie
#
b c
$ graphdiff annotate before.tgf after.tgf -O mermaidflowchart LR
b["Bravo"]
c["+ Charlie"]
a["- Alpha"]
b --> c
a --> b
Shorten file paths to the minimal unique suffix. Useful for displaying lists of files in a compact way while keeping them distinguishable.
$ minpath <<EOF
/home/user/project/src/main.rs
/home/user/project/src/lib.rs
/home/user/project/tests/main.rs
EOF
src/main.rs
lib.rs
tests/main.rsMultiple options are available to customize and tune the output. See minpath --help for details.
The bbclasses script can parse BitBake recipes to generate an inheritance diagram. It tries to evaluate variable expansion, and needs to run in your BitBake environment to work properly.
bbclasses --group-by-layer curl >curl.dotflowchart LR
subgraph meta[meta]
poky/meta/classes-global/debian.bbclass{{"poky/meta/classes-global/debian.bbclass"}}
poky/meta/classes-global/package.bbclass{{"poky/meta/classes-global/package.bbclass"}}
poky/meta/classes-recipe/autotools.bbclass{{"poky/meta/classes-recipe/autotools.bbclass"}}
poky/meta/classes-recipe/ptest.bbclass{{"poky/meta/classes-recipe/ptest.bbclass"}}
poky/meta/conf/distro/include/ptest-packagelists.inc[["poky/meta/conf/distro/include/ptest-packagelists.inc"]]
poky/meta/recipes-support/curl/curl_8.7.1.bb["poky/meta/recipes-support/curl/curl_8.7.1.bb"]
end
subgraph meta-oem[meta-oem]
meta-oem/classes/dynamic-packagearch.bbclass{{"meta-oem/classes/dynamic-packagearch.bbclass"}}
end
meta-work/recipes-support/curl/curl__.bbappend(["meta-work/recipes-support/curl/curl_%.bbappend"])
meta-oem/classes/dynamic-packagearch.bbclass -->|"INHERIT"| poky/meta/recipes-support/curl/curl_8.7.1.bb
poky/meta/classes-global/debian.bbclass -->|"INHERIT"| poky/meta/recipes-support/curl/curl_8.7.1.bb
poky/meta/classes-global/package.bbclass -->|"inherit"| poky/meta/classes-global/debian.bbclass
poky/meta/classes-recipe/autotools.bbclass -->|"inherit"| poky/meta/recipes-support/curl/curl_8.7.1.bb
poky/meta/classes-recipe/ptest.bbclass -->|"inherit"| poky/meta/recipes-support/curl/curl_8.7.1.bb
poky/meta/conf/distro/include/ptest-packagelists.inc -->|"require"| poky/meta/classes-recipe/ptest.bbclass
poky/meta/recipes-support/curl/curl_8.7.1.bb -->|"appends"| meta-work/recipes-support/curl/curl__.bbappend