Contributing to core-cpp¶
core-cpp is shared by six projects, so a change here reaches all of them. This page says what belongs in core-cpp, what a change must carry, and how pull requests are labelled. The C++ rules are in the C++ guidelines; the constraints that have each already been a bug are in the rulebook.
What belongs here¶
- Code at least two of the consuming projects need. A file moves into core-cpp when a second project needs it (the graduation rule), and it must carry no PUBLIC compile flag and no dependency beyond the standard library and Threads, unless it adds a row to the dependency table.
- Generic code only. Nothing specific to one consumer enters core-cpp: no terminal-emulator, shell, cache or disk-usage concept. A consumer adapts to core-cpp's API through its own code.
- Fixes to vendored copies go here first. A consumer never edits its copy of core-cpp; the fix lands here, is released, and the consumer moves its pin.
Toolchain¶
| Tool | Minimum |
|---|---|
| clang | 22 |
| GCC | 14 |
| AppleClang | Xcode 16 |
Visual Studio (cl, clang-cl) |
2022 |
| CMake | 3.25 |
| Ninja | any recent |
| Python | 3 |
| emsdk (WebAssembly only) | 3.1.56 |
Build with a preset, into out/build/<preset>:
On Windows, run from a Visual Studio developer shell and use cl-debug or clangcl-debug. The
building guide lists
every preset.
Formatting and static analysis¶
clang-format, clang-tidy and ruff are pinned to one PyPI release each, because successive LLVM releases format differently, an older clang-tidy is silent about newer checks, and ruff's formatter output changes between its releases too:
python scripts/tool-versions.py --install # the three pins, from .<tool>-version
python scripts/clang-format.py <paths> # format the files you touched
python scripts/clang-format.py --all --check # what CI runs
python scripts/python-style.py <paths> # format and lint the files you touched
python scripts/python-style.py --all --check # what CI runs
cmake --preset clang-tidy && cmake --build --preset clang-tidy
scripts/clang-format.py and scripts/python-style.py each refuse any build that is not the pinned
one. Never format with another version, and never silence a finding with NOLINT -- or with any
other language's suppression comment: fix it.
Both refuse a bare run, naming the files you touched or --all as the two ways to mean it. A
bare invocation used to rewrite the whole tree, which is exactly what the rule against formatting
a file somebody else is editing forbids; a default the tooling breaks is a rule that gets broken.
The Python wraps at the same column as the C++: ruff.toml's line-length is .clang-format's
ColumnLimit, so one number governs the repository. ruff.toml also states ruff's default lint
set (E4, E7, E9, F) rather than inheriting it, so a future ruff cannot widen or narrow
the gate by changing its mind about the default. Nothing stylistic is linted: layout is the
formatter's job. The linter never rewrites -- a finding is for a human to fix.
What a change carries¶
- Tests. New or changed behaviour has a test next to the code (
Foo_test.cppbesideFoo.cpp), and the test was seen to fail without the change. - Small, semantic commits, each one building and passing on its own, each message ending
with a
Signed-off-by:trailer (git commit -s). - A CHANGELOG entry under
[Unreleased]for anything a consumer can observe: public API, options, dependencies, behaviour. A breaking change goes under Breaking with a migration note. - Documentation for what the change affects: the module's page, the options page, and the rulebook when the change fixes something that was a bug.
- A "Consumer impact" section in the pull request, from the template: for each of contour,
endo, fastcached, tuidu, Lightweight's
dbtooland morph, what it must change, or "none". Grep their sources before changing a public signature.
Labels¶
Every pull request carries exactly one type/ label, which decides the section of the release
notes it appears in:
| Label | Means |
|---|---|
type/feature |
New capability, or a user-visible extension of one |
type/bug |
Behaves incorrectly against its stated contract |
type/perf |
Throughput, latency or footprint |
type/docs |
Documentation, the rulebook, comments |
type/chore |
Build, CI, dependencies, releases, repository hygiene |
Add breaking-change when a consumer must change code or build configuration, and one
module/<name> label per module touched: module/base, module/log, module/cli,
module/platform, module/async, module/net, module/tui, module/testing.
Versioning¶
core-cpp follows Semantic Versioning with vX.Y.Z tags. While the major version is 0, a minor
release may break the API, and each break is recorded under Breaking with a migration note;
a patch release never breaks. Consumers pin a tag, or temporarily a full commit SHA, never a
branch.
Reporting a security problem¶
Do not open a public issue; see the security policy.
License¶
core-cpp is licensed under the Apache License, Version 2.0. By contributing you agree that your contribution is licensed under the same terms.