Skip to content

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>:

cmake --preset clang-debug && cmake --build --preset clang-debug && ctest --preset clang-debug

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.cpp beside Foo.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 dbtool and 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.