How to Integrate Catch2 with CMake: Complete Build Target Guide

To integrate Catch2 with CMake, locate the package using find_package, add_subdirectory, or FetchContent, then link your test executable against the exported targets Catch2::Catch2 or Catch2::Catch2WithMain defined in src/CMakeLists.txt, and finally invoke catch_discover_tests from extras/Catch.cmake to register tests with CTest automatically.

Catch2 is a modern, header-only C++ testing framework that provides first-class CMake support. Integrating Catch2 with CMake allows you to leverage exported build targets and automatic test discovery mechanisms that streamline the development workflow. The library defines its core interfaces in src/CMakeLists.txt and ships helper scripts in the extras directory to enable seamless CTest integration.

Understanding Catch2 CMake Targets

According to the source code in src/CMakeLists.txt, Catch2 exports two primary CMake targets for downstream consumption. The Catch2::Catch2 target provides the core testing framework headers and implementation, while Catch2::Catch2WithMain bundles the core library with a pre-written main() function. These targets handle include directories, compile features, and linking requirements automatically when linked to your test executables.

Three Methods to Include Catch2 in Your Project

Installing and Finding the Package

After building and installing Catch2 (e.g., sudo cmake --build build --target install), locate the package in your project's CMakeLists.txt:

cmake_minimum_required(VERSION 3.16)
project(MyTests LANGUAGES CXX)

find_package(Catch2 3 REQUIRED)
add_executable(tests test.cpp)
target_link_libraries(tests PRIVATE Catch2::Catch2WithMain)

If you require custom initialization logic, link against Catch2::Catch2 instead and provide your own main() implementation.

Embedding via add_subdirectory

When vendoring Catch2 within your repository (e.g., under lib/Catch2), simply add the subdirectory:

add_subdirectory(lib/Catch2)
add_executable(tests test.cpp)
target_link_libraries(tests PRIVATE Catch2::Catch2WithMain)

This approach uses the same target names as the installed package, making it easy to switch between installation methods without modifying target linkage.

Fetching with FetchContent

For automatic acquisition at configure time, use CMake's FetchContent module:

include(FetchContent)
FetchContent_Declare(
  Catch2
  GIT_REPOSITORY https://github.com/catchorg/Catch2.git
  GIT_TAG v3.8.1
)
FetchContent_MakeAvailable(Catch2)

add_executable(tests test.cpp)
target_link_libraries(tests PRIVATE Catch2::Catch2WithMain)

Automatic Test Discovery with CTest

Catch2 provides the catch_discover_tests function in extras/Catch.cmake to automatically parse test executables and register individual tests with CTest. This script utilizes extras/CatchAddTests.cmake as a helper implementation to process the --list-tests output.

To enable automatic discovery:

include(CTest)
list(APPEND CMAKE_MODULE_PATH ${Catch2_SOURCE_DIR}/extras)
include(Catch)

add_executable(my_test test.cpp)
target_link_libraries(my_test PRIVATE Catch2::Catch2)
catch_discover_tests(my_test)

When using FetchContent, you must explicitly add the source directory to the module path before including the helper script:

list(APPEND CMAKE_MODULE_PATH ${catch2_SOURCE_DIR}/extras)
include(Catch)
catch_discover_tests(my_test)

Building and Running Tests with Make

Once configured, build your project using standard CMake workflows:

cmake -B build -S .
cmake --build build

Execute tests through CTest using either ctest directly or the make test alias:

cd build
make test

# or

ctest --output-on-failure

Summary

  • Catch2 exports two CMake targets from src/CMakeLists.txt: Catch2::Catch2 (core only) and Catch2::Catch2WithMain (including default main).
  • Integration methods include find_package for system installations, add_subdirectory for vendored code, and FetchContent for automatic downloading.
  • Test discovery requires including extras/Catch.cmake and calling catch_discover_tests, which parses --list-tests output to populate CTest.
  • FetchContent users must manually prepend ${catch2_SOURCE_DIR}/extras to CMAKE_MODULE_PATH to locate helper scripts.
  • Build workflow follows standard CMake patterns: configure, build with cmake --build, then test with make test or ctest.

Frequently Asked Questions

What is the difference between Catch2::Catch2 and Catch2::Catch2WithMain?

Catch2::Catch2 links only the core testing framework, requiring you to define your own main() function. Catch2::Catch2WithMain includes the core library plus a default implementation that handles command-line arguments and test execution, suitable for most projects that do not need custom initialization.

How do I use catch_discover_tests when Fetching Catch2?

When using FetchContent_MakeAvailable(Catch2), the extras directory is not automatically on CMake's module path. You must append ${catch2_SOURCE_DIR}/extras to CMAKE_MODULE_PATH before calling include(Catch) to make the catch_discover_tests function available.

Can I integrate Catch2 without installing it system-wide?

Yes. Use either add_subdirectory(path/to/Catch2) for vendored dependencies, or FetchContent_Declare to download the source at configure time. Both methods expose the same Catch2::Catch2 and Catch2::Catch2WithMain targets without requiring a system-wide installation.

How do I install the CMake helper scripts for catch_discover_tests?

Set the CATCH_INSTALL_EXTRAS option to ON when building and installing Catch2 (e.g., cmake -DCATCH_INSTALL_EXTRAS=ON --build build --target install). This installs extras/Catch.cmake and related files to your CMake package directory, making them available via find_package without manually specifying the source path.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →