  | 
 
 
 
 |  
 |  | 
 
  
    | MAKEPPGRAPH(1) | 
    Makepp | 
    MAKEPPGRAPH(1) | 
   
 
makeppgraph -- Graphical analysis of the dependency graph 
?: -?,  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. 
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. 
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: 
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.
 
 
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. 
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.
 
 
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.
 
 
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/>. 
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. 
   
 
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.
 
 
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.
 
 
Daniel Pfeiffer (occitan@esperanto.org) 
 
 
  Visit the GSP FreeBSD Man Page Interface. Output converted with ManDoc.
  |