Skip to content

Instantly share code, notes, and snippets.

@ag7
Last active December 20, 2015 04:28
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ag7/8a34e4b028cabba35189 to your computer and use it in GitHub Desktop.
Save ag7/8a34e4b028cabba35189 to your computer and use it in GitHub Desktop.
30-lines include mess hunter
"""Generate a cpp project include graph with dot."""
import sys, os, re, optparse, tempfile, subprocess
if __name__ == '__main__':
# parse arguments
parser = optparse.OptionParser()
parser.add_option("-d", dest="input_dir",
help="input directory", default=".")
parser.add_option("-o", dest="output_file",
help="name of the output file", default="include_graph.png")
(opts, _) = parser.parse_args()
# discover source files in the input directory
fl = []
for (path, _, files) in os.walk(os.path.realpath(opts.input_dir)):
fl += [os.path.join(path, f)
for f in files if re.match(r'.+\.(cpp|h)$', f)]
# generates dot file with include dependencies
(tmpfd, tmppath) = tempfile.mkstemp()
file = open(tmppath, 'w')
file.write('digraph includegraph\n{\nrankdir = LR\nnode '
'[color=black, fillcolor=darkgoldenrod1, style=filled]\n')
for fn in fl:
srcfile = open(fn)
file.write('\n// %s\n' % (os.path.basename(fn)))
for line in iter(srcfile):
m = re.match(r'^\s*\#include\s+("|<)(.+)("|>)', line)
if m:
file.write('"%s" -> "%s"\n'
% (os.path.basename(fn), m.group(2)))
srcfile.close()
file.write('}\n')
DEVNULL = open(os.devnull, 'wb')
# produces a png image with the include graph from the dot file
retcode = subprocess.call(['dot', '-Tpng', tmppath,
'-o', opts.output_file],
stdout=DEVNULL, stderr=DEVNULL)
# free resources
file.close()
os.close(tmpfd)
os.remove(tmppath)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment