Skip to content
Switch branches/tags

Latest commit


Git stats


Failed to load latest commit information.
Latest commit message
Commit time


License & Copyright

  • Copyright (C) 2009-2015 University of Passau, Germany

All rights reserved.

cppstats is covered by the GNU Lesser General Public License. The full license text is distributed with this software. See the LICENSE.LESSER file.

Main Developers

Further Contributors

What is it?

cppstats is a suite of analyses for measuring C preprocessor-based variability in software product lines.

Currently, cppstats supports following analyses:

  • general,
  • generalvalues,
  • discipline,
  • featurelocations,
  • derivative, and
  • interaction.

For detailed information on each kind of analysis, please refer to the corresponding paragraph below in this file.

For further information, please see the tool's homepage at:

Details of the latest version can be found on the cppstats project site at GitHub under

System Requirements


cppstats should be runnable under following systems:

  • Linux/Ubuntu,
  • Mac OS X, and
  • Cygwin.

Please see the file called for detailed instructions for each system.

In detail, cppstats was successfully tested under:

  • Ubuntu 12.04, Python 2.7.*, and
  • Cygwin, Python 2.7.*.

Right now, Python 3.x is NOT supported.

Quick Start

  • Install cppstats using sudo python install.

  • Supply cppstats with the appropriate paths in cppstats_input.txt

    • use full paths like /local/repos/mpsolve/mpsolve-2.2

    • each project folder given in the file has to be structured as follows:

      > /local/repos/cpp-history/mpsolve/mpsolve-2.2/
          > source/ (here are the C source files)
  • Then run:

    $ cppstats --kind <K>

    <K> must be one of the analyses listed in the introduction. Also, have a look on cppstats --help for further command line options.

  • The output files for each analysis are written to the folders given in the file cppstats_input.txt.



    • Measurement of CPP-related metrics regarding scattering, tangling, and nesting
    • returns a list of metrics for each file, and a list of metric values for the whole project folder

    • Calculation of scattering, tangling, and nesting values
    • allows deactivation of the rewriting of #ifdefs to get a 'pure' result
      • rewriting changes #else branches from no used constant to the negation of the corresponding #if clause
    • returns a list for each characteristic, which #ifdef or configuration constant has which value (merged and unmerged)
      • unmerged: each #ifdef expression is counted once per file
      • merged: each #ifdef expression is counted once per project

    • Analysis of the discipline of used CPP annotations
    • returns the number of occurences for the categories listed below
      • (1) check top level siblings (compilation unit)'
      • (2) check sibling (excludes check top level siblings; NOT CLASSIFIED)'
      • (4) check if-then enframement (wrapper)'
      • (8) check case enframement (conditional)'
      • (16) check else-if enframement (conditional)
      • (32) check param/argument enframement (parameter)
      • (64) check expression enframement (expression)
      • (128) check else enframement (NOT CLASSIFIED)

    • Analysis of the locations of CPP annotation blocks in the given file or project folder
    • returns a table with the following headers:
      • file
      • starting line
      • end line
      • type of the annotation (#if, #elif, #else)
      • the #ifdef expression -- involved configuration constants

    • Analysis of all derivatives in the given project folder
    • returns all CPP annotations that involve shared code (expression contains &&)

    • Analysis of pair-wise interactions of configurations constants that have been used alltogether in one expression (# of constants involved >= 3)
    • (A, B, C) -> |(A, B)? (A, C)? (B, C)? ...|

General Notes

  • When cppstats computes general stats (--kind general parameter), the reported granularity function level (GRANFL) also accounts for conditional elements within an array initialization or conditional field initializations when creating a struct variable. Example (for array):

    static const struct squashfs_decompressor *decompressor[] = {
      #if defined(CONFIG_SQUASHFS_LZO)

    The rationale behind such decision is that array/struct instance initializations can be interpreted as constructor procedure calls.


toolsuite for analyzing cpp-preprocessor-based software product lines




No packages published