Copyright update
[deps.git] / doc / README.dbk.xml
blobd6653a08a6f05c8260b3819fab8bf2135b0d89b3
1 <?xml version="1.0" encoding="UTF-8"?>
2 <!DOCTYPE article PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN" "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd">
4 <article lang="en">
5   <articleinfo>
6     <title>The graph-includes toolkit</title>
8     <author>
9       <firstname>Yann</firstname>
10       <surname>Dirson</surname>
11       <email>ydirson@altern.org</email>
12     </author>
14     <legalnotice>
15       <simpara>This program is free software; you can redistribute it
16       and/or modify it under the terms of the GNU General Public
17       License, version 2, as published by the Free Software
18       Foundation.</simpara>
20       <simpara>This program is distributed in the hope that it will be
21       useful, but WITHOUT ANY WARRANTY; without even the implied
22       warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
23       See the GNU General Public License for more details.</simpara>
24     </legalnotice>
26     <copyright>
27       <year>2005</year>
28       <year>2006</year>
29       <holder>Yann Dirson</holder>
30     </copyright>
31   </articleinfo>
33   <section>
34     <title>In short</title>
36     <simpara>Graph-includes creates a graph of dependencies between
37     source-files and/or groups of source-files, with an emphasis on
38     getting readable and usable graphs even for large
39     projects.</simpara>
41     <para>Usability of the dependency graphs are currently improved by:
42       <itemizedlist>
43         <listitem><simpara>customizable grouping of several source files into
44           a single node</simpara></listitem>
46         <listitem><simpara>transitive reduction of the
47         graph</simpara></listitem>
49       </itemizedlist>
50     </para>
52     <simpara>It currently supports graphing the C/C++ #include
53     relationship, using graphviz.</simpara>
55   </section>
57   <section>
58     <title>Important notice</title>
60     <simpara>This tool has evolved from a 50-line script written for a
61     particular project (<ulink url="http://wesnoth.org/">Battle for
62     Wesnoth</ulink>).  Although it has been generalized much, there
63     are still somewhat ad-hoc heuristics harcoded here and there,
64     especially in the default project class (see class descriptions
65     below).</simpara>
67     <simpara>Although work is under way to make this tool as generic
68     as possible, work still has to be done at all levels.  It is still
69     under development, and may not suit your needs (at least, not
70     yet).</simpara>
72   </section>
74   <section>
75     <title>Installation instructions</title>
77     <simpara>Be sure you have a recent version of Perl installed.  At
78     least List::Util is missing from versions earlier than 5.8.  You
79     can also just fetch this additional package from CPAN if you
80     cannot upgrade.  If you notice that another package is missing
81     from your installation, please report it, so it can be listed
82     here.</simpara>
84     <simpara>The Set::Object module is also required.</simpara>
86     <para>Install it like standard perl packages.</para>
87     <example>
88       <title>Sample install session</title>
89       <literallayout><prompt>$</prompt> perl Makefile.PL prefix=/usr/local
90 <prompt>$</prompt> make
91 <prompt>$</prompt> su
92 <prompt>#</prompt> make install</literallayout>
93     </example>
95     <simpara>Be sure that the directory in which the library modules
96     got installed is in your perl library path.  Eg, if
97     "graph-includes --version" does not give the expected result,
98     try setting the PERL5LIB environment variable to (in the above
99     example) /usr/local/share/perl/5.8.4/.</simpara>
101     <simpara>New versions can be found at
102     <uri>https://alioth.debian.org/projects/deps/</uri>.</simpara>
104     <simpara>A darcs repository is available at <uri
105     type="darcs">http://deps.alioth.debian.org/darcs/deps/</uri
106     >.</simpara>
108     <simpara>To be able to format the produced graphs, you will need
109     one of <ulink url="http://www.graphviz.org/">graphviz</ulink> and
110     <ulink url="http://www.tulip-software.org/"
111     >tulip</ulink></simpara>
113   </section>
115   <section>
116     <title>How to take advantage of this tool to improve your code</title>
118     <simpara>Graph-includes is only a supporting tool for a
119     refactoring effort.  It can be useful in helping a developper to
120     see where he should put its efforts in order to get cleaner and
121     saner dependencies in a project.</simpara>
123     <simpara>In this respect, it is quite similar to a microscope: if
124     you don't look at the right place, you won't see anything
125     interesting.  But if you start with a small magnifying factor, you
126     can locate regions of interest, and then zoom on those to get to
127     the interesting stuff.</simpara>
129     <section>
130       <title>On the spirit of dependency cleanup</title>
132       <section>
133         <title>First look at a dependency graph</title>
135         <simpara>When developping a project of medium size (we'll talk
136         mostly C/C++ here, but that will apply to most languages),
137         expecially with many people writing code, it is quite easy to
138         get to a point where each file (out of several tens of
139         hundreds of files) depends on too many other files.</simpara>
141         <simpara>The most obvious relation is the #include one.  The
142         more #includes a file has, the more time it takes to build -
143         especially when those included files #include themselves a
144         bunch of other files.  For a project of about 100 files, just
145         producing a graph of all those files, with arrows representing
146         the #include dependencies, will usually give an unreadable
147         graph, and will show very little about possible improvements.
148         This is why this tool has been written: to make it possible to
149         get to the useful information hidden in this unusable
150         dependency graph.</simpara>
151       </section>
153       <section>
154         <title>Looking further</title>
156         <simpara>A less obvious relation appears more clearly when you
157         consider not files by themselves, but the set of files made of
158         an interface and the matching implementation.  Let's consider
159         two such sets, made of the files a.h, a.c, b.h, b.c.  a.c
160         includes b.h, and b.c includes a.h, and each implementation,
161         following good practice, includes its own interface.  A simple
162         dependency graph as described above would show such a
163         graph:</simpara>
165         <literallayout class="monospaced"
166 >a.c -&gt; b.h
167    \  /|
168     \/
169     /   
170    /  \|
171 b.c -&gt; a.h</literallayout>
173         <para>If OTOH we represent those sets of files instead of
174         the files themselves, we now have something like:</para>
176         <literallayout class="monospaced"
177           >a &lt;--&gt; b</literallayout>
179         <para>This shows much more clearly that those two modules are
180         intrinsicately related.  In many cases, this will express that
181         whenever you use the a.o file resulting from the build of a.c,
182         you'll need to link b.o as well, and vice versa.  This will be
183         the case when each file uses the headers to get function
184         prototypes.  Then hunting for abusive dependencies will allow,
185         for example, to select with finer grain which of those modules
186         of code will need to go into which executable, thus producing
187         lighter executables.</para>
189         <simpara>Note that such a reciprocal dependency may not be
190         pathological.  Many projects tend to split a large module into
191         several files for clarity, even when those files are
192         inter-dependant.  It is much often in cycles of unidirectional
193         dependencies that we find dependencies that should not be
194         there.</simpara>
196         <simpara>In other cases, headers would just have been used to
197         access a type definition from b.h, and the associated b.o
198         would not be needed.  In such cases, you may want to consider
199         splitting such "low-level" declarations into their own
200         headers.  Not only this would simplify the graph, allowing you
201         to get a better grasp on your source code, but it can also
202         lead to faster compilations, since each file will be able
203         include less unrelated definitions.</simpara>
205       </section>
206     </section>
208     <section>
209       <title>Tuning the "files" and "includes" parameters</title>
211       <simpara>Your first run will surely looks somewhat
212       like:</simpara>
214 <literallayout class="monospaced">graph-includes -o project.ps src/ lib/</literallayout>
216       <simpara>You will take care of specifying all directories or
217       individual source files that make up your project.</simpara>
219       <simpara>In addition to an initial graph in the project.ps file,
220       which is quite likely to be incomplete by far, you will find a
221       file named project.ps.graph-includes.report.  It is a text file,
222       which will help us to finetune ou command-line.  Its first
223       section will look something like:</simpara>
225       <literallayout class="monospaced"
226 >General statistics:
227 -------------------
229 412 files, 353 nodes (14% dropped)
230 245 dependencies, 137 edges (44% dropped)
231 225 leaf node(s)
233 280 dependencies not found
234 0 dependencies identified as system headers</literallayout>
236       <simpara>As you can see, many dependencies are declared as "not
237       found".  What happens is quite similar to running a C compiler
238       without any -I flags: most header files are not
239       located.</simpara>
241       <simpara>We have in graph-includes two different flags to
242       specify paths where to look for the dependencies.  -I (aka
243       -Include) specifies directories that are part of the project,
244       and will allow to find all of our include-style dependencies.
245       OTOH, -sysI (aka -sysInclude) specifies system directories;
246       included files found in such a directory will of course not
247       result in an intra-project dependency, and will add no edge to
248       our graph, but will stop being displayed as part of the
249       "dependencies not found" count.  Thus, they will help us to see
250       how far we are from specifying all the -I flags.</simpara>
252       <simpara>Now you will most likely require several iterations of
253       adding -I/-sysI flags and checking the results.  But that alone
254       may not be sufficient to reach the ultimate "0 dependencies not
255       found":</simpara>
257       <itemizedlist>
258         <listitem>
259           <simpara>multi-platform source often have conditional
260           #include directives, and eg. win32 headers will probably not
261           be located on a Un*x box.</simpara>
262         </listitem>
263         <listitem>
264           <simpara>some generated files will require the source tree
265           to be configured in some way, or even to be partly or
266           completely built (eg. config.h generated by a "configure"
267           script, or Qt source generated by the meta-object
268           compiler)</simpara>
269         </listitem>
270       </itemizedlist>
272       <simpara>When you are confident that those remaining missing
273       dependencies are system headers for other platforms, you can go
274       on and look at the graph.</simpara>
276     </section>
278     <section>
279       <title>Possible strategies to help locating abusive
280       dependencies</title>
282       <simpara>Keeping in mind that we are essentially looking for
283       dependency loops, we expect to obtain in then end a graph that
284       will be wihout cycles, that is, with all (or, at least, most of)
285       arrows pointing from left to right in our graph.</simpara>
287       <simpara>Then we will look for those arrows pointing backwards,
288       as a sure sign for a cycle.  Remember that if the cycle is not a
289       long one, it may be legitimate; only if you judge that some of
290       the modules in this cycle are really unrelated, should your
291       consider it pathological.  Those backward arrows are not
292       necessarily directly pointing to the abusive dependency, but
293       they can surely be used to locate the culprit: by finding the
294       various cycles of which our backward arrows are part of, and
295       checking one by one all the dependencies in those cycles, you
296       can bet at least one that, with some work, could be
297       cleared.</simpara>
299       <simpara>Then, the way to modifications to do are really
300       dependant on your code.  Some possibilities include:</simpara>
302       <itemizedlist>
303         <listitem>
304           <simpara>removing an #include which is not necessary,
305           perhaps remaining from a revious code
306           reorganization</simpara>
307         </listitem>
308         <listitem>
309           <simpara>splitting a file in two parts, when you can easily
310           split the components of the file into distinct sets.  One
311           productive distinction to look for is to find a couple of
312           really high-level parts, that not all the parts depending on
313           this module would need.  This will most probably be related
314           to the dependency that you found abusive when looking at the
315           cycle in the graph.</simpara>
316         </listitem>
317       </itemizedlist>
318     </section>
319   </section>
321   <section>
322     <title>Tool architecture</title>
324     <section>
325       <title>Overview:</title>
327       <simpara>Graph-includes was initially developped with only a
328       handful of ideas, and then started to grow as I noticed where
329       useful things were missing.  That initial phase was useful for
330       me to get a grasp on the domain of dependency graphing, and
331       provided the ground for a (hopefully) decent design, which still
332       has to be completely implemented.</simpara>
334       <simpara>Together with blocking issues marked
335       <emphasis>+</emphasis> in the TODO list, the implementation of
336       this design shall be the goal for a 1.0 release.</simpara>
338       <simpara>The planned design is architectured as successive
339       layers, all of which should be pluggable to allow a high degree
340       of customization.</simpara>
342       <literallayout class="monospaced"
343 >   source locator
344          |
345          v
346   language selector
347          |
348          v
349 dependency extractor
350          |
351          v
352 graph transformations
353          |
354          v
355       styling
356          |
357          v
358    layout engine
359          |
360          v
361      rendering</literallayout>
363       <simpara>We will then be able to consider the graph-includes
364       project as being made of a number of parts:</simpara>
366       <itemizedlist>
367         <listitem>
368           <simpara>core classes and glue, implementing the above
369           design</simpara>
370         </listitem>
371         <listitem>
372           <simpara>standard classes, doing the real work </simpara>
373         </listitem>
374         <listitem>
375           <simpara>command-line and gui tools to allow easy use of the
376           whole</simpara>
377         </listitem>
378       </itemizedlist>
380       <simpara>This will hopefully make it easy for anyone to plug
381       their own work at any place in the architecture.</simpara>
383     </section>
385     <section>
386       <title>State of things</title>
388       <simpara>Currently, only the extractor and the renderer are
389       properly customizable.</simpara>
391       <simpara>Language selectors are intermixed with extractors.  The
392       current source locator is a local-tree one (alternatives would
393       include SCM-aware locators), and takes parameters from
394       per-language extractors to find files.</simpara>
396       <simpara>Project classes allow some customisation of the
397       grouping transformation, and of styling, but this has to be
398       split and generalized, as the design plans imply.</simpara>
400       <simpara>Proper graph transformations were implemented for
401       transitive reduction, and for grouping using a compatibility
402       API.  Edge labelling, the old "special edge" mechanism, and
403       color styling, have to be reimplemented.</simpara>
405       <simpara>There is no distinction (yet ?) between the layout
406       engine and the renderer.  In fact, it may not be easy to do
407       this, since most layout engines are tied to a particular
408       renderer.</simpara>
410     </section>
411   </section>
413   <section>
414     <title>Command-line usage</title>
416     <simpara>See "graph-includes --help".</simpara>
418     <section>
419       <title>output type</title>
421       <simpara>The default output is a .dot file on standard output,
422       suitable for formatting by dot (from the graphviz toolkit), or
423       interactive editing by dotty (also from graphviz).
424       Alternatively, a graph file for the Tulip graph visualizer can
425       be generated instead using "--renderer=tulip".</simpara>
427       <simpara>You can ask graph-includes to do the formatting for
428       you, eg. using "--output=&lt;file&gt;.&lt;suffix&gt;".  It will
429       run "dot -T&lt;suffix&gt;", so that "--output=mydeps.ps" or
430       "--output=mydeps.jpg" will have the expected behaviour.  If your
431       suffix is not known to dot, it will complain itself, so asking
432       for --output=foo.bar will cause a message like:</simpara>
434       <simpara>Warning: language bar not recognized, use one of: canon
435       cmap cmapx dia dot fig gd gd2 gif hpgl imap ismap jpeg jpg mif
436       mp pcl pic plain plain-ext png ps ps2 svg svgz vrml vtx wbmp
437       xdot</simpara>
439       <simpara>If you intend to print the result on paper, the default
440       layout will likely be too large.  You can use --paper=a4 to
441       select parameters that will produce a smaller graph and spilt it
442       into pages.  This flag also changes the default output format to
443       postscript.  Be warned that dot may not honor the page-splitting
444       parameter for all output formats.</simpara>
446       <simpara>Since the transitive reduction can take time, you may
447       like the --verbose switch, which will show a progress
448       bar.</simpara>
450     </section>
452     <section>
453       <title>what to draw</title>
455       <simpara>The files to be analyzed are given as non-option
456       arguments, and can be explicitely specified, or found by
457       recursing in directories.  Eg, to analyse foo.c in current
458       directory, as well as all C/C++ files in the src/ directory,
459       use:</simpara>
461 <literallayout class="monospaced">$ graph-includes foo.c src/</literallayout>
463       <simpara>When an directory argument is specified, it is searched
464       for files whose name matches a specific regexp pattern, whose
465       default value depends on the specified language (see --language
466       below).  This pattern can be overriden using the --fileregexp
467       option.  Eg, to match in addition to .c and .h files, those with
468       an additional .tmpl suffix, you could write:</simpara>
470 <literallayout class="monospaced">$ graph-includes -I src -fileregexp '\.[ch](\.tmpl)?$' src/</literallayout>
472       <simpara>How dependencies get extracted from the source files
473       depend on the language used in those files.  You can specify it
474       with the --language flag.  Default value is C (which should also
475       be used for other languages based on the C preprocessor, like
476       C++).  There is also some partial support for perl - see
477       comments in lib/graphincludes/extractor/perl.pm for more
478       details.</simpara>
480       <simpara>In order to tell the #include resolver where to look
481       for included files, you can use the cpp-like -I (aka. --Include)
482       flag.  Eg:</simpara>
484 <literallayout class="monospaced">$ graph-includes -I src src/</literallayout>
486       <simpara>Dependencies not found in the project (ie. files
487       appearing in #include but not given on command-line) are listed
488       as "not found" in the graph-includes.report file for diagnostics
489       purposes, unless they are found in a system directory.  System
490       directories are declared in a similar fashion, with the
491       --sysInclude option.  Eg:</simpara>
493 <literallayout class="monospaced">$ graph-includes -I src -sysI /opt/foo/include src/</literallayout>
495       <simpara>Language extractor have some knowledge about default
496       system include dirs: the C extractor knows about /usr/include,
497       and the Perl extractor asks perl itself.</simpara>
499       <simpara>To avoid having useless information on the graph,
500       --prefixstrip=&lt;prefix&gt; can be used to avoid repeating a
501       given prefix in all node labels.  Typically:</simpara>
503 <literallayout class="monospaced">$ graph-includes --prefixstrip=src/ src/</literallayout>
505     </section>
507     <section>
508       <title>how to draw</title>
510       <simpara>Files will be grouped in a hierarchy of groups, level 0
511       groups typically containing just one file.  Groups are defined
512       by the selected project class, selected by the
513       --class=&lt;class&gt; option.  See below for descriptions of the
514       project classes available by default, and for instructions to
515       write customized project classes.</simpara>
517       <simpara>The range of group levels to be drawn is selected with
518       --group=&lt;min&gt;-&lt;max&gt;, which defaults to 1-1.  Eg, for
519       class "default", whose group levels are defined as:</simpara>
521       <glosslist>
522         <glossentry>
523           <glossterm>0</glossterm>
524           <glossdef>
525             <simpara>one file per group</simpara>
526           </glossdef>
527         </glossentry>
528         <glossentry>
529           <glossterm>1</glossterm>
530           <glossdef>
531             <simpara><filename>what/ever.*</filename> go into a
532             <filename>what/ever</filename> group (usually interface +
533             implementation)</simpara>
534           </glossdef>
535         </glossentry>
536         <glossentry>
537           <glossterm>2</glossterm>
538           <glossdef>
539             <simpara><filename>what/*</filename> go into a
540             <filename>what</filename> group, supposing top-level
541             directories denote modules of some sort</simpara>
542           </glossdef>
543         </glossentry>
544       </glosslist>
546       <simpara>Group levels below "min" or above "max" are not
547       displayed as nodes.  Groups of level "min" are drawn as nodes of
548       the graph.  If "max" is strictly greater than "min", then groups
549       of levels "min+1" through "max" are drawn as box clusters
550       containing lower-level groups.</simpara>
552       <simpara>Since such a way of grouping nodes will not improve the
553       readability in projects where the inter-groups dependencies have
554       not been cleaned up yet, higher-level groups can instead be
555       colored, using a class-defined color scheme, possibly modified
556       by <userinput>--color
557       &lt;n&gt;:&lt;label&gt;=&lt;color&gt;[,&lt;label&gt;=&lt;color&gt;&#8230;]</userinput>
558       options, where &lt;n&gt; is the group level in which the group
559       name &lt;label&gt; will receive a background of the specified
560       color, which can be defined either by a named X11 color (like
561       "blue" or "palegreen"), or by a RGB color using the standard X11
562       "#RRGGBB" syntax.</simpara>
564       <simpara>The number of grouping levels to be colored is limited
565       by the renderer to be used.  As of 0.11, the dot renderer only
566       supports coloring 2 group levels.  Groups of a lower level than
567       the minimal level requested to --group cannot be colored, for
568       obvious reasons.</simpara>
570       <simpara>For those wanting to see what edges the transitive
571       reduction dropped, the --showdropped will add them to the graph
572       in a different color.  Be prepared for your computer room to get
573       a noticeable temperature increase for anything else than a small
574       set of files with only few dependencies.</simpara>
576       <simpara>OTOH, <option
577       >--focus=<replaceable>node-label</replaceable ></option> will do
578       the same, but only for the dependencies of a specified node.
579       That should prevent the nasty effects described above, and will
580       be useful for various purposes, including debugging the
581       transitive reducer.  The node-label refers to a node in the
582       lowest group-level drawn, ie. the "min" argument to
583       --group.</simpara>
585       <simpara>People still getting cold may also like to circumvent
586       the transitive-reduction engine completely, using --alldeps.
587       The author assumes no responsibility for losses of mental health
588       induced by trying to make any serious use of the resulting
589       graph.</simpara>
591     </section>
592   </section>
594   <section>
595     <title>Existing project classes</title>
597     <section>
598       <title>class "default"</title>
600       <simpara>As implied by its name, it is the one which will be
601       used unless you use the --class option.  Although it is the
602       default one, it may still be quite rough at the moment, still
603       using some ad-hoc heuristics, and will be improved in the near
604       future.  Here are its main characteristics:</simpara>
606       <itemizedlist>
607         <listitem>
608           <simpara>looks at C-style #include lines</simpara>
609         </listitem>
610         <listitem>
611           <simpara>creates level-1 groups for all files sharing the same
612             path and (disregarding the suffix) filename.  Eg, files
613             "foo/bar.c" and "foo/bar.h" would be grouped in a "foo/bar"
614             level-1 group.  In clear, it won't connect include files if
615             they are all located in an include/ directory.</simpara>
616         </listitem>
617         <listitem>
618           <simpara>creates by-directory level-2 groups.  Eg. in the
619             above example, a group "foo" would exist at level-2.</simpara>
620         </listitem>
621       </itemizedlist>
622     </section>
624     <section>
625       <title>class "uniqueincludes"</title>
627       <simpara>Built on top of the default class, it is meant for
628         projects where file names are kept unique across all directories.
629         If the ad-hoc #include processing of the default class does not
630         suit your project, it is the only out-of-the-box alternative
631         available today.  Here are its main characteristics:</simpara>
633       <itemizedlist>
634         <listitem>
635           <simpara>provides a single grouping level based on filenames,
636             disregarding all the directory hierarchy.</simpara>
637         </listitem>
638       </itemizedlist>
640       <simpara>Note that it is not meant for general use, as:</simpara>
642       <itemizedlist>
643         <listitem>
644           <simpara>it will group any files with the same name in the
645             same level-0 group, possibly causing confusion.</simpara>
646         </listitem>
647         <listitem>
648           <simpara>it does not make any directory name appear in the
649             node names</simpara>
650         </listitem>
651       </itemizedlist>
653     </section>
654   </section>
656     <section>
657     <title>Examples of use</title>
659     <section>
660       <title>Pure command-line examples</title>
662       <section>
663         <title>Graphing graph-includes itself:</title>
665         <literallayout>$ ./graph-includes -lang perl -I lib -prefixstrip lib/ -o deps.ps     graph-includes lib/</literallayout>
667         <simpara>graph-includes does not know in advance which classes
668           it will use</simpara>
669       </section>
671       <section>
672         <title>Rather clean ones:</title>
674         <simpara>a rather clean dependency graph</simpara>
676         <literallayout>Maelstrom-3.0.6$ graph-includes -v -sysI /usr/include/SDL     -I . -I ./netlogic -I ./maclib -I ./screenlib --prefixstrip ./ -o deps.ps .</literallayout>
678         <simpara>more work has to be put in the wesnoth example class:</simpara>
680         <literallayout>wesnoth-0.9.1$ graph-includes -v --class wesnoth --group 1-1     -sysI /usr/include/c++/3.3 -sysI /usr/include/SDL     --prefixstrip src/ -I src -o deps.ps src/</literallayout>
682       </section>
684       <section>
685         <title>Examples only here as a reminder to write proper project
686           classes for them</title>
688         <para>needs supporting features for multi-arch source trees:</para>
690         <literallayout>qemu-0.7.0$ graph-includes -v -sysI /usr/include/SDL     $(find -name CVS -prune -o -type d -printf <emphasis>-I %p\n</emphasis>) -o deps.ps .</literallayout>
692         <para>needs proper file-grouping:</para>
694         <literallayout>mesag-6.2.1$ graph-includes -o -I ./include -I ./include/GL     -I ./src/mesa -I ./src/mesa/main -I ./src/glu/sgi/include     -I ./src/glu/sgi/libnurbs/internals -I ./src/mesa/glapi -o deps.ps .</literallayout>
696       </section>
697     </section>
699     <section>
700       <title>Customization examples</title>
702       <simpara>See graphincludes::project::wesnoth in the examples/
703       dir as an example of a custom project class.</simpara>
705       <simpara>Keep in mind that the API is not frozen yet, and will
706       probably be overhauled more than once before an official API
707       gets blessed.</simpara>
709     </section>
710   </section>
712   <section>
713     <title>Caveats</title>
715     <itemizedlist>
716       <listitem>
717         <simpara>this script only handles explicitely-declared
718         dependencies, it won't detect it if eg. a prototype was
719         cut'n'pasted instead of using the correct #include, but you
720         shouldn't do that anyway :)</simpara>
721       </listitem>
722     </itemizedlist>
723   </section>
725   <section>
726     <title>Related tools</title>
728     <simpara>I finally found a couple of tools out there, from which I
729     may borrow ideas some day.  I'd be happy to hear about more of
730     them.</simpara>
732     <itemizedlist>
733       <listitem>
734         <simpara>cinclude2dot, originally from Darxus
735         (http://www.chaosreigns.com/code/cinclude2dot/), then taken
736         over by F. Flourish (http://www.flourish.org/cinclude2dot/) is
737         a GPL C/C++-only tool, which apparently has support for
738         grouping, but not for transitive reduction.  Should I have
739         searched better, and found it a couple of months ago, maybe
740         graph-includes would have never been developped :)
741         </simpara>
742       </listitem>
743       <listitem>
744         <simpara>http://www.tarind.com/depgraph.html has a dependency
745         grapher for python, without transitive reduction as well.  It
746         does however allow customisation of project classes, somewhat
747         similar to graph-includes.</simpara>
748       </listitem>
749       <listitem>
750         <simpara>OptimalAdvisor
751         (http://javacentral.compuware.com/pasta/) is a refactoring
752         tool, which goes far beyond simple dependency analysis, but is
753         non-free/libre/open-source (also they have a
754         functionally-limited free/gratis edition) and seems to support
755         only java.</simpara>
756       </listitem>
757       <listitem>
758         <simpara>codeproject.com has some VisualStudio(tm) plugins
759         targetting C++, which I cannot test, but appear to scale badly
760         for large projects
761         (http://www.codeproject.com/csharp/DependencyGraph.asp).</simpara>
762       </listitem>
763     </itemizedlist>
764   </section>
766   <section>
767     <title>TODO</title>
768       <section>
769         <title>general</title>
771       <itemizedlist>
772         <listitem>
773           <simpara>consider using Set::Object instead of hashes for
774           sets</simpara>
775         </listitem>
776         <listitem>
777           <simpara>continue merging the verbose/debug behaviour into
778           the global report file</simpara>
779         </listitem>
780         <listitem>
781           <simpara>change case of class names when the API gets
782           stabilized</simpara>
783         </listitem>
784         <listitem>
785           <simpara>finalize filename portability support, using
786           File::Spec volume information</simpara>
787         </listitem>
788       </itemizedlist>
789     </section>
791     <section>
792       <title>core engine</title>
794       <itemizedlist>
795         <listitem>
796           <simpara>allow to associate attributes to files (eg. an ARCH
797           attribute for multi-architecture trees, like kernels,
798           development tools and emulators)</simpara>
799         </listitem>
800         <listitem>
801           <simpara>modularization (finish the restructuring into a
802           cleaner and more modular design)</simpara>
803         </listitem>
804         <listitem override="+">
805           <simpara>rework the recording of
806           edges to make them apply to files, not to graph nodes, since
807           more advanced features will need more flexibility</simpara>
808         </listitem>
809         <listitem>
810           <simpara>allow passing options to modules (-O param=value
811           ?)</simpara>
812         </listitem>
813         <listitem>
814           <simpara>separate styling from project classes</simpara>
815         </listitem>
816         <listitem>
817           <simpara>allow to define several views in a project-class,
818           several of which can be generated by default.</simpara>
819         </listitem>
820         <listitem>
821           <simpara>find out whether we can declare
822           protocols/pure-virtual-classes in some way, to cleanup the
823           class graph</simpara>
824         </listitem>
825         <listitem>
826           <simpara>generalize --prefix-strip
827           </simpara>
828         </listitem>
829         <listitem>
830           <simpara>give consistent access to all commonly-needed
831           features through command-line and class
832           customization</simpara>
833         </listitem>
834         <listitem>
835           <simpara>generalize the special_edge() mechanism (use a hash
836           of edge attributes ?)</simpara>
837         </listitem>
838         <listitem>
839           <simpara>Maybe allow to use as nodes other objects than
840           files (eg. URI objects ?), for ultimate
841           generalization.</simpara>
842         </listitem>
843       </itemizedlist>
844     </section>
846     <section>
847       <title>graph-includes tool</title>
849       <itemizedlist>
850         <listitem>
851           <simpara>allow to run from a build directory</simpara>
852         </listitem>
853         <listitem>
854           <simpara>--class does not allow to find the project file
855           (need to set PERL5LIB)</simpara>
856         </listitem>
857         <listitem>
858           <simpara>caller must prepend path to source tree to
859           --prefixstrip and all relative -I flags</simpara>
860         </listitem>
861         <listitem override="+">
862           <simpara>find the accessory classes as easily as possible
863           (like bugzilla ?)</simpara>
864         </listitem>
865         <listitem>
866           <simpara>better robustness to incorrect arguments
867           (eg. --group 1:2)</simpara>
868         </listitem>
869         <listitem>
870           <simpara>automate --help production (see Pod::Usage
871           ?)</simpara>
872         </listitem>
873         <listitem override="+">
874           <simpara>multi-sheet paper support may be broken</simpara>
875         </listitem>
876         <listitem>
877           <simpara>use an existing source of paper formats (libpaper,
878           LC_PAPER, whatever)</simpara>
879         </listitem>
880         <listitem>
881           <simpara>maybe use graphviz' tred(1) to check our transitive
882           reductions.</simpara>
883         </listitem>
884         <listitem>
885           <simpara>some autodetection of the language to use based on
886           filenames ?</simpara>
887         </listitem>
888         <listitem>
889           <simpara>provide an initial list of system directories to
890           avoid repeating them (ask compiler)</simpara>
891         </listitem>
892       </itemizedlist>
893     </section>
895     <section>
896       <title>extractors</title>
897       <itemizedlist>
898         <listitem override="+">
899           <simpara>allow -I syntax for programs using eg. -I. from
900           source subdirectory</simpara>
901         </listitem>
902         <listitem override="+">
903           <simpara>behave as expected wrt leading "./", use
904           File::Spec for more portability</simpara>
905         </listitem>
906         <listitem>
907           <simpara>consider using Cwd::realpath or so, for correct
908           "../" handling</simpara>
909         </listitem>
910         <listitem>
911           <simpara>write other extractors (java, python,
912           &#8230;)</simpara>
913         </listitem>
914         <listitem>
915           <itemizedlist>
916             <title>C-like extractor</title>
917             <listitem>
918               <simpara>some support for CPP symbol conditionals
919               (mostly #ifdef), perhaps coupling this with
920               attributes</simpara>
921             </listitem>
922             <listitem>
923               <itemizedlist>
924                 <title>write an openc++-based dependency
925                 extractor</title>
926                 <listitem>
927                   <simpara>extract more fine-grained dependency
928                   (depending on a header does not necessarily imply
929                   depending on code)</simpara>
930                 </listitem>
931                 <listitem>
932                   <simpara>handle (warn about) the case where the
933                   declarations for a given implementation file are
934                   scattered in more than one header</simpara>
935                 </listitem>
936               </itemizedlist>
937             </listitem>
938           </itemizedlist>
939         </listitem>
940         <listitem>
941           <simpara>detect undeclared dependencies (eg. manually
942           inserted prototypes)</simpara>
943         </listitem>
944         <listitem>
945           <simpara>check necessity of declared includes</simpara>
946         </listitem>
947         <listitem>
948           <itemizedlist>
949             <title>perl extractor</title>
950             <listitem>
951               <simpara>remove arbitrary limitations</simpara>
952             </listitem>
953             <listitem>
954               <simpara>report use/require lines we could not
955               completely parse</simpara>
956             </listitem>
957             <listitem>
958               <simpara>do some invariant analysis when importing a
959               module using a variable name.  Investigate drawing 1->n
960               links in this case.</simpara>
961             </listitem>
962           </itemizedlist>
963         </listitem>
964       </itemizedlist>
965     </section>
967     <section>
968       <title>project classes</title>
970       <itemizedlist>
971         <listitem>
972           <simpara>proper way to define include paths in project
973           class</simpara>
974         </listitem>
975         <listitem>
976           <simpara>make default project-class consider multiple levels
977           of directories as group levels, but only if they
978           (consistently ?) have multiple subgroups ?</simpara>
979         </listitem>
980         <listitem>
981           <simpara>write a linux-kernel class and others as examples
982           :)</simpara>
983         </listitem>
984         <listitem>
985           <simpara>provide a simple hash-based filelabel
986           implementation</simpara>
987         </listitem>
988       </itemizedlist>
989     </section>
991     <section>
992       <title>grouping</title>
994       <itemizedlist>
995         <listitem>
996           <simpara>Abstract the grouping process into GroupSet
997           objects, computed independently from other
998           processes, and customizable</simpara>
999         </listitem>
1000         <listitem>
1001           <simpara>Provide a regexp-based grouper, useful from
1002           command-line, and as a base for current level-1 grouping,
1003           and possibly to automatic per-directory grouping</simpara>
1004         </listitem>
1005         <listitem>
1006           <simpara>provide tools for automatic grouping (eg. using
1007           cycles, or selected external deps, or from leaves)</simpara>
1008         </listitem>
1009         <listitem>
1010           <itemizedlist>
1011             <title>keep group members as close as possible</title>
1012             <listitem>
1013               <simpara>Give more weight to intra-group edges</simpara>
1014             </listitem>
1015             <listitem>
1016               <simpara>Improve transitive reductions implying multiple
1017               edges into a single cycle, to prefer an edge into the
1018               lowest-level common group</simpara>
1019             </listitem>
1020           </itemizedlist>
1021         </listitem>
1022       </itemizedlist>
1023     </section>
1025     <section>
1026       <title>styling</title>
1028       <itemizedlist>
1029         <listitem>
1030           <simpara>allow styling through font color, node shape
1031           (dot/tulip), number of peripheries (dot)</simpara>
1032         </listitem>
1033         <listitem>
1034           <simpara>allow to draw non-consecutive group
1035           levels (eg. --groups 1,3)</simpara>
1036         </listitem>
1037         <listitem>
1038           <simpara>allow different node shapes when mixing high-level
1039           nodes with lower-level ones through the default singleton
1040           groups (special_node mechanism similar to the special_edge
1041           one ?)</simpara>
1042         </listitem>
1043         <listitem>
1044           <simpara override="+">optionally show labels (using
1045           attributes ?) or count for files (subnodes) in a node and
1046           color arcs according to them</simpara>
1047         </listitem>
1048         <listitem>
1049           <simpara>optionally show external deps (deps on files not on
1050           command-line)</simpara>
1051         </listitem>
1052         <listitem>
1053           <simpara>limit graph to one or more given group(s) of files
1054           (specified by &lt;level&gt;:&lt;label&gt;)</simpara>
1055         </listitem>
1056         <listitem>
1057           <simpara>draw cycles in a given color</simpara>
1058         </listitem>
1059         <listitem>
1060           <simpara>draw a specific path</simpara>
1061         </listitem>
1062         <listitem>
1063           <simpara>provide automatic coloring schemes</simpara>
1064         </listitem>
1065         <listitem>
1066           <simpara>color intra-group edges with the same color as
1067           nodes (post-processing ?)</simpara>
1068         </listitem>
1069         <listitem>
1070           <simpara>allow to request drawing of who in a high-level
1071           node points to another node (ie. violates some
1072           constraint)</simpara>
1073         </listitem>
1074         <listitem>
1075           <simpara>propagate excuses in some way when they are dropped
1076           by the transitive reducer</simpara>
1077         </listitem>
1078         <listitem>
1079           <simpara>investigate candidate tools for hyperbolic layout
1080           ?</simpara>
1081         </listitem>
1082         <listitem>
1083           <simpara>allow to show the count of deps in a given edge
1084           using line width instead of labels</simpara>
1085         </listitem>
1086       </itemizedlist>
1087     </section>
1089     <section>
1090       <title>documentation</title>
1091       <itemizedlist>
1092         <listitem>
1093           <simpara>write more documentation</simpara>
1094         </listitem>
1095       </itemizedlist>
1096     </section>
1098     <section>
1099       <title>testsuite</title>
1101       <itemizedlist>
1102         <listitem>
1103           <simpara>write a testsuite.</simpara>
1104         </listitem>
1105         <listitem>
1106           <simpara>ensure that all provided non-abstract classes are
1107             self-contained</simpara>
1108         </listitem>
1109       </itemizedlist>
1110     </section>
1112     <section>
1113       <title>gui</title>
1115       <para>The standard GUI should be able to navigate the project
1116       definition, visualizing the hierarchy of groups, (un)folding
1117       groups and edges, displaying single culprits from a group, and
1118       anything you can think of.</para>
1120       <para>For an engine, maybe with graphviz' lefty, or write a
1121       specialized tulip gui ?  A self-customizable GUI like entity may
1122       be a good idea.  Since entity has support for OpenGL areas,
1123       maybe it can be made to embed tulip graphs.</para>
1125     </section>
1126   </section>
1128   <section>
1129     <title>Known bugs</title>
1131     <itemizedlist>
1132       <listitem>
1133         <simpara>volume names in paths are not handled yet (eg. on
1134         windows)</simpara>
1135       </listitem>
1136       <listitem>
1137         <simpara>on windows, backslash path separator in -prefixstrip
1138         argument interferes with regexp ("Trailing \ in regex m/ ... at
1139         wesnoth.pm line 21")</simpara>
1140       </listitem>
1141       <listitem>
1142         <simpara>traversal counts on edges are unreasonably high on
1143         cycles (real graph traversal issue, but unlikely to get fixed
1144         before we get another visual way to spot cycles ;)</simpara>
1145       </listitem>
1146       <listitem>
1147         <simpara>the colored style of a node of level &lt; min is not
1148         shown when that node is displayed because it is not part of
1149         any node &gt; min and &lt; max.</simpara>
1150       </listitem>
1151       <listitem>
1152         <simpara>--showdropped mode draws too many edges as dropped
1153         (ie. does not consider marked edges as dropped when deciding
1154         whether to consider subsequent edges as dropped)</simpara>
1155       </listitem>
1156       <listitem>
1157         <simpara>transitive reduction may not be complete, some more
1158         edges could possibly be dropped - wesnoth tree at 2005-03-25
1159         exhibits the problem with the "display -&gt; builder -&gt;
1160         animated -&gt; image" path</simpara>
1161       </listitem>
1162     </itemizedlist>
1163   </section>
1165 </article>