Search code examples
c++cmakecatch-unit-test

CMake: How to reuse the same test_main.cpp for each test


I would like to use the test framework Catch2 in a monorepo in which there will be many components, each with their own tests. I'd like to use CMake to define all build targets.

Catch2 provides a simple means to generate a common main() function that will run all tests linked into the application. The source file (which I am calling test_main.cpp) is just these two lines:

#define CATCH_CONFIG_MAIN
#include "catch.hpp"

I'd like to have just one copy of test_main.cpp in my source tree, and refer to it from each component directory that has tests (which will end up being on the order of hundreds of directories).

I can see how to set up CMake to work if I duplicated the test_main.cpp so that a redundant copy existed in each directory with tests, but I haven't figured out how to have just one copy. Is there a simple trick I've overlooked?


Solution

  • Try integrating Catch2 as a CMake interface library in the following way:

    Add the single header file catch.hpp and test_main.cpp to a directory of their own (e.g., Catch2) along with the following CMakeLists.txt:

    add_library(catch INTERFACE)
    target_include_directories(catch INTERFACE $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>)
    target_sources(catch INTERFACE "${CMAKE_CURRENT_SOURCE_DIR}/test_main.cpp")
    

    The in your outermost CMakeLists.txt include Catch2 with add_subdirectory:

    add_subdirectory(Catch2)
    

    You can then set up test executables anywhere in the project in the following way:

    add_executable(
        project_tests EXCLUDE_FROM_ALL
        test_case1.cpp
        test_case2.cpp
        ...
    )
    
    target_link_libraries(project_tests catch)
    

    Because test_main.cpp has been added to catch as an interface source file, it will be compiled as part of the test executable.