10.8 Tracing object relationships

Understanding the LilyPond source often boils down to figuring out what is happening to the Grobs. Where (and why) are they being created, modified and destroyed? Tracing Lily through a debugger in order to identify these relationships can be time-consuming and tedious.

In order to simplify this process, a facility has been added to display the grobs that are created and the properties that are set and modified. Although it can be complex to get set up, once set up it easily provides detailed information about the life of grobs in the form of a network graph.

Each of the steps necessary to use the Graphviz utility is described below.

  1. Install Graphviz

    In order to create the graph of the object relationships, it is first necessary to install Graphviz. Graphviz is available for a number of different platforms:

    https://www.graphviz.org/download/
    
  2. Compile LilyPond with debugging functionality

    In order for the Graphviz tool to work, LilyPond needs to be compiled with the option ‘-DDEBUG’. You can achieve this by configuring with

    ./configure --enable-checking
    

    The executable code of LilyPond must then be rebuilt from scratch:

    make clean && make
    
  3. Create a Graphviz-compatible ‘.ly’ file

    In order to use the Graphviz utility, the ‘.ly’ file must include ‘ly/graphviz-init.ly’, and should then specify the grobs and symbols that should be tracked. An example of this is found in ‘input/regression/graphviz.ly’.

  4. Run LilyPond with output sent to a log file

    The Graphviz data can be sent to an arbitrary output port, including files, standard output or standard error. In the example given in ‘input/regression/graphviz.ly’, the graph is sent to stderr, like normal progress messages. You can redirect it to a logfile:

    lilypond graphviz.ly 2> graphviz.log
    

    In this case, you have to delete everything from the beginning of the file up to but not including the first occurrence of digraph. Also, delete the final LilyPond message about success from the end of the file.

    Alternatively, you can change the output port to stdout. See ‘input/regression/graphviz.ly’ for a commented example. Then you get only the graph with the following invocation:

    lilypond graphviz.ly 1> graphviz.dot
    
  5. Process the logfile with dot

    The directed graph is created from the log file with the program dot:

    dot -Tpdf graphviz.dot > graphviz.pdf
    

    The pdf file can then be viewed with any pdf viewer.

  6. Interpret the created graph

    Depending on the callbacks that were specified to be tracked within the Graphviz framework, the graph does contain varying information. It is possible to track grob creation, modification of grob properties and caching of grob properties. Generally, all tracked events happening to a particular grob are presented as a directed graph, with arrows connecting the events. All property modifications that occur within a specific file in the source code are grouped by a blue border. Caching a grob property means to calculate the result of a callback function once and store the result afterwards for further use. The node labels can be configured freely. To understand which information is showed by default, see ‘ly/graphviz-init.ly’.

When compiled with ‘-DDEBUG’, LilyPond may run slower than normal. The original configuration can be restored by rerunning ./configure with ‘--disable-checking’. Then rebuild LilyPond with

make clean && make

LilyPond — Contributor’s Guide v2.23.2 (development-branch).