Skip to content

Latest commit

 

History

History
197 lines (144 loc) · 6.09 KB

File metadata and controls

197 lines (144 loc) · 6.09 KB

CMake Debugging Guide

This guide explains how to attach a debugger to CMake's unit testing framework. We'll focus on using GDB on Linux for both command-line and IDE debugging. See documentation on CMake Development for more information.

Linux: Using GDB

On Linux, the GNU Debugger (GDB) is the standard tool for debugging the CMake test suite. The core process involves launching the cmake executable from within GDB with a specific set of arguments that configure and run the desired test.

GDB Configuration

For effective debugging, GDB must be configured to handle child processes correctly, which CMake tests often create. A good practice is to use a local .gdbinit file in your build directory. This keeps CMake-specific settings separate from your global configuration.

1. Enable Local .gdbinit Files (One-Time Setup)

To allow GDB to automatically load configuration from your build directory, add the following line to your global GDB initialization file at $HOME/.gdbinit. This is a one-time setup that makes future projects easier to manage.

set auto-load local-gdbinit on

2. Create a Project-Specific .gdbinit

Next, create a .gdbinit file inside your CMake build directory. This file will contain settings specific to debugging CMake. To make this easier, you can symlink the template file provided in the CMake source tree:

# Navigate to your build directory
cd /path/to/your/cmake/build

# Create a symlink to the template
ln -s $cmake_srcdir/Utilities/gdb/gdbinit-template .gdbinit

The template contains the essential settings for debugging CMake tests:

# Allows GDB to follow child processes
set follow-fork-mode child

# Allows the parent process continue in parallel
set non-stop on

Debugging from the Command Line

To start debugging, first cd to the build directory. Then, launch the cmake executable using gdb --args, which passes the necessary test configuration arguments directly to CMake.

Note

To get the launch command, run ctest -R "RunCMake.$TESTNAME" -VV -N

The following example runs the InstallPackageInfo test.

# Define paths to your CMake source and build directories
CMAKE_SOURCE_DIR="$HOME/cmake"
CMAKE_BUILD_DIR="$CMAKE_SOURCE_DIR/build"

# Define the specific test to run
TEST_NAME="InstallPackageInfo"

# Navigate to the build directory
cd "$CMAKE_BUILD_DIR"

# Launch GDB with the appropriate arguments for the test
gdb --args ./bin/cmake \
  "-DCMAKE_MODULE_PATH=$CMAKE_SOURCE_DIR/Tests/RunCMake" \
  "-DRunCMake_GENERATOR=Ninja" \
  "-DRunCMake_SOURCE_DIR=$CMAKE_SOURCE_DIR/Tests/RunCMake/$TEST_NAME" \
  "-DRunCMake_BINARY_DIR=$CMAKE_BUILD_DIR/Tests/RunCMake/$TEST_NAME" \
  "-P" "$CMAKE_SOURCE_DIR/Tests/RunCMake/RunCMakeTest.cmake"

Once GDB loads, you may set breakpoints (e.g., b cmInstallCommand) and then start the test by typing run.

Filtering Tests

Some test suites contain multiple sub-tests. To run only a specific one, you can use the RunCMake_TEST_FILTER environment variable.

For example, to run only the "Metadata" test within the InstallPackageInfo suite, you can set the variable before launching GDB:

RunCMake_TEST_FILTER="Metadata" gdb --args ...

Alternatively, you can set the environment variable from within the GDB session before running the test:

(gdb) set environment RunCMake_TEST_FILTER Metadata
(gdb) run

IDE Integration

You can also debug CMake tests directly from your IDE.

CLion

If you have configured GDB to auto-load local .gdbinit files as described above, CLion will automatically pick up the necessary settings.

A simple way to debug a test is to modify its CTest run configuration:

  1. Select the Test: In the "Run/Debug Configurations" dialog, find the CTest entry for your test (e.g., RunCMake.InstallPackageInfo).
  2. Add CTest Arguments: In the "CTest arguments" field, add --extra-verbose. This is helpful for debugging because it prints the exact command CTest uses to run the test.
  3. Set Working Directory: Ensure the "Working Directory" field is set to $CMakeCurrentLocalGenerationDir$.

You can now set breakpoints in your code and debug this configuration.

Visual Studio Code

Create a launch.json file in the .vscode directory of your CMake source folder with the following configuration. This configuration hardcodes the necessary GDB settings, so it does not depend on an external .gdbinit file.

{
 "version": "0.2.0",
 "configurations": [
   {
     "name": "Debug CMake Test",
     "type": "cppdbg",
     "request": "launch",
     "program": "${workspaceFolder}/build/bin/cmake",
     "args": [
       "-DCMAKE_MODULE_PATH=${workspaceFolder}/Tests/RunCMake",
       "-DRunCMake_GENERATOR=Ninja",
       "-DRunCMake_SOURCE_DIR=${workspaceFolder}/Tests/RunCMake/InstallPackageInfo",
       "-DRunCMake_BINARY_DIR=${workspaceFolder}/build/Tests/RunCMake/InstallPackageInfo",
       "-P",
       "${workspaceFolder}/Tests/RunCMake/RunCMakeTest.cmake"
     ],
     "stopAtEntry": false,
     "cwd": "${workspaceFolder}/build",
     "environment": [],
     "MIMode": "gdb",
     "setupCommands": [
       {
         "description": "Enable pretty-printing for gdb",
         "text": "-enable-pretty-printing",
         "ignoreFailures": true
       },
       {
         "description": "Follow child processes",
         "text": "set follow-fork-mode child",
         "ignoreFailures": true
       },
       {
         "description": "Don't stop the parent process",
         "text": "set non-stop on",
         "ignoreFailures": true
       }
     ]
   }
 ]
}

Note

Remember to change the test name (InstallPackageInfo) in the "args" section to the specific test you want to debug.