makefile2graph

Creates a graph of dependencies from GNU-Make; Output is a graphiz-dot file or a Gexf-XML file.

619
63
C

makefile2graph

Creates a graph of dependencies from GNU-Make

Output can be generated for the following formats:

Notice that sub-makefiles are not supported.

https://travis-ci.org/lindenb/makefile2graph.svg

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

screenshot.png

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 §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="&lt;ROOT&gt;"/>
      <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

workflow

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

workflow

Misc

try the gexf+ #gephi output or another grafviz algo like neato

See also

  • J4Make java equivalent of makefile2graph