contributing.md
1 <a id="top"></a> 2 # Contributing to Catch2 3 4 **Contents**<br> 5 [Using Git(Hub)](#using-github)<br> 6 [Testing your changes](#testing-your-changes)<br> 7 [Writing documentation](#writing-documentation)<br> 8 [Writing code](#writing-code)<br> 9 [CoC](#coc)<br> 10 11 So you want to contribute something to Catch2? That's great! Whether it's 12 a bug fix, a new feature, support for additional compilers - or just 13 a fix to the documentation - all contributions are very welcome and very 14 much appreciated. Of course so are bug reports, other comments, and 15 questions, but generally it is a better idea to ask questions in our 16 [Discord](https://discord.gg/4CWS9zD), than in the issue tracker. 17 18 19 This page covers some guidelines and helpful tips for contributing 20 to the codebase itself. 21 22 ## Using Git(Hub) 23 24 Ongoing development happens in the `devel` branch for Catch2 v3, and in 25 `v2.x` for maintenance updates to the v2 versions. 26 27 Commits should be small and atomic. A commit is atomic when, after it is 28 applied, the codebase, tests and all, still works as expected. Small 29 commits are also preferred, as they make later operations with git history, 30 whether it is bisecting, reverting, or something else, easier. 31 32 _When submitting a pull request please do not include changes to the 33 amalgamated distribution files. This means do not include them in your 34 git commits!_ 35 36 When addressing review comments in a MR, please do not rebase/squash the 37 commits immediately. Doing so makes it harder to review the new changes, 38 slowing down the process of merging a MR. Instead, when addressing review 39 comments, you should append new commits to the branch and only squash 40 them into other commits when the MR is ready to be merged. We recommend 41 creating new commits with `git commit --fixup` (or `--squash`) and then 42 later squashing them with `git rebase --autosquash` to make things easier. 43 44 45 46 ## Testing your changes 47 48 _Note: Running Catch2's tests requires Python3_ 49 50 51 Catch2 has multiple layers of tests that are then run as part of our CI. 52 The most obvious one are the unit tests compiled into the `SelfTest` 53 binary. These are then used in "Approval tests", which run (almost) all 54 tests from `SelfTest` through a specific reporter and then compare the 55 generated output with a known good output ("Baseline"). By default, new 56 tests should be placed here. 57 58 To configure a Catch2 build with just the basic tests, use the `basic-tests` 59 preset, like so: 60 61 ``` 62 # Assuming you are in Catch2's root folder 63 64 cmake -B basic-test-build -S . -DCMAKE_BUILD_TYPE=Debug --preset basic-tests 65 ``` 66 67 However, not all tests can be written as plain unit tests. For example, 68 checking that Catch2 orders tests randomly when asked to, and that this 69 random ordering is subset-invariant, is better done as an integration 70 test using an external check script. Catch2 integration tests are written 71 using CTest, either as a direct command invocation + pass/fail regex, 72 or by delegating the check to a Python script. 73 74 Catch2 is slowly gaining more and more types of tests, currently Catch2 75 project also has buildable examples, "ExtraTests", and CMake config tests. 76 Examples present a small and self-contained snippets of code that 77 use Catch2's facilities for specific purpose. Currently they are assumed 78 passing if they compile. 79 80 ExtraTests then are expensive tests, that we do not want to run all the 81 time. This can be either because they take a long time to run, or because 82 they take a long time to compile, e.g. because they test compile time 83 configuration and require separate compilation. 84 85 Finally, CMake config tests test that you set Catch2's compile-time 86 configuration options through CMake, using CMake options of the same name. 87 88 These test categories can be enabled one by one, by passing 89 `-DCATCH_BUILD_EXAMPLES=ON`, `-DCATCH_BUILD_EXTRA_TESTS=ON`, and 90 `-DCATCH_ENABLE_CONFIGURE_TESTS=ON` when configuring the build. 91 92 Catch2 also provides a preset that promises to enable _all_ test types, 93 `all-tests`. 94 95 The snippet below will build & run all tests, in `Debug` compilation mode. 96 97 <!-- snippet: catch2-build-and-test --> 98 <a id='snippet-catch2-build-and-test'></a> 99 ```sh 100 # 1. Regenerate the amalgamated distribution (some tests are built against it) 101 ./tools/scripts/generateAmalgamatedFiles.py 102 103 # 2. Configure the full test build 104 cmake -B debug-build -S . -DCMAKE_BUILD_TYPE=Debug --preset all-tests 105 106 # 3. Run the actual build 107 cmake --build debug-build 108 109 # 4. Run the tests using CTest 110 cd debug-build 111 ctest -j 4 --output-on-failure -C Debug 112 ``` 113 <sup><a href='/tools/scripts/buildAndTest.sh#L6-L19' title='File snippet `catch2-build-and-test` was extracted from'>snippet source</a> | <a href='#snippet-catch2-build-and-test' title='Navigate to start of snippet `catch2-build-and-test`'>anchor</a></sup> 114 <!-- endSnippet --> 115 116 For convenience, the above commands are in the script `tools/scripts/buildAndTest.sh`, and can be run like this: 117 118 ```bash 119 cd Catch2 120 ./tools/scripts/buildAndTest.sh 121 ``` 122 123 A Windows version of the script is available at `tools\scripts\buildAndTest.cmd`. 124 125 If you added new tests, you will likely see `ApprovalTests` failure. 126 After you check that the output difference is expected, you should 127 run `tools/scripts/approve.py` to confirm them, and include these changes 128 in your commit. 129 130 131 ## Writing documentation 132 133 If you have added new feature to Catch2, it needs documentation, so that 134 other people can use it as well. This section collects some technical 135 information that you will need for updating Catch2's documentation, and 136 possibly some generic advise as well. 137 138 139 ### Technicalities 140 141 First, the technicalities: 142 143 * If you have introduced a new document, there is a simple template you 144 should use. It provides you with the top anchor mentioned to link to 145 (more below), and also with a backlink to the top of the documentation: 146 ```markdown 147 <a id="top"></a> 148 # Cool feature 149 150 > [Introduced](https://github.com/catchorg/Catch2/pull/123456) in Catch2 X.Y.Z 151 152 Text that explains how to use the cool feature. 153 154 155 --- 156 157 [Home](Readme.md#top) 158 ``` 159 160 * Crosslinks to different pages should target the `top` anchor, like this 161 `[link to contributing](contributing.md#top)`. 162 163 * We introduced version tags to the documentation, which show users in 164 which version a specific feature was introduced. This means that newly 165 written documentation should be tagged with a placeholder, that will 166 be replaced with the actual version upon release. There are 2 styles 167 of placeholders used through the documentation, you should pick one that 168 fits your text better (if in doubt, take a look at the existing version 169 tags for other features). 170 * `> [Introduced](link-to-issue-or-PR) in Catch2 X.Y.Z` - this 171 placeholder is usually used after a section heading 172 * `> X (Y and Z) was [introduced](link-to-issue-or-PR) in Catch2 X.Y.Z` 173 - this placeholder is used when you need to tag a subpart of something, 174 e.g. a list 175 176 * For pages with more than 4 subheadings, we provide a table of contents 177 (ToC) at the top of the page. Because GitHub markdown does not support 178 automatic generation of ToC, it has to be handled semi-manually. Thus, 179 if you've added a new subheading to some page, you should add it to the 180 ToC. This can be done either manually, or by running the 181 `updateDocumentToC.py` script in the `scripts/` folder. 182 183 ### Contents 184 185 Now, for some content tips: 186 187 * Usage examples are good. However, having large code snippets inline 188 can make the documentation less readable, and so the inline snippets 189 should be kept reasonably short. To provide more complex compilable 190 examples, consider adding new .cpp file to `examples/`. 191 192 * Don't be afraid to introduce new pages. The current documentation 193 tends towards long pages, but a lot of that is caused by legacy, and 194 we know that some of the pages are overly big and unfocused. 195 196 * When adding information to an existing page, please try to keep your 197 formatting, style and changes consistent with the rest of the page. 198 199 * Any documentation has multiple different audiences, that desire 200 different information from the text. The 3 basic user-types to try and 201 cover are: 202 * A beginner to Catch2, who requires closer guidance for the usage of Catch2. 203 * Advanced user of Catch2, who want to customize their usage. 204 * Experts, looking for full reference of Catch2's capabilities. 205 206 207 ## Writing code 208 209 If want to contribute code, this section contains some simple rules 210 and tips on things like code formatting, code constructions to avoid, 211 and so on. 212 213 ### C++ standard version 214 215 Catch2 currently targets C++14 as the minimum supported C++ version. 216 Features from higher language versions should be used only sparingly, 217 when the benefits from using them outweigh the maintenance overhead. 218 219 Example of good use of polyfilling features is our use of `conjunction`, 220 where if available we use `std::conjunction` and otherwise provide our 221 own implementation. The reason it is good is that the surface area for 222 maintenance is quite small, and `std::conjunction` can directly use 223 compiler built-ins, thus providing significant compilation benefits. 224 225 Example of bad use of polyfilling features would be to keep around two 226 sets of metaprogramming in the stringification implementation, once 227 using C++14 compliant TMP and once using C++17's `if constexpr`. While 228 the C++17 would provide significant compilation speedups, the maintenance 229 cost would be too high. 230 231 232 ### Formatting 233 234 To make code formatting simpler for the contributors, Catch2 provides 235 its own config for `clang-format`. However, because it is currently 236 impossible to replicate existing Catch2's formatting in clang-format, 237 using it to reformat a whole file would cause massive diffs. To keep 238 the size of your diffs reasonable, you should only use clang-format 239 on the newly changed code. 240 241 242 ### Code constructs to watch out for 243 244 This section is a (sadly incomplete) listing of various constructs that 245 are problematic and are not always caught by our CI infrastructure. 246 247 248 #### Naked exceptions and exceptions-related function 249 250 If you are throwing an exception, it should be done via `CATCH_ERROR` 251 or `CATCH_RUNTIME_ERROR` in `internal/catch_enforce.hpp`. These macros will handle 252 the differences between compilation with or without exceptions for you. 253 However, some platforms (IAR) also have problems with exceptions-related 254 functions, such as `std::current_exceptions`. We do not have IAR in our 255 CI, but luckily there should not be too many reasons to use these. 256 However, if you do, they should be kept behind a 257 `CATCH_CONFIG_DISABLE_EXCEPTIONS` macro. 258 259 260 #### Avoid `std::move` and `std::forward` 261 262 `std::move` and `std::forward` provide nice semantic name for a specific 263 `static_cast`. However, being function templates they have surprisingly 264 high cost during compilation, and can also have a negative performance 265 impact for low-optimization builds. 266 267 You should be using `CATCH_MOVE` and `CATCH_FORWARD` macros from 268 `internal/catch_move_and_forward.hpp` instead. They expand into the proper 269 `static_cast`, and avoid the overhead of `std::move` and `std::forward`. 270 271 272 #### Unqualified usage of functions from C's stdlib 273 274 If you are using a function from C's stdlib, please include the header 275 as `<cfoo>` and call the function qualified. The common knowledge that 276 there is no difference is wrong, QNX and VxWorks won't compile if you 277 include the header as `<cfoo>` and call the function unqualified. 278 279 280 #### User-Defined Literals (UDL) for Catch2' types 281 282 Due to messy standardese and ... not great ... implementation of 283 `-Wreserved-identifier` in Clang, avoid declaring UDLs as 284 ```cpp 285 Approx operator "" _a(long double); 286 ``` 287 and instead declare them as 288 ```cpp 289 Approx operator ""_a(long double); 290 ``` 291 292 Notice that the second version does not have a space between the `""` and 293 the literal suffix. 294 295 296 297 ### New source file template 298 299 If you are adding new source file, there is a template you should use. 300 Specifically, every source file should start with the licence header: 301 ```cpp 302 303 // Copyright Catch2 Authors 304 // Distributed under the Boost Software License, Version 1.0. 305 // (See accompanying file LICENSE.txt or copy at 306 // https://www.boost.org/LICENSE_1_0.txt) 307 308 // SPDX-License-Identifier: BSL-1.0 309 ``` 310 311 The include guards for header files should follow the pattern `{FILENAME}_INCLUDED`. 312 This means that for file `catch_matchers_foo.hpp`, the include guard should 313 be `CATCH_MATCHERS_FOO_HPP_INCLUDED`, for `catch_generators_bar.hpp`, the include 314 guard should be `CATCH_GENERATORS_BAR_HPP_INCLUDED`, and so on. 315 316 317 ### Adding new `CATCH_CONFIG` option 318 319 When adding new `CATCH_CONFIG` option, there are multiple places to edit: 320 * `CMake/CatchConfigOptions.cmake` - this is used to generate the 321 configuration options in CMake, so that CMake frontends know about them. 322 * `docs/configuration.md` - this is where the options are documented 323 * `src/catch2/catch_user_config.hpp.in` - this is template for generating 324 `catch_user_config.hpp` which contains the materialized configuration 325 * `BUILD.bazel` - Bazel does not have configuration support like CMake, 326 and all expansions need to be done manually 327 * other files as needed, e.g. `catch2/internal/catch_config_foo.hpp` 328 for the logic that guards the configuration 329 330 331 ## CoC 332 333 This project has a [CoC](../CODE_OF_CONDUCT.md). Please adhere to it 334 while contributing to Catch2. 335 336 ----------- 337 338 _This documentation will always be in-progress as new information comes 339 up, but we are trying to keep it as up to date as possible._ 340 341 --- 342 343 [Home](Readme.md#top)