1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
|
<a id="top"></a>
> **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 (`<Progmasoft/Catch3/TestMacros.hpp>`, `find_package(Catch3)`, `Catch3::Catch3WithMain`). See [Catch3 additions](progmasoft-catch3.md) for Progmasoft APIs.
# CMake integration
**Contents**<br>
[CMake targets](#cmake-targets)<br>
[Automatic test registration](#automatic-test-registration)<br>
[CMake project options](#cmake-project-options)<br>
[`CATCH_CONFIG_*` customization options in CMake](#catch_config_-customization-options-in-cmake)<br>
[Using Catch3 from a checkout](#using-catch3-from-a-checkout)<br>
[Using an installed Catch3 package](#using-an-installed-catch3-package)<br>
[Catch3 next to Catch2](#catch3-next-to-catch2)<br>
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.
<a id="catch3_discover_tests"></a>
### `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 <POST_BUILD|PRE_TEST>]
[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 `<target>_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=<file>` and `json`
passes `--json=<file>` 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<test_name>`.
* `OUTPUT_SUFFIX suffix`
May be used in conjunction with `OUTPUT_DIR`.
If specified, `suffix` is added to each output file name, like so
`dir/<test_name>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)
|