Provided by: makepp_2.0.98.5-2.1_all bug

NAME

       makeppgraph -- Graphical analysis of the dependency graph

DESCRIPTION

       ?: -?,  A: -A,
         --args-file,
         --arguments-file,  B: -b,
         --because,
         --build-reasons,  C: &cwd,  D: -D,
         -d,
         --dependencies,
         &dir,
         --dot,
         --down,
         --downwards,  G: -g,
         --graphviz,  H: -h,
         --help,
         &home,
         --html,  I: -I,
         -i,
         --include,
         --include-dir,
         --includes,  L: -l,
         --log,
         --log-file,  M: -M,
         -m,
         &makepp,
         $MAKEPPGRAPHFLAGS,
         --merge,
         --module,  O: -o,
         --output,  P: -p,
         --plain,  R: -r,
         --rename,  S: -s,
         --separate-directions,
         &suf,  T: -t,
         --text,  U: -u,
         --up,
         --upwards,
         &usr,  V: -V,
         --version

       makeppgraph [ option ... ] [ pattern ... ]

       mppg [ option ... ] [ pattern ... ]

       They say "A picture is worth a thousand words".  So let's draw your dependency or include
       graph from various viewpoints.  Check out the gallery
       <http://makepp.sourceforge.net/gallery/> to get some ideas of what you can do.

       Each node represents a source file or a target, colored according to file name patterns.
       A file's node is rectangular.  A phony target's node is oval.  Each solid edge represents
       a direct dependency.  Alternately or additionally you can display include relationships as
       dotted lines.  For a more detailed but not so pretty textual view see makepplog.

       But beware, even for a small build the complexity can be staggering!  This is because with
       .o files and system includes you easily have twice as many nodes as source files.  But
       that is nothing -- the number of edges often far exceeds that of nodes, due to multiple
       include statements.  A crossing-free layout is usually impossible.

       In real projects the complexity becomes insane.  Techniques like template based source
       file generation, preprocessors (e.g. embedded SQL, interface definition languages, Qt
       library) or publishing of files to central directories (e.g. to have only one "-I" or "-L"
       option) make the graph explode.  Even if edges are just one pixel wide, you end up with
       broad black stripes of criss-crossing edges.

       Once you realize what really goes on, if you're lucky, you may be able to find a way of
       simplifying your build setup.  But before you get there, you must drastically reduce the
       amount of information you display.  To that end there are various selection, renaming and
       merging possibilities in "makeppgraph".  When you fail to strike a balance between
       reducing the graph so far that it becomes sensibly displayable, while still showing what
       you want to see, you may fall back to a textual graph.

OUTPUT FORMATS

       Graph layouting, display and manipulation are complex tasks, which are beyond the scope of
       "makeppgraph".  Instead it produces input files for specialized tools.  It creates an
       output file replacing or adding the appropriate suffix to its first input file.  If that
       is .makepp/log, the default, the output file will skip the .makepp directory, leading to
       log.udg.  If the first input is - (stdin), the output goes to stdout.

   uDraw(Graph)
       With uDraw(Graph) <http://www.informatik.uni-bremen.de/uDrawGraph/> you get a fairly
       modern GUI, which allows to select parents or children, find the other end of an edge, or
       hide subgraphs.  Tweaking the options like the node distances, and using splines for edges
       can make the graph prettier.

       While the above features make this a tremendously useful tool, there are a few small
       hitches:

       •   It is quite memory hungry, such that, after a longish meditation, it may crash without
           having displayed anything -- a clear sign that you must reduce the number of nodes
           and/or edges further.

       •   It strongly separates graph attributes and display options.  This means that you can't
           put into a generated graph the fact that it is to be oriented sideways (which is
           generally necessary here because, even when renamed to something short, filenames are
           much wider than tall).  As a workaround, if you don't want to make it your default, or
           choose orientation from the menu every time, they propose a little starter script:

               export UDG_HOME=/where/ever/uDrawGraph-3.1
               TMP=`mktemp -t udg.XXXXXX` || exit 1
               trap "rm -f $TMP" EXIT
               echo "[menu(file(open_graph(\"${1-log.udg}\"))),menu(layout(orientation(left_right)))]" >$TMP
               $UDG_HOME/bin/uDrawGraph -init $TMP

       •   It doesn't yet support node border colors.  Due to this "--because" displays double
           borders when they should be red.

       •   When merging several files into one node leads to self edges both with
           "--dependencies" and "--includes", only one of these will be displayed, randomly
           dotted or drawn through and with a label of "2*".

   Graphviz
       Graphviz <http://www.graphviz.org/> consists of several command line tools, which allow
       many more export formats than uDraw(Graph).  That includes not only static image formats
       but also input for designer programs like dia.  There is a utility "twopi" for creating a
       radial layout, which is nice if your graph comes close to a true tree, i.e. your
       dependencies fan out, but few nodes have common dependencies with others.  There are a few
       viewers available, none of which helps you to navigate along the structure of the graph:

       dotty
           Its own display tool, dotty, has the advantage over uDraw(Graph) that you can freely
           drag the nodes, without being restricted to the level assigned by the layout.  When
           your screen is full of edges, dragging one node gives you a nice impression of where
           the edges of that node lead to.  But it also loses information when you modify it.
           Apart from that it is an antiquated Xlib tool.  It also displays an annoying little
           circle on the middle of each edge, and no option seems to get rid of it.

       ZGRViewer
           ZGRViewer <http://zvtm.sourceforge.net/zgrviewer.html> is a separately downloadable
           Java viewer which has comfortable zooming and panning.  The graph is only viewable, no
           moving of nodes.  There are five buttons in the view area, which offer additional
           fancy semi-3D zoom variations, but, unlike the basic functionality, they can be
           extremely slow depending on your Java setup.  For my Sun Linux Java, the following
           gave a tremendous boost:

               export J2D_PIXMAPS=shared USE_DGA_PIXMAPS=1

       Grappa
           Grappa is a separately downloadable Java 1.2 viewer.  There is no wrapper shell
           script, the jar contains no manifest, none of the sources contain a main function, and
           with the appletviewer it produced two tall windows which hang with a "starting applet"
           message, so I don't know how to test this.  It can be tried on a demo web site as an
           applet.

           Selecting an edge makes it bold red, so you can manually scroll its other end into
           view without loosing it out of sight.  Other than that and zooming and deleting nodes
           it seems to have no useful features.  It ignores valid hexadecimal color
           specifications.

       SVG SVG, one of the file types the backends can export to, is already quite old.  But some
           browsers still have problems with it.  When embedding it with an object tag only Opera
           scales it, others clip it, which is useless for a thumbnail.  When viewed as a
           document of it's own, only Opera and Konqueror allow scaling it, while Firefox scales
           only the labels.  Even though the labels are text, no browser can search for them.
           IE6 doesn't have a clue, unless you install a plugin.  A dedicated application, like
           Inkscape, can serve you better.

   HTML
       This is a simple unordered list tree format that can be perused with any browser.  You
       should have JavaScript and CSS, which allows folding subtrees and seeing colors.  Usually
       your graph will not be a tree, which is worked around by repeating nodes in every subtree
       needed, but as a link to the first occurrence where you can see all its attributes.  Due
       to IE's limited Unicode support, vertical arrows are used for include relations, instead
       of the usual dotted arrows.

   Textual Graph
       This is a simple indentation-based format that can be perused with any text viewer.  This
       means you can usually study much bigger graphs than with the other formats.  In Emacs you
       can use outline and foldout for very powerful graph navigation with this little wrapper
       mode:

           (define-derived-mode textgraph-mode outline-mode "Graph"
             (view-mode)
             (set (make-local-variable 'outline-regexp) " *.")
             (set (make-local-variable 'outline-level)
                  (lambda () (/ (- (match-end 0) (match-beginning 0) -1) 2)))
             (set (make-local-variable 'outline-font-lock-keywords)
                  '(("^ *\\(?:{[a-z,]+} \\)?\\([^{\n]+\\)" (1 (outline-font-lock-face) nil t))))
             (setq imenu-generic-expression
                   '((nil "^ *\\(?:{[a-z,]+} \\)?\\(.+?\\)\\(?:{[a-z,]+}\\)?$" 1))))

       The lines can have comma separated annotations between braces, unless you also give the
       "-p, --plain" option.  When these come before the target they pertain to the relationship
       with the parent, i.e. the previous line indented less.  When they come after the target,
       they pertain to the target itself.  They are as follows:

       because
           When this comes before a target, the parent was built because of this one.  When it
           comes after, the target had some inherent reason for being rebuilt.

       bidirectional
           This dependency or inclusion goes in both directions.

       include
           The parent includes this file.  This annotation is only given when also showing
           dependencies.

       phony
           This is a phony target.

       repeated
           The information about this target and its children was already given earlier on.

OPTIONS

       If you give no patterns, makeppgraph will start operating with all the nodes it can
       extract from makepp's log.  When given one or more patterns (using "?", "*", "**" and/or
       "[...]"), it will match those in the file system and operate on any that also occur in the
       log.  For these it will by default select "upwards", i.e. all targets that depend on
       and/or include any of them and "downwards", i.e. all targets and/or sources, which any of
       them depends on and/or includes.  (The directions are metaphorical, because the graph is
       best displayed from left "top" to right "bottom" due to the width of the nodes.)

       -A filename
       --args-file=filename
       --arguments-file=filename
           Read the file and parse it as possibly quoted whitespace- and/or newline-separated
           options.

       -b
       --because
       --build-reasons
           If a node was rebuilt because of a dependency, then that edge is shown in red.  Alas
           makepp applies optimizations to detect when a target needs rebuilding, such that it
           often can't say which file triggered the rebuild.  If the node was rebuilt for a
           reason not attributed to another file, then the node's border is red.  With
           uDraw(Graph) a double border is used instead, as it doesn't support border color.

       -D
       --dependencies
           Draw a graph of the dependency relationship determined by makepp.  This is the default
           unless "-i, --includes" is also given.

       -d
       --down
       --downwards
           This option is only meaningful if you provide one or more patterns.  It will then only
           select the targets and/or sources which the matched files depend on, or which they
           include.

       -g
       --graphviz
       --dot
           Produce a Graphviz .dot file, instead of the default uDraw(Graph) .udg file.

       -h
       --html
           Produce a browser .html file, instead of the default uDraw(Graph) .udg file.

       -?
       --help
           Print out a brief summary of the options.

       -I directory
       --include=directory
       --include-dir=directory
           Add directory to Perl load path @INC.

       -i
       --includes
           Instead of dependencies (or with "-D, --dependencies" additionally to them) draw a
           graph of include relationships.  This will only have been logged as far as it needed
           to be analyzed.  To get the full picture you need a fresh full build.

       -l filename
       --log=filename
       --log-file=filename
           The filename is to where makepp wrote its log.  It may also be a directory, in which a
           file called .makepp/log or log will be searched.  To read from stdin, you must give -
           as a filename.  When this option is not given, it defaults to the current directory.

           This option can be given multiple times, e.g. for merging all the logs from
           "--traditional-recursive-make".  But the dependencies you hid from makepp through the
           evil recursion paradigm can't of course show up here.

       -M module[=arg,...]
       --module=module[=arg,...]
           Load module and import any functions it exports.

       -m perlcode
       --merge=perlcode
           Perform perlcode for every target and its dependencies.  See merging for details about
           this option.

       -o filename
       --output=filename
           Write the output to this file.

       -p
       --plain
           Don't use attributes like colors or dotted lines.  This is especially useful for
           uncluttering "-t, --text" output.  In that format bidirectional edges will be lost
           unless you combine this with "-s, --separate-directions".

       -r perlcode
       --rename=perlcode
           Perform perlcode for every target and its dependencies.  See renaming for details
           about this option.

       -s
       --separate-directions
           Draw two separate arrows, instead of each double ended arrow, to make them easier to
           spot.

       -t
       --text
           Produce a human readable .txt file, instead of the default uDraw(Graph) .udg file.

       -u
       --up
       --upwards
           This option is only meaningful if you provide one or more patterns.  It will then only
           select the targets which depend on and/or include the matched files.

       -V
       --version
           Print out the version number.

REWRITING

       The techniques in this chapter are usually essential to get a reasonably sized graph.  As
       they are formulated as Perl code, knowing the language is helpful.  But you should be able
       to achieve quite a lot with the examples here or in the gallery
       <http://makepp.sourceforge.net/gallery/>.

   Renaming
       This is the first name rewriting that occurs, if the "-r, --rename" option is given.  For
       every name encountered, perlcode gets called.  It gets a filename in $_, and it may modify
       it.  This is often needed, because makepp logs fully qualified file names, so one node can
       easily be half a screen wide.

       For one thing, you can rewrite names to "undef" or the empty string.  This will eliminate
       the node from the graph.  Note that eliminating a node in this first stage will break a
       chain of dependency if this node was in the middle.

       You can also rewrite various names to the same string, coercing them all into the same
       node, which accumulates the combined dependencies and dependents.

       On the other hand you can just rename names to (usually) shorter names, so as to reduce
       the width of nodes, which can be far to wide with absolute filenames.  There are a few
       predefined functions in package "Mpp::Rewrite", in which your code also runs, you can use
       for this.  These return true if they did something so you can combine them as in:

           --rename='cwd( 1 ) || &home || &usr'

       &cwd
       cwd number
       cwd number, name[, separator]
           Removes the current working directory from the beginning of path.  With a number, also
           replaces parent directories that many levels up with the right number of ../
           directories, where applicable.  In this case you can give an alternate name, like a
           piled up ':' instead of '..' and additionally an alternate separator like '' instead
           of '/'.  In the first case you might get :/:/a/b, in the second an even shorter ::a/b
           instead of ../../a/b.  Passing a number is useful if you draw in stuff from
           neighbouring trees.  Or you have a src directory, where most of the action is, so you
           call makeppgraph there, but want to see the relation to your other directories too.

           If you give no "--rename" option, &cwd is the default.  Should you want no renaming,
           you can give some perlcode like "--rename=1" that does nothing.

       &dir
           This one is a great reducer of graph complexity.  It reduces every file to its
           directory.  That amounts to the question: "Files from which directory depend on files
           from which other directory?"  Note that while the dependency graph is always acyclic
           (else makepp wouldn't know where to start building), that is not true of this reduced
           view.  E.g. if dir1/a depends on dir2/b and dir2/a on dir1/b that will display as a
           mutual dependency between dir1 and dir2.  Since a cyclic graph has no obvious starting
           point, the layout may be odd.

           Unlike the other functions in this section, this is not exclusive with the others.  So
           you may not want to logically combine it:

               --rename='&dir; &cwd || &home'

       &home
           Replaces your home directory with ~/.

       &makepp
           Replaces the makepp installation directory with |m|.

       &suf
       suf number
           This one is also a great reducer of graph complexity.  It reduces every file that has
           a suffix to an asterisk and that suffix.  So you can see which kinds of files depend
           on which other kinds.  With an argument of 0 it leaves the first character of the
           directory, provided it is one of "/", "~" or "|" (as put in by &home or &usr if you
           called those first).  With a positive argument, it leaves that many directory levels
           at the beginning.  With a negative argument, it removes that many directory levels at
           the end.  So for /a/b/c/d/e/x.y you get:

               &suf        *.y
               suf 0       /*.y
               suf 1       /a/*.y
               suf 2       /a/b/*.y
               suf -1      /a/b/c/d/*.y
               suf -2      /a/b/c/*.y

           For a relative a/b/c/d/e/x.y you get:

               &suf        *.y
               suf 0       *.y
               suf 1       a/*.y
               suf -1      a/b/c/d/*.y

       &usr
           Under /, /usr, /usr/local, /usr/X11, /usr/X11R6, /usr/X11R7 or /opt, for any of the
           directories bin, etc, include, lib or share, the initials of these words are
           concatenated between bars.

           E.g. /usr/local/bin/foobar becomes |ulb|foobar or /usr/include/net/if.h becomes
           |ui|net/if.h.  Note that `l' stands for `local' when between two letters and for `lib'
           as the last letter.

   Merging
       This is the second name rewriting that occurs, if the "-m, --merge" option is given.  This
       API is still under development!  Currently the target is passed in $_ and the dependency
       as an argument.  If perlcode returns a value, that value replaces both the target and the
       dependency, merging them into one node.  A few predefined functions can help you:

       c2o For any C/C++ source and the resulting .o file, merge them into one node, by adding to
           the source path a suffix of ">o" like some/where/foo.cc>o, even if the .o file is in
           another directory.

       exe For any .o file and the resulting executable of the same notdir basename without a
           suffix or with .exe, merge them into one node, by adding an asterisk to the .o file.
           This will not currently work together with c2o.

       x2  For any pair of files with the same name, usually a header or library published to a
           central directory, merge them into one node, by adding *2 to the dependency.

ENVIRONMENT

       Makeppgraph looks at the following environment variable:

       $MAKEPPGRAPHFLAGS
           Any flags in this environment variable are interpreted as command line options before
           any explicit options.  Quotes are interpreted like in makefiles.

AUTHOR

       Daniel Pfeiffer (occitan@esperanto.org)