> **Catch3 compatibility reference:** This page describes the test-writing API Catch3 shares with Catch2: the macros, such as `TEST_CASE` and `REQUIRE`, and the `Catch::` namespace keep Catch2's names. Headers and build names are Catch3's own (``, `find_package(Catch3)`, `Catch3::Catch3WithMain`). See [Catch3 additions](progmasoft-catch3.md) for Progmasoft APIs.
# CMake integration
**Contents**
[CMake targets](#cmake-targets)
[Automatic test registration](#automatic-test-registration)
[CMake project options](#cmake-project-options)
[`CATCH_CONFIG_*` customization options in CMake](#catch_config_-customization-options-in-cmake)
[Using Catch3 from a checkout](#using-catch3-from-a-checkout)
[Using an installed Catch3 package](#using-an-installed-catch3-package)
[Catch3 next to Catch2](#catch3-next-to-catch2)
Catch3's CMake package is `Catch3`. It exports two targets:
1. `Catch3::Catch3`, the library: the Catch2-compatible engine, the Catch3
runner, property testing and snapshots. It is C++17, and its headers
work in C++17 and later.
2. `Catch3::Catch3WithMain`, the library with the default `main`.
`Catch3.cmake` registers each `TEST_CASE` with CTest.
## CMake targets
Link `Catch3::Catch3WithMain` unless you provide a custom `main`. For an
installed Catch3:
```cmake
find_package(Catch3 0.3 CONFIG REQUIRED)
add_executable(tests test.cpp)
target_link_libraries(tests PRIVATE Catch3::Catch3WithMain)
add_executable(custom-main-tests test.cpp test-main.cpp)
target_link_libraries(custom-main-tests PRIVATE Catch3::Catch3)
```
If Catch3 is checked out in `external/catch3`, build it as a subdirectory:
```cmake
add_subdirectory(external/catch3)
add_executable(tests test.cpp)
target_link_libraries(tests PRIVATE Catch3::Catch3WithMain)
```
## Automatic test registration
Catch3 also contains two CMake scripts that register `TEST_CASE`s with
CTest. They are in the `extras` folder:
1) `Catch3.cmake` (and its dependency `Catch3AddTests.cmake`)
2) `Catch3ShardTests.cmake` (and its dependency `Catch3ShardTestsImpl.cmake`)
If Catch3 is installed, both can be used after `find_package(Catch3 REQUIRED)`.
Otherwise add the `extras` folder to your CMake module path. Their names, and
the names of the functions they define, start with `Catch3`/`catch3_`, so they
do not meet Catch2's `Catch.cmake` in a project that uses both.
### `Catch3.cmake` and `Catch3AddTests.cmake`
`Catch3.cmake` provides function `catch3_discover_tests` to get tests from
a target. This function works by running the resulting executable with
`--list=json`, and then reading the listing to find all existing tests.
#### Usage
```cmake
cmake_minimum_required(VERSION 3.16)
project(baz LANGUAGES CXX VERSION 0.0.1)
find_package(Catch3 REQUIRED)
add_executable(tests test.cpp)
target_link_libraries(tests PRIVATE Catch3::Catch3)
include(CTest)
include(Catch3)
catch3_discover_tests(tests)
```
When using `FetchContent`, `include(Catch3)` will fail unless
`CMAKE_MODULE_PATH` is explicitly updated to include the extras
directory.
```cmake
# ... FetchContent ...
#
list(APPEND CMAKE_MODULE_PATH ${catch3_SOURCE_DIR}/extras)
include(CTest)
include(Catch3)
catch3_discover_tests(tests)
```
#### Customization
`catch3_discover_tests` can be given several extra arguments:
```cmake
catch3_discover_tests(target
[TEST_SPEC arg1...]
[EXTRA_ARGS arg1...]
[WORKING_DIRECTORY dir]
[TEST_PREFIX prefix]
[TEST_SUFFIX suffix]
[PROPERTIES name1 value1...]
[TEST_LIST var]
[REPORTER reporter]
[OUTPUT_DIR dir]
[OUTPUT_PREFIX prefix]
[OUTPUT_SUFFIX suffix]
[DISCOVERY_MODE ]
[SKIP_IS_FAILURE]
[ADD_TAGS_AS_LABELS]
)
```
* `TEST_SPEC arg1...`
Specifies test cases, wildcarded test cases, tags and tag expressions to
pass to the Catch executable alongside the `--list-test-names-only` flag.
* `EXTRA_ARGS arg1...`
Any extra arguments to pass on the command line to each test case.
* `WORKING_DIRECTORY dir`
Specifies the directory in which to run the discovered test cases. If this
option is not provided, the current binary directory is used.
* `TEST_PREFIX prefix`
Specifies a _prefix_ to be added to the name of each discovered test case.
This can be useful when the same test executable is being used in multiple
calls to `catch3_discover_tests()`, with different `TEST_SPEC` or `EXTRA_ARGS`.
* `TEST_SUFFIX suffix`
Same as `TEST_PREFIX`, except it specific the _suffix_ for the test names.
Both `TEST_PREFIX` and `TEST_SUFFIX` can be specified at the same time.
* `PROPERTIES name1 value1...`
Specifies additional properties to be set on all tests discovered by this
invocation of `catch3_discover_tests`.
* `TEST_LIST var`
Make the list of tests available in the variable `var`, rather than the
default `_TESTS`. This can be useful when the same test
executable is being used in multiple calls to `catch3_discover_tests()`.
Note that this variable is only available in CTest.
* `REPORTER reporter`
Write a report of each test: `junit` passes `--junit=` and `json`
passes `--json=` to the test executable; `console` writes no file.
`junit` and `json` need `OUTPUT_DIR`.
* `OUTPUT_DIR dir`
The directory the reports of `REPORTER` go to, one file per test, named
after the test. Use it instead of `EXTRA_ARGS --junit=foo` so that tests
that run at the same time do not write the same file.
* `OUTPUT_PREFIX prefix`
May be used in conjunction with `OUTPUT_DIR`.
If specified, `prefix` is added to each output file name, like so
`dir/prefix`.
* `OUTPUT_SUFFIX suffix`
May be used in conjunction with `OUTPUT_DIR`.
If specified, `suffix` is added to each output file name, like so
`dir/suffix`. This can be used to add a file extension to
the output file name e.g. ".xml".
* `DISCOVERY_MODE mode`
If specified allows control over when test discovery is performed.
For a value of `POST_BUILD` (default) test discovery is performed at build time.
For a value of `PRE_TEST` test discovery is delayed until just prior to test
execution (useful e.g. in cross-compilation environments).
``DISCOVERY_MODE`` defaults to the value of the
``CMAKE_CATCH3_DISCOVER_TESTS_DISCOVERY_MODE`` variable if it is not passed when
calling ``catch3_discover_tests``. This provides a mechanism for globally
selecting a preferred test discovery behavior.
_Note that on Apple Silicon with the Xcode generator you must use `PRE_TEST`,
e.g. `catch3_discover_tests(tests DISCOVERY_MODE PRE_TEST)`. With the default
`POST_BUILD` mode the build fails with `Result: Subprocess killed`, because
macOS on Apple Silicon refuses to run unsigned binaries and Xcode code-signs
the test executable only **after** the post-build script that `POST_BUILD`
mode uses to run it for test discovery. `PRE_TEST` avoids this by delaying
discovery until test time, when the executable is already signed. The same
limitation affects CMake's `gtest_discover_tests`; see
[Catch2 #2411](https://github.com/catchorg/Catch2/issues/2411) and
[CMake #21845](https://gitlab.kitware.com/cmake/cmake/-/issues/21845)._
* `SKIP_IS_FAILURE`
Skipped tests will be marked as failed instead.
* `ADD_TAGS_AS_LABELS`
Add the tags from tests as labels to CTest.
### `Catch3ShardTests.cmake`
`Catch3ShardTests.cmake` provides a function
`catch3_add_sharded_tests(TEST_BINARY)` that splits tests from `TEST_BINARY`
into multiple shards. The tests in each shard and their order is randomized,
and the seed changes every invocation of CTest.
Currently there are 3 customization points for this script:
* SHARD_COUNT - number of shards to split target's tests into
* REPORTER - report options for the shards, such as --junit=FILE
* TEST_SPEC - test spec used for filtering tests
Example usage:
```
include(Catch3ShardTests)
catch3_add_sharded_tests(foo-tests
SHARD_COUNT 4
TEST_SPEC "A"
)
catch3_add_sharded_tests(tests
SHARD_COUNT 8
TEST_SPEC "B"
)
```
This registers total of 12 CTest tests (4 + 8 shards) to run shards
from `foo-tests` test binary, filtered by a test spec.
_Note that this script is currently a proof-of-concept for reseeding
shards per CTest run, and thus does not support (nor does it currently
aim to support) all customization points from
[`catch3_discover_tests`](#catch3_discover_tests)._
## CMake project options
Catch3's CMake project also provides some options for other projects
that consume it. These are:
* `BUILD_TESTING` -- When `ON` and the project is not used as a subproject,
Catch3's test binaries will be built. Defaults to `ON`.
* `CATCH3_INSTALL_DOCS` -- When `ON`, Catch3's documentation will be
included in the installation. Defaults to `ON`.
* `CATCH3_INSTALL_EXTRAS` -- When `ON`, Catch3's extras folder (the CMake
scripts mentioned above, debugger helpers) will be included in the
installation. Defaults to `ON`.
* `CATCH3_DEVELOPMENT_BUILD` -- When `ON`, configures the build for development
of Catch3. This means enabling test projects, warnings and so on.
Defaults to `OFF`.
Enabling `CATCH3_DEVELOPMENT_BUILD` also enables further configuration
customization options:
* `CATCH3_BUILD_TESTING` -- When `ON`, Catch3's SelfTest project will be
built. Defaults to `ON`. Note that Catch3 also obeys `BUILD_TESTING` CMake
variable, so _both_ of them need to be `ON` for the SelfTest to be built,
and either of them can be set to `OFF` to disable building SelfTest.
* `CATCH3_BUILD_EXAMPLES` -- When `ON`, Catch3's usage examples will be
built. Defaults to `OFF`.
* `CATCH3_BUILD_EXTRA_TESTS` -- When `ON`, Catch3's extra tests will be
built. Defaults to `OFF`.
* `CATCH3_BUILD_FUZZERS` -- When `ON`, Catch3's fuzzing entry points will
be built. Defaults to `OFF`.
* `CATCH3_ENABLE_WERROR` -- When `ON`, adds `-Werror` or equivalent flag
to the compilation. Defaults to `ON`.
* `CATCH3_BUILD_SURROGATES` -- When `ON`, each header of the engine will be
compiled separately to ensure that they are self-sufficient.
Defaults to `OFF`.
## `CATCH_CONFIG_*` customization options in CMake
Due to the new separate compilation model, all the options from the
[Compile-time configuration docs](configuration.md#top) can also be set
through Catch3's CMake. To set them, define the option you want as `ON`,
e.g. `-DCATCH_CONFIG_NOSTDOUT=ON`.
Note that setting the option to `OFF` doesn't disable it. To force disable
an option, you need to set the `_NO_` form of it to `ON`, e.g.
`-DCATCH_CONFIG_NO_COLOUR_WIN32=ON`.
To summarize the configuration option behaviour with an example:
| `-DCATCH_CONFIG_COLOUR_WIN32` | `-DCATCH_CONFIG_NO_COLOUR_WIN32` | Result |
|-------------------------------|----------------------------------|-------------|
| `ON` | `ON` | error |
| `ON` | `OFF` | force-on |
| `OFF` | `ON` | force-off |
| `OFF` | `OFF` | auto-detect |
## Using Catch3 from a checkout
Clone [Progmasoft/catch3](https://github.com/Progmasoft/catch3) and use
`add_subdirectory` as shown above. Keep it at a reviewed commit or release
tag in production builds.
## Using an installed Catch3 package
Configure and install Catch3 with CMake, then point `CMAKE_PREFIX_PATH` at
the install prefix and use `find_package(Catch3)`. The package installs
`lib/cmake/Catch3`, the headers below `include/Progmasoft`, and the
pkg-config files `catch3.pc` and `catch3-with-main.pc`.
## Catch3 next to Catch2
Catch3 is not Catch2's package: `find_package(Catch2)` finds Catch2, and
`find_package(Catch3)` finds Catch3. Their packages, targets, CMake scripts,
headers and pkg-config files have different names, so both can be installed
into the same prefix and used by different test binaries of one project. One
test binary links one of them: both define the `Catch::` namespace.
---
[Home](Readme.md#top)