| 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. |
| |
| .. _`CMake Development`: README.rst |
| |
| 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. |
| |
| .. code-block:: text |
| |
| 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: |
| |
| .. code-block:: bash |
| |
| # 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: |
| |
| .. code-block:: gdb |
| |
| # 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. |
| |
| .. code-block:: bash |
| |
| # 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: |
| |
| .. code-block:: bash |
| |
| RunCMake_TEST_FILTER="Metadata" gdb --args ... |
| |
| Alternatively, you can set the environment variable from within the |
| GDB session before running the test: |
| |
| .. code-block:: gdb-prompt |
| |
| (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: |
| |
| #. **Select the Test**: In the "Run/Debug Configurations" dialog, find the |
| ``CTest`` entry for your test (e.g., ``RunCMake.InstallPackageInfo``). |
| #. **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. |
| #. **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. |
| |
| .. code-block:: json |
| |
| { |
| "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. |