Makepp
HomeFAQDocumentationDownloadSourceForgeCPAN

Makepp Gallery

What graphs show you

Examples

First come the examples to whet your appetite. The overall explanation comes at the bottom. If you are interested in general screenshots about makepp usage, those are found on the sourceforge project page.


SuffixesHTML variant

Here we care only about suffixes, which are obtained, where present, by the rename action &suf. Instead, files which have no suffix at least get the directory stripped. This is performed by a Perl substitute operation up to the last slash, on all names not handled by the first expression.

makeppgraph -gr '&suf || s!.*/!!'
dot -Tsvg log.dot >suf.svg
makeppgraph -hr '&suf || s!.*/!!' -o suf.html

Because of still widely varying browser quality concerning SVG, the preview is a classical bitmap image. If you click on it, you get the actual SVG unscaled, which all modern browsers display fine. If you don't have one, get one, like Opera, Konqueror or Firefox. Else get a plugin, or view them externally, e.g. with Inkscape or GIMP.

Alternately use the "HTML variant" link in each preview. This gives you an equivalent representation, flattened into a tree. The snag is that you can get the same nodes in several places, in which case they are presented as a link to the first occurrence. With JavaScript you can click nodes to fold their subtrees.


DirectoriesHTML variant HTML variant

Here we care only about directories, which are obtained by the rename action &dir. Additionally we make our subdirectories relative to the current working directory, which is done with &cwd. Other directories are eliminated by undef`ing in the left case. In the right case they are tried for a fancy rewriting with &usr. This tries to abbreviate various standard directories like /usr/include through their initials between bars, in this case |ui|.

Note how the current directory, labelled with a dot, comes out oval. That is because it contains the phony "all" target. It also contains real targets, but it can have just one shape...

makeppgraph -gr '&dir; &cwd || undef $_'
twopi -Tsvg -Goverlap=scale log.dot >dir.svg
makeppgraph -gr '&dir; &cwd || &usr'
twopi -Tsvg -Goverlap=scale log.dot >dir-usr.svg

There is a speciality with the &dir renaming method. A build tree must be acyclical, else makepp wouldn't know where to start. But there may be crosswise dependencies of files across directories, which get merged into one node here. So it is likely that this graph is cyclical. Therefore some edges may have two arrowheads. Among the Graphviz tools twopi seems to give the best results here, while uDraw(Graph) manages nicely with its normal layout.

But the incredible mess this graph is in, is a clear sign of too many interdirectory dependencies. In the case of this stress test, that is intended. But if you see this in your build system, you might gain something by putting interdependent things together. Btw. the reduced vision this conveys is similar to what traditional recursive build systems do. Those are of course wrong in their simplistic approach, whereas here it is only an extract of the actual complete dependency information.


Radial HTML variant

This style of layout is alas only provided by Graphviz. Whereas we used it as the least chaotic form in the previous example, it is best applied if you have a fairly tree-shaped graph, i.e. few nodes have common dependencies. Since these mostly stem from header files, we eliminate those, by substituting them with the empty string. For those that remain we try to make them relative to the current working directory, as before. Of these we again eliminate the bin dir, since all .o files depend on the compiler. This algorithm has three variants, which can be selected with the -Goverlap option. Without it, you get an extremely crowded graph, so we show the two others here.

cd src
makeppgraph -l.. -gr 's/.*\.h// || cwd( 1 ) && s!^\.\./bin.*!!'
cd ..
twopi -Tsvg -Goverlap=false log.dot >twopi-false.svg
twopi -Tsvg -Goverlap=scale log.dot >twopi-scale.svg

What would happen if?HTML variant

At times you might wonder what consequences a modification would have. For this you pass the file or files you have in mind to makeppgraph. The produced graph will now be limited to those files which the given ones depend on and those targets that depend on them. In this case you are only interested in the latter kind, so you might give the -u option to only select those. But since you would not usually modify a file that depends on something else (makepp would rebuild it first thing unless you say --dont-build), you don't need to.

makeppgraph -gr '&cwd && s/^all$//' src/h/hehpsem.genec
dot -Tsvg log.dot >what-if.svg

Why was this built?HTML variant HTML variant

Up to now all graphs were static. But often you will want to see why makepp built what it did. If you call makeppgraph --because you get a red arrow for those targets that got built because of a dependency, and a red border (double line in udraw(Graph) which doesn't allow colouring borders) for those that had an inherent reason (like changed command options). Alas makepp optimizes its decisions strongly, not caring in detail which input changed when the set of input signatures no longer matches. And it took only one reason to build, even if there would have been others, so deceiveingly not everything that could will be red.

Here the -d option is given to select only (logically) downwards from the target, which in this case eliminates only the phony all target. Since the result is quite overwhelming, in the second attempt the suf( 9 ) reduces all names under the current working directory to the first nine (i.e. all, use a bigger number if needed) directory levels, an asterisk and the suffix.

makeppgraph -gbdr '&cwd || undef $_' proggie1
dot -Tsvg log.dot >proggie1.svg
makeppgraph -gbdr '&cwd ? suf( 9 ) : undef $_' proggie1
dot -Tsvg log.dot >proggie1-suf.svg

Who includes what?HTML variant HTML variant

Up to now all graphs showed dependency relationships. But makepp also analyzes include relationships. As these get shown with dotted lines, so as to differentiate them, they can hardly be seen in the small previews.

makeppgraph -guir '&cwd || undef $_' include/rided.h
dot -Tsvg log.dot >inc-up.svg
makeppgraph -gdir '&cwd || undef $_' src/h/hehpsem.c
dot -Tsvg log.dot >inc-down.svg

Combine dependencies and includeHTML variant

This is the same as the first example. But here we combine it with include information.

makeppgraph -gDir '&cwd; &suf || s!.*/!!'
dot -Tsvg log.dot >combine.svg

Explanation

This page wants to show you what kinds of graphs you can create from your build system, so as to better analyze it. By calling just makeppgraph without any tuning, you get a rather useless graph of a staggering complexity. Instead we used rewriting and selection options to obtain various more manageable graphs of the same build system.

These are principally small Perl scripts, but thanks to the utility functions you need not know much Perl. It might be useful to know that ; separates operations that happen one after another, while && chains two operations together so that the second happens if the first succeeds. Conversely with || it is if the first fails. && binds more strongly than ||, that is, you can combine several of the former before and/or after one of the latter. And you can of course reorder these with parentheses, as in maths.

All this is based on an abstract build system. Makepp has a stress test generator for spitting out build systems of any size. The directory was created with stress-test.pl 'names 25' and you can look at a listing before and after building. The mechanisms are best seen in the first example above.

The C sources contain mostly preprocessor statements (which makepp must understand to find dependencies). In addition there are embedded SQL/C sources (*.ec) as well as a generation mechanism based on *.genc, *.genh and *.genec input files, from which the aforementioned sources are derived. The test suite had been conceived for stressing makepp, not the compilers, so it even comes with tiny pseudo-compilers, which you will find in the bin directory. An include directory is created with symbolic links to most .h files, for simpler compiler options.

More to come -- come back soon!

Daniel Pfeiffer
Last modified: 2012/01/06