--- name: gstackplusplus version: 2.0.0 description: | C++ build, test, and analysis toolkit for application, server, and embedded development. Builds with cmake, runs ctest, runs clang-tidy and cppcheck static analysis, runs AddressSanitizer and UndefinedBehaviorSanitizer, checks memory with valgrind. ~instant per command. Use when you need to build a project, run tests, check for memory leaks, or verify a feature works before shipping. allowed-tools: - Bash - Read - AskUserQuestion --- {{PREAMBLE}} # gstack++: C++ Build, Test & Analysis Toolkit Fast C++ development toolkit. Build → Test → Analyze, all from one place. Covers cmake/make/meson/bazel, GTest/Catch2/doctest, clang-tidy, cppcheck, AddressSanitizer, UndefinedBehaviorSanitizer, ThreadSanitizer, and valgrind. {{BROWSE_SETUP}} ## IMPORTANT - Use Bash directly with the detected cmake/build commands — no wrapper binary needed. - **Always rebuild** after changing headers or source files — incremental builds are fast. - **Sanitizer builds are separate** — maintain a sanitizer build dir alongside your release dir. - ASan and UBSan reports go to stderr; pipe with `2>&1` to capture them. ## Build Workflows ### Configure and build a project ```bash # Create and configure build directory (detect generator automatically) cmake -B build -DCMAKE_BUILD_TYPE=Debug \ -DCMAKE_CXX_FLAGS="-Wall -Wextra -Wpedantic" 2>&1 # Build (parallel — use nproc or fixed thread count) cmake --build build --parallel $(nproc) 2>&1 # Or with make directly if Makefiles are used make -C build -j$(nproc) 2>&1 ``` ### Build with sanitizers ```bash # AddressSanitizer + UndefinedBehaviorSanitizer build cmake -B build-asan -DCMAKE_BUILD_TYPE=Debug \ -DCMAKE_CXX_FLAGS="-fsanitize=address,undefined -fno-omit-frame-pointer -g" \ -DCMAKE_EXE_LINKER_FLAGS="-fsanitize=address,undefined" 2>&1 cmake --build build-asan --parallel $(nproc) 2>&1 # ThreadSanitizer build (mutually exclusive with ASan) cmake -B build-tsan -DCMAKE_BUILD_TYPE=Debug \ -DCMAKE_CXX_FLAGS="-fsanitize=thread -fno-omit-frame-pointer -g" \ -DCMAKE_EXE_LINKER_FLAGS="-fsanitize=thread" 2>&1 cmake --build build-tsan --parallel $(nproc) 2>&1 ``` ### Run tests ```bash # Run all tests with output on failure ctest --test-dir build --output-on-failure -j$(nproc) 2>&1 # Run a subset of tests by name pattern ctest --test-dir build -R "MyTest.*" --output-on-failure 2>&1 # Run with verbose output ctest --test-dir build -V 2>&1 # Run under sanitizers ASAN_OPTIONS=halt_on_error=0:detect_leaks=1 \ UBSAN_OPTIONS=print_stacktrace=1 \ ctest --test-dir build-asan --output-on-failure 2>&1 ``` ### Run static analysis ```bash # clang-tidy on specific files clang-tidy src/myfile.cpp -- -std=c++17 -Iinclude 2>&1 # clang-tidy on all changed files (vs base branch) git diff --name-only origin/main...HEAD | grep -E '\.(cpp|cc|cxx)$' | \ xargs -I{} clang-tidy {} -- -std=c++17 -Iinclude 2>&1 # cppcheck (whole project) cppcheck --enable=all --std=c++17 --error-exitcode=1 \ --suppress=missingIncludeSystem src/ include/ 2>&1 ``` ### Check for memory leaks with valgrind ```bash # Valgrind memcheck on a test binary valgrind --leak-check=full --error-exitcode=1 \ --suppressions=valgrind.supp \ ./build/test/my_test_binary 2>&1 # Or via ctest with valgrind ctest --test-dir build -T memcheck 2>&1 ``` ## Quick Verification Patterns ```bash # Does it build clean with warnings? cmake --build build 2>&1 | grep -E '^(error|warning):' | head -20 # Do all tests pass? ctest --test-dir build --output-on-failure 2>&1 | tail -5 # Any ASan errors? ASAN_OPTIONS=halt_on_error=0 ctest --test-dir build-asan -j1 2>&1 | \ grep -E '(ERROR|WARNING): AddressSanitizer' # Any clang-tidy warnings in changed files? git diff --name-only HEAD~1 | grep '\.cpp$' | \ xargs clang-tidy -- -std=c++17 -Iinclude 2>&1 | grep -c 'warning:' # Check test count ctest --test-dir build -N 2>&1 | tail -3 # List failing tests only ctest --test-dir build --output-on-failure 2>&1 | grep -E '^[0-9]+/[0-9]+ Test.*Failed' ``` ## Embedded-Specific Workflows ### Cross-compile for ARM embedded target ```bash # Configure with cross-compile toolchain cmake -B build-arm \ -DCMAKE_TOOLCHAIN_FILE=cmake/arm-none-eabi.cmake \ -DCMAKE_BUILD_TYPE=Release 2>&1 cmake --build build-arm 2>&1 # Check binary size (critical for embedded) arm-none-eabi-size build-arm/firmware.elf arm-none-eabi-nm --size-sort build-arm/firmware.elf | tail -20 # Run host-side unit tests (mock HAL, no target hardware needed) ctest --test-dir build --output-on-failure -L host 2>&1 ``` ### Verify ISR safety ```bash # Check for heap allocations in ISR-reachable code # (grep for new/malloc in files tagged for ISR context) grep -rn "new \|malloc\|calloc\|realloc" src/isr/ src/hal/ 2>&1 # Check for blocking calls in interrupt context grep -rn "sleep\|wait\|mutex_lock\|sem_wait" src/isr/ 2>&1 ``` ## Server-Specific Workflows ### ThreadSanitizer for data races ```bash # Build with TSan cmake -B build-tsan -DCMAKE_BUILD_TYPE=Debug \ -DCMAKE_CXX_FLAGS="-fsanitize=thread -g" \ -DCMAKE_EXE_LINKER_FLAGS="-fsanitize=thread" 2>&1 cmake --build build-tsan 2>&1 # Run concurrent tests under TSan TSAN_OPTIONS="halt_on_error=0:history_size=7" \ ctest --test-dir build-tsan -R ".*concurrent.*\|.*thread.*" \ --output-on-failure -j1 2>&1 ``` ### Connection and resource leak check ```bash # Run server tests with leak detection ASAN_OPTIONS=detect_leaks=1:halt_on_error=0 \ ./build-asan/test/server_test 2>&1 | grep -E '(leak|LEAK|lost bytes)' ``` ## Health Score Reference | Category | Weight | What's measured | |----------------|--------|-----------------| | Build | 25% | Clean compile, zero warnings with -Wall -Wextra | | Tests | 35% | All pass, coverage ≥80% of changed code | | Static Analysis| 20% | Zero clang-tidy/cppcheck findings in changed files | | Memory Safety | 20% | Zero ASan/UBSan/valgrind errors in test suite | **Score → Ship readiness:** - 90-100: Ship with confidence - 75-89: Ship with noted caveats - 50-74: Do not ship without fixing highs - <50: Do not ship ## Tips 1. **Incremental builds are fast.** `cmake --build build` only rebuilds changed TUs. Rebuild after every edit. 2. **Keep a parallel sanitizer build.** `build/` for speed, `build-asan/` always available for checking. 3. **Use `-j$(nproc)` everywhere.** Parallel builds and parallel ctest dramatically cut wall time. 4. **clang-tidy on changed files only.** Running on the whole project is slow; run on `git diff` files. 5. **ASan finds bugs valgrind misses.** Prefer ASan for development; valgrind for final leak audit. 6. **`ctest -R pattern` for focused runs.** No need to run 500 tests to verify one module. 7. **Check compiler warnings first.** Warnings are often latent bugs; fix them before running sanitizers. 8. **`cmake --build build --target help`** lists all available targets — useful for discovering test/bench targets. 9. **Triage flow.** Build fails → check CMake configure output. Tests fail → run with `--output-on-failure`. ASan fires → read the stack trace top-down.