Debugging CMake

What compiler commands actually are executed

When cmake assembles the compiler commands, the final result can be written to a file “compile_commands.json” in the build folder by setting

CMAKE_EXPORT_COMPILE_COMMANDS=ON

either in CMakeLists.txt:

set(CMAKE_EXPORT_COMPILE_COMMANDS ON)

or via the command line:

cmake (...) -DCMAKE_EXPORT_COMPILE_COMMANDS=ON

This makes it easy to test the compilation of an individual file and quickly fiddle around with the options (e.g. adding or removing an option).

Where the compiler options come from

However, it’s often really hard to judge from where a specific compiler flag comes from, e.g. an include directory, as it can be set directly (e.g. target_include_directories) or indirectly from a dependency target (e.g. from target__link_libraries).

In that case on can use the following snippet to have CMake print with the following snippet in CMakeLists.txt:

set(CMAKE_DEBUG_TARGET_PROPERTIES
  INCLUDE_DIRECTORIES
  COMPILE_DEFINITIONS
  POSITION_INDEPENDENT_CODE
  CONTAINER_SIZE_REQUIRED
  LIB_VERSION
)

which I found here.

Where dependencies come from

Dependency management in huge projects is hard. Want to reuse a component and extract it from a huge workspace? Removing parts of a project (wrappers, GUI, backends) and want to know which dependencies you now can throw out?

Try the –graphviz option of cmake:

cmake .. --graphviz=dependency-graph.dot

This will generate a file dependency-graph.dot that contains all dependencies in the project. The official documentation of this feature can be found at cmake.org

To view this use dot (if you don’t have it: sudo apt install graphviz) to convert the graph file to some viewable document, e.g. to an pdf:

dot dependency-graph.dot -Tpdf -o dependency-graph.pdf

Replace -Tpdf (and the filename extension) with -Tpng to get an image instead.

A neat “trick” to make the hierarchy more readable is to set rankdir="LR"; with the -G option, which changes the layout of the hierarchy to left-to-right:

dot -Grankdir="LR" dependency-tree.dot -Tpdf -o dependency-tree.pdf

Tracing CMake

This one comes from the fantastic online book An Introduction to Modern CMake, specifically its chapter on debugging. Adding –trace-source=your-cmake-file will log every line that is run to the screen. Example:

cmake .. –trace-source=CMakeLists.txt

Adding --trace-expand will expand the variables to their values.



Home