Skip to content

Commit e067a22

Browse files
leftibotclaude
andcommitted
Fix #95: Add README_design.md documenting template design choices
New top-level doc explains the rationale behind the template's CMake layout, C++23 default, warning/sanitizer/hardening flags, CPM-based dependencies, dual top-level/subdir behavior, and the myproject_ENABLE_* knobs. Wording is kept short and specific so beginners and veterans can adapt the defaults knowingly. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent ec01c73 commit e067a22

1 file changed

Lines changed: 98 additions & 0 deletions

File tree

README_design.md

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
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

Comments
 (0)