|
| 1 | +# Design Choices |
| 2 | + |
| 3 | +This template starts a C++ project with safe, modern defaults. Each choice |
| 4 | +below explains *why*, so you can keep it, swap it, or turn it off. |
| 5 | + |
| 6 | +## Goals |
| 7 | + |
| 8 | +1. Catch bugs at compile time, not in production. |
| 9 | +2. Stay portable across GCC, Clang, MSVC, and Emscripten. |
| 10 | +3. Work the same way as a top-level project or as a subdirectory dependency. |
| 11 | + |
| 12 | +## Layout |
| 13 | + |
| 14 | +| File | Role | |
| 15 | +| --- | --- | |
| 16 | +| `CMakeLists.txt` | Top-level wiring. | |
| 17 | +| `ProjectOptions.cmake` | All `myproject_*` options and setup macros. | |
| 18 | +| `Dependencies.cmake` | CPM package fetch, gated by `if(NOT TARGET ...)`. | |
| 19 | +| `cmake/*.cmake` | One concern per file (warnings, sanitizers, hardening, ...). | |
| 20 | + |
| 21 | +`PROJECT_IS_TOP_LEVEL` flips defaults: strict when you own the build, quiet |
| 22 | +when you are a dependency. |
| 23 | + |
| 24 | +## C++ standard |
| 25 | + |
| 26 | +C++23, set only if a parent project has not chosen one. `CMAKE_CXX_EXTENSIONS` |
| 27 | +is off so the standard flag is `-std=c++23`, not `-std=gnu++23`. This avoids |
| 28 | +`-Wpedantic` conflicts with precompiled headers. |
| 29 | + |
| 30 | +## Warnings |
| 31 | + |
| 32 | +`cmake/CompilerWarnings.cmake` enables a curated set per compiler — `/W4` |
| 33 | +plus extras on MSVC, and `-Wall -Wextra -Wshadow -Wconversion -Wpedantic ...` |
| 34 | +on GCC/Clang. Top-level builds add `-Werror` / `/WX`. Source: |
| 35 | +[cppbestpractices](https://github.com/lefticus/cppbestpractices/blob/master/02-Use_the_Tools_Available.md). |
| 36 | + |
| 37 | +## Sanitizers |
| 38 | + |
| 39 | +ASan and UBSan are on by default for top-level GCC/Clang builds when a link |
| 40 | +probe shows them working. TSan, LSan, and MSan are off — they conflict with |
| 41 | +each other and MSan needs an instrumented standard library. Emscripten and |
| 42 | +MSVC skip the sanitizer pass. |
| 43 | + |
| 44 | +## Hardening |
| 45 | + |
| 46 | +`cmake/Hardening.cmake` adds `_FORTIFY_SOURCE=3` (release builds), |
| 47 | +`_GLIBCXX_ASSERTIONS`, `-fstack-protector-strong`, `-fcf-protection`, and |
| 48 | +`-fstack-clash-protection` when supported. MSVC gets `/sdl /DYNAMICBASE |
| 49 | +/guard:cf /NXCOMPAT /CETCOMPAT`. When no full sanitizer is active, the UBSan |
| 50 | +minimal runtime is layered on top. |
| 51 | + |
| 52 | +## Static analysis |
| 53 | + |
| 54 | +clang-tidy and cppcheck run as part of the build, on by default at top level. |
| 55 | +They are separate options because one tool may not be installed in every |
| 56 | +environment. |
| 57 | + |
| 58 | +## Link-time optimization |
| 59 | + |
| 60 | +IPO/LTO is on by default at top level. It is gated through |
| 61 | +`check_ipo_supported` so unsupported toolchains skip it. |
| 62 | + |
| 63 | +## Dependencies |
| 64 | + |
| 65 | +[CPM](https://github.com/cpm-cmake/CPM.cmake) fetches sources at configure |
| 66 | +time. Each package is gated by `if(NOT TARGET ...)`, so a parent project can |
| 67 | +supply its own version. `SYSTEM YES` silences warnings from third-party |
| 68 | +headers. Default set: fmt, spdlog, Catch2, CLI11, FTXUI, lefticus/tools. |
| 69 | + |
| 70 | +## Testing |
| 71 | + |
| 72 | +* `test/tests.cpp` — Catch2 unit tests. |
| 73 | +* `test/constexpr_tests.cpp` — the same checks at compile time, so bugs |
| 74 | + become build errors. |
| 75 | +* `fuzz_test/` — libFuzzer harness, auto-enabled when ASan/TSan/UBSan and |
| 76 | + libFuzzer are all available. |
| 77 | + |
| 78 | +## Targets and packaging |
| 79 | + |
| 80 | +`myproject_options` and `myproject_warnings` are `INTERFACE` libraries that |
| 81 | +hold flags. Real targets link them to inherit the configuration without |
| 82 | +touching global state. `CPack` package names embed compiler, version, and |
| 83 | +short Git SHA, so a binary maps to one build. |
| 84 | + |
| 85 | +## Defaults for daily use |
| 86 | + |
| 87 | +The default build type is `RelWithDebInfo` — debuggable and fast. |
| 88 | +`compile_commands.json` is always exported, for editors and clang tooling. |
| 89 | + |
| 90 | +## Changing the defaults |
| 91 | + |
| 92 | +Every knob is a CMake option named `myproject_ENABLE_<feature>`. Flip it on |
| 93 | +the configure line, for example: |
| 94 | + |
| 95 | + cmake -B build -S . -Dmyproject_ENABLE_CLANG_TIDY=OFF |
| 96 | + |
| 97 | +The `myproject_` prefix is the placeholder the rename workflow replaces, so |
| 98 | +renaming the project is one search-and-replace. |
0 commit comments