feat(skills): add coding-dev.md and per-language rules under code-languages/
Generic coding rules and preferences distilled from existing agent rule files, project AGENTS.md/.rules, and saved memories: - strictness maximal; suppressions must be reported to the user - never filter build/lint/test output through grep/tail/head - reuse > fork > self-implement; generic code becomes its own package - 1000-line file / 100-line function limits, split by concern - regression test every fixed bug; never test against real user data - events over polling; scope discipline; honest reporting Per-language: rust, js-typescript, bash, python, go, csharp-dotnet, c-cpp. Each extends coding-dev.md rather than repeating it. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
ba95f171b2
commit
57968904bf
9 files changed
+1499
-1
No files matched your search
@@ -0,0 +1,153 @@
|
||||
---
|
||||
name: c-cpp
|
||||
description: >-
|
||||
Use this skill when writing, building, or debugging C or C++ — including compiler warning
|
||||
configuration, sanitizers, modern C++ resource management, build systems (CMake/Meson),
|
||||
32-bit/cross builds, and FFI boundaries exposed to other languages.
|
||||
---
|
||||
|
||||
# C / C++ — Rules & Preferences
|
||||
|
||||
Extends [`../coding-dev.md`](../coding-dev.md). Everything there applies; this adds C/C++ specifics.
|
||||
|
||||
C and C++ are for the cases with no better option: existing codebases, hard real-time paths,
|
||||
and FFI boundaries. **For new standalone work, prefer Rust** — the memory-safety guarantees
|
||||
are worth more than the familiarity.
|
||||
|
||||
---
|
||||
|
||||
## 1. Warnings — Everything On, Errors
|
||||
|
||||
```cmake
|
||||
target_compile_options(mytarget PRIVATE
|
||||
-Wall -Wextra -Wpedantic -Werror
|
||||
-Wshadow -Wconversion -Wsign-conversion
|
||||
-Wnon-virtual-dtor -Wold-style-cast -Wcast-align
|
||||
-Wunused -Woverloaded-virtual -Wdouble-promotion
|
||||
-Wformat=2 -Wnull-dereference -Wimplicit-fallthrough
|
||||
)
|
||||
```
|
||||
|
||||
- **`-Werror` in the build gate.** `-Wconversion` and `-Wshadow` are noisy on first contact and
|
||||
catch real bugs — do not drop them because a legacy file complains; fix the file or scope the
|
||||
suppression to it.
|
||||
- Run **both** GCC and Clang where possible; each diagnoses things the other misses.
|
||||
- `clang-tidy` with `bugprone-*`, `cert-*`, `performance-*`, `modernize-*`.
|
||||
- `clang-format` with a committed `.clang-format`. No hand-formatting.
|
||||
|
||||
---
|
||||
|
||||
## 2. Sanitizers — Use Them
|
||||
|
||||
```bash
|
||||
cmake -DCMAKE_BUILD_TYPE=Debug \
|
||||
-DCMAKE_CXX_FLAGS="-fsanitize=address,undefined -fno-omit-frame-pointer"
|
||||
```
|
||||
|
||||
- **ASan + UBSan on every debug/test build.** They find the bugs that warnings cannot.
|
||||
- TSan for anything threaded (separate build — it is incompatible with ASan).
|
||||
- Valgrind when a sanitizer build is not possible.
|
||||
- **A sanitizer finding is a bug, not noise.** Fix it.
|
||||
|
||||
---
|
||||
|
||||
## 3. Resource Management (C++)
|
||||
|
||||
- **RAII for everything.** Every raw `new`/`delete`, `malloc`/`free`, `fopen`/`fclose`, and
|
||||
native handle pair is a leak waiting for an early return or a throw.
|
||||
- `std::unique_ptr` by default; `std::shared_ptr` only where ownership is genuinely shared.
|
||||
`std::weak_ptr` to break cycles.
|
||||
- **No owning raw pointers.** A raw pointer or reference in a signature means "borrowed,
|
||||
non-owning, outlives the call".
|
||||
- `std::string_view` / `std::span` for non-owning views — and never return one that outlives
|
||||
its backing storage.
|
||||
- **The Rule of Zero**: design so no destructor, copy, or move needs writing. If you must write
|
||||
one, write all five.
|
||||
- `constexpr`, `const`, and `noexcept` wherever they hold. `[[nodiscard]]` on anything whose
|
||||
return value must not be dropped.
|
||||
|
||||
---
|
||||
|
||||
## 4. C Specifics
|
||||
|
||||
- C17 or later unless the target forbids it.
|
||||
- **Check every allocation and every return value.** In C, unchecked returns are the primary
|
||||
bug source.
|
||||
- Fixed-width types from `<stdint.h>` (`uint32_t`), never bare `int` for anything with a
|
||||
defined width on the wire.
|
||||
- Always the bounded string functions (`snprintf`, `strncpy` with explicit termination); never
|
||||
`strcpy`, `sprintf`, `gets`.
|
||||
- `static` on every function and global not exported from the translation unit.
|
||||
- Prefer a struct-and-functions module boundary with an opaque pointer over exposing layout.
|
||||
|
||||
---
|
||||
|
||||
## 5. Build Systems
|
||||
|
||||
- **CMake** (3.20+, target-based) or **Meson** for new projects. Never a hand-written Makefile
|
||||
for anything non-trivial.
|
||||
- Target-based CMake only: `target_link_libraries`, `target_include_directories`,
|
||||
`target_compile_options`. **No directory-level `include_directories` or global
|
||||
`CMAKE_CXX_FLAGS` mutation.**
|
||||
- `PRIVATE` / `PUBLIC` / `INTERFACE` chosen deliberately — this is what keeps include leaks out
|
||||
of dependents.
|
||||
- **Register every new source file with the build system** in the same commit that adds it. A
|
||||
source file the build never compiles will sit there looking correct while every edit to it
|
||||
does nothing.
|
||||
- Vendor dependencies with `FetchContent` or submodules; document which and why.
|
||||
|
||||
---
|
||||
|
||||
## 6. Cross & Multi-Arch Builds
|
||||
|
||||
- Keep 32-bit and 64-bit outputs in **separate build directories**; never reuse one.
|
||||
- **A component built for one architecture cannot load one built for another.** An
|
||||
`ELFCLASS64` / `ELFCLASS32` error means a loader path is reaching the wrong build — check the
|
||||
library search path, not the code.
|
||||
- When a build must match an already-installed runtime's version, **pin it explicitly** and
|
||||
note the constraint. A silently mismatched pair fails at load time with a message that
|
||||
points nowhere useful.
|
||||
- Record the exact toolchain and container used for a cross build. "It built on my machine" is
|
||||
not reproducible for native code.
|
||||
|
||||
---
|
||||
|
||||
## 7. FFI Boundaries
|
||||
|
||||
When exposing C/C++ to another language:
|
||||
|
||||
- `extern "C"` on the boundary, with a hand-written, stable, documented header.
|
||||
- **Ownership across the boundary must be explicit** — who allocates, who frees, and with which
|
||||
function. Provide a matching `free` for every allocation you hand out.
|
||||
- **Never let an exception cross an `extern "C"` boundary.** Catch everything at the edge and
|
||||
convert to an error code.
|
||||
- Bindings generated by a tool (`bindgen`, etc.) are regenerated, never hand-edited.
|
||||
- On the consuming side, keep all `unsafe`/unmanaged interop in **one thin wrapper module**
|
||||
that exposes a safe API — never scattered through call sites.
|
||||
|
||||
> [!WARNING]
|
||||
> **Binding crates/packages that reach into a library's struct fields break when that library
|
||||
> makes the struct opaque.** Pin to a binding version that matches the installed library
|
||||
> generation, and note the constraint where someone will read it before bumping.
|
||||
|
||||
---
|
||||
|
||||
## 8. Testing & Debugging
|
||||
|
||||
- GoogleTest or Catch2; CTest integration so `ctest` runs the suite.
|
||||
- **Regression test every fixed bug.**
|
||||
- Debug builds keep frame pointers (`-fno-omit-frame-pointer`) so stack traces are usable.
|
||||
- `-g` even in release builds; ship separate debug symbols rather than none.
|
||||
- **Record dead ends in the project's notes**, especially for native debugging — the
|
||||
investigation that ruled something out is expensive and will otherwise be repeated. Note
|
||||
what did *not* work alongside what did.
|
||||
- When a binary search through a packed/embedded blob finds nothing, that is not evidence the
|
||||
content is absent — packed asset formats defeat naive string searches. Re-check without
|
||||
anchoring before concluding.
|
||||
|
||||
---
|
||||
|
||||
## 9. Related
|
||||
- [`../coding-dev.md`](../coding-dev.md) — the general rules this extends.
|
||||
- [`rust.md`](./rust.md) — the preferred language for new native work, and the usual consumer
|
||||
of these FFI boundaries.
|
||||
Reference in new issue
Block a user