Makefile2graph
Creates a graph of dependencies from GNU-Make; Output is a graphiz-dot file or a Gexf-XML file.
Install / Use
/learn @lindenb/Makefile2graphREADME
makefile2graph
Creates a graph of dependencies from GNU-Make
Output can be generated for the following formats:
- Graphviz/dot
- Gexf-XML
- PlantUML
- Mermaid
- or a list of the deepest independent targets that should be make.
Notice that sub-makefiles are not supported.
History
- 2023-08-30 added format PlantUML
- 2023-08-30 added format Mermaid
- 2023-08-14 added options for setting graph, node, edge, and dirty attributes
- 2014-12-31 added option
--format, removed otpions 'x' and 'd' - 2014-12-22 added 'deep' output. I need this when I'm working on a cluster and I need to know the deepest independent targets that should be make.
- 2014-10-07 print version
- 2014-10-06 added --root option
- 2014-09-17 added long_opt , options basename and suffix
- 2014-09-16 fixed new format for GNU make v4.0
Screenshot

Compilation
make
Options
- -h|--help help (this screen)
- -f|--format (format)
- (d)ot graphiz dot output (default) (x)ml output
- (g)exf XML output (M)ermaid output (P)lantUML output
- (E) print the deepest indepedent targets.
- (L)ist all targets.
- -b|--basename only print file basename
- -s|--suffix only print file extension
- -r|--root show root node
- -c|--colorscheme (scheme) Set colorscheme applied interleaved to all nodes.
- -g|--graph-attributes: Sets attributes applied to the graph.
- -n|--node-attributes: Sets attributes applied to all nodes.
- -e|--edge-attributes: Sets attributes applied to all edges.
- -e|--dirty-attributes: Sets attributes applied to dirty nodes only.
- -v|--version print version
Usage
make -Bnd | make2graph > output.dot
make -Bnd | make2graph | dot -Tpng -o out.png
make -Bnd | make2graph --format x > output.xml
make -Bnd | make2graph --format p -g "skinparam BackgroundColor LightYellow" -n "BackgroundColor Peru" -e "skinparam ArrowColor Blue" -d "BackgroundColor Salmon" > output.puml
Locale
make2graph only parses english messages from GNU make. If you're using another locale, you should set LC_ALL=C.
Examples
Tabix 0.2.5 - DOT
$ cd tabix-0.2.5
$ make -Bnd |make2graph
digraph G {
n1[label="<ROOT>", color="green"];
n2[label="Makefile", color="green"];
n4[label="all", color="red"];
n3[label="all-recur", color="red"];
n23[label="bedidx.c", color="green"];
n22[label="bedidx.o", color="red"];
n9[label="bgzf.c", color="green"];
n10[label="bgzf.h", color="green"];
n8[label="bgzf.o", color="red"];
n27[label="bgzip", color="red"];
n29[label="bgzip.c", color="green"];
n28[label="bgzip.o", color="red"];
n18[label="index.c", color="green"];
n17[label="index.o", color="red"];
n20[label="khash.h", color="green"];
n16[label="knetfile.c", color="green"];
n11[label="knetfile.h", color="green"];
n15[label="knetfile.o", color="red"];
n24[label="kseq.h", color="green"];
n21[label="ksort.h", color="green"];
n13[label="kstring.c", color="green"];
n14[label="kstring.h", color="green"];
n12[label="kstring.o", color="red"];
n6[label="lib", color="red"];
n7[label="libtabix.a", color="red"];
n26[label="main.c", color="green"];
n25[label="main.o", color="red"];
n5[label="tabix", color="red"];
n19[label="tabix.h", color="green"];
n2 -> n1 ;
n4 -> n1 ;
n3 -> n1 ;
n27 -> n4 ;
n5 -> n4 ;
n23 -> n22 ;
n20 -> n22 ;
n24 -> n22 ;
n9 -> n8 ;
n10 -> n8 ;
n11 -> n8 ;
n8 -> n27 ;
n28 -> n27 ;
n15 -> n27 ;
n10 -> n28 ;
n29 -> n28 ;
n10 -> n17 ;
n18 -> n17 ;
n20 -> n17 ;
n21 -> n17 ;
n14 -> n17 ;
n19 -> n17 ;
n16 -> n15 ;
n11 -> n15 ;
n13 -> n12 ;
n14 -> n12 ;
n7 -> n6 ;
n22 -> n7 ;
n8 -> n7 ;
n17 -> n7 ;
n15 -> n7 ;
n12 -> n7 ;
n10 -> n25 ;
n14 -> n25 ;
n26 -> n25 ;
n19 -> n25 ;
n6 -> n5 ;
n25 -> n5 ;
}
Tabix 0.2.5 - XML
$ cd tabix-0.2.5
$ make -Bnd | make2graph --format x
<?xml version="1.0" encoding="UTF-8"?>
<gexf xmlns="http://www.gexf.net/1.2draft" version="1.2">
<meta>
<creator>Pierre Lindenbaum</creator>
<description>Makefile Graph</description>
</meta>
<graph mode="static" defaultedgetype="directed">
<attributes class="node" mode="static"/>
<nodes>
<node id="n1" label="<ROOT>"/>
<node id="n2" label="Makefile"/>
<node id="n4" label="all"/>
<node id="n3" label="all-recur"/>
<node id="n23" label="bedidx.c"/>
<node id="n22" label="bedidx.o"/>
<node id="n9" label="bgzf.c"/>
<node id="n10" label="bgzf.h"/>
<node id="n8" label="bgzf.o"/>
<node id="n27" label="bgzip"/>
<node id="n29" label="bgzip.c"/>
<node id="n28" label="bgzip.o"/>
<node id="n18" label="index.c"/>
<node id="n17" label="index.o"/>
<node id="n20" label="khash.h"/>
<node id="n16" label="knetfile.c"/>
<node id="n11" label="knetfile.h"/>
<node id="n15" label="knetfile.o"/>
<node id="n24" label="kseq.h"/>
<node id="n21" label="ksort.h"/>
<node id="n13" label="kstring.c"/>
<node id="n14" label="kstring.h"/>
<node id="n12" label="kstring.o"/>
<node id="n6" label="lib"/>
<node id="n7" label="libtabix.a"/>
<node id="n26" label="main.c"/>
<node id="n25" label="main.o"/>
<node id="n5" label="tabix"/>
<node id="n19" label="tabix.h"/>
</nodes>
<edges>
<edge id="E1" type="directed" source="n2" target="n1"/>
<edge id="E2" type="directed" source="n4" target="n1"/>
<edge id="E3" type="directed" source="n3" target="n1"/>
<edge id="E4" type="directed" source="n27" target="n4"/>
<edge id="E5" type="directed" source="n5" target="n4"/>
<edge id="E6" type="directed" source="n23" target="n22"/>
<edge id="E7" type="directed" source="n20" target="n22"/>
<edge id="E8" type="directed" source="n24" target="n22"/>
<edge id="E9" type="directed" source="n9" target="n8"/>
<edge id="E10" type="directed" source="n10" target="n8"/>
<edge id="E11" type="directed" source="n11" target="n8"/>
<edge id="E12" type="directed" source="n8" target="n27"/>
<edge id="E13" type="directed" source="n28" target="n27"/>
<edge id="E14" type="directed" source="n15" target="n27"/>
<edge id="E15" type="directed" source="n10" target="n28"/>
<edge id="E16" type="directed" source="n29" target="n28"/>
<edge id="E17" type="directed" source="n10" target="n17"/>
<edge id="E18" type="directed" source="n18" target="n17"/>
<edge id="E19" type="directed" source="n20" target="n17"/>
<edge id="E20" type="directed" source="n21" target="n17"/>
<edge id="E21" type="directed" source="n14" target="n17"/>
<edge id="E22" type="directed" source="n19" target="n17"/>
<edge id="E23" type="directed" source="n16" target="n15"/>
<edge id="E24" type="directed" source="n11" target="n15"/>
<edge id="E25" type="directed" source="n13" target="n12"/>
<edge id="E26" type="directed" source="n14" target="n12"/>
<edge id="E27" type="directed" source="n7" target="n6"/>
<edge id="E28" type="directed" source="n22" target="n7"/>
<edge id="E29" type="directed" source="n8" target="n7"/>
<edge id="E30" type="directed" source="n17" target="n7"/>
<edge id="E31" type="directed" source="n15" target="n7"/>
<edge id="E32" type="directed" source="n12" target="n7"/>
<edge id="E33" type="directed" source="n10" target="n25"/>
<edge id="E34" type="directed" source="n14" target="n25"/>
<edge id="E35" type="directed" source="n26" target="n25"/>
<edge id="E36" type="directed" source="n19" target="n25"/>
<edge id="E37" type="directed" source="n6" target="n5"/>
<edge id="E38" type="directed" source="n25" target="n5"/>
</edges>
</graph>
</gexf>
Deep output
deep output was needed when using a cluster: I needed a list of all deepest independant targets that must be re-built.
For the following Makefile
NUMS=1 2 3 4 5
.PHONY:all clean
%.c: %.b
echo "$<" > $@
%.b: %.a
echo "$<" > $@
%.a:
echo "$@" > $@
all:$(addsuffix .c,${NUMS})
clean:
rm -f $(foreach P,a b c,$(addsuffix .${P},${NUMS}))
make a few targets:
$ make 1.a 2.a 3.b 4.c
echo "1.a" > 1.a
echo "2.a" > 2.a
echo "3.a" > 3.a
echo "3.a" > 3.b
echo "4.a" > 4.a
echo "4.a" > 4.b
echo "4.b" > 4.c
rm 3.a 4.a 4.b
deep output :
$ make -nd all | ./make2graph --format e
1.b
2.b
3.c
5.a
build other targets
$ make 1.b 3.c
echo "1.a" > 1.b
echo "3.b" > 3.c
new deep output :
$ make -nd all | ./make2graph --format e
1.c
2.b
5.a
Gallery
https://twitter.com/yokofakun/status/514329843065167872

https://twitter.com/yokofakun/status/278086490809040896

Misc
<blockquote class="twitter-tweet" lang="en"><p><a href="https://twitter.com/yokofakun">@yokofakun</a> Using your <a href="https://t.co/Z1xg8dhW2r">https://t.co/Z1xg8dhW2r</a>, and Graphviz 2.36 for OS X. Large graph. How can I scale it better? <a href="http://t.co/d6ZQX2MnqH">pic.twitter.com/d6ZQX2MnqH</a></p>— Lex Nederbragt (@lexnederbragt) <a href="https://twitter.com/lexnederbragt/status/502165603076288512">August 20, 2014</a></blockquote> <script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script>try the gexf+ #gephi output or another grafviz algo like neato
See also
- J4Make java equivalent of makefile2graph
Related Skills
node-connect
339.3kDiagnose OpenClaw node connection and pairing failures for Android, iOS, and macOS companion apps
frontend-design
83.9kCreate distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, or applications. Generates creative, polished code that avoids generic AI aesthetics.
openai-whisper-api
339.3kTranscribe audio via OpenAI Audio Transcriptions API (Whisper).
commit-push-pr
83.9kCommit, push, and open a PR
