|
MyProject 1.0.0
My C++ Project
|
A C++23 template with C23 support built with CMake presets, Ninja, CTest, clang-format, clang-tidy, cppcheck and llvm-cov. Warnings, sanitizers and coverage instrumentation apply uniformly to the library, the executable and every test.
macOS-only by design: the presets pin /usr/bin/clang, /usr/bin/clang++ and CMAKE_OSX_SYSROOT, and tool discovery prefers Xcode's toolchain via xcrun. If Xcode lacks a tool such as clang-tidy, install it separately (for example, Homebrew LLVM). Put machine-specific overrides in CMakeUserPresets.json, which is gitignored.
make init rewrites the project name across CMakeLists.txt, README.md, CLAUDE.md and .vscode/. Then replace the placeholder greeting module with your own code.
Application logic belongs in the core library (<Project>_core), which both the executable and the tests link. Keeping main.cpp thin is what makes the code testable.
CMake enables C++23 and C23 with language extensions disabled. The sample src/main.cpp uses the C library in src/greeting.c; greeting.h uses extern "C" guards so both languages can include it. C and C++ tests exercise that shared interface. C++-only headers can use .hpp and normal C++ linkage.
Add production .c, .cc, .cpp or .cxx files explicitly to the core target in CMakeLists.txt. Test discovery and quality tools support all four extensions; formatting also covers .h, .hh, .hpp, .hxx, .inl and .tpp headers. Test filenames must have unique stems, such as test_greeting.c and test_greeting_cpp.cpp. C-only prototype warnings are restricted to C sources.
Tests use Unity, fetched automatically at configure time — a clean build needs network access. Create tests/test_<thing>.cpp (or .c for a C test):
It is globbed, built and registered with CTest automatically — no CMake edit needed. Common assertions are TEST_ASSERT_EQUAL_STRING, TEST_ASSERT_EQUAL_INT, TEST_ASSERT_TRUE, TEST_ASSERT_NULL and TEST_ASSERT_NOT_NULL; failures report both the expected and the actual value. Unity's full assertion reference is in its docs.
make cbuild builds the current CONFIG without reconfiguring; it is the primitive the other targets compose, and is what editor tasks and file watchers should call.
make install defaults to PREFIX=$HOME/.local, so it needs no sudo and puts the executable in ~/.local/bin. Pass PREFIX for anywhere else — a system-wide make install PREFIX=/usr/local needs sudo, since that tree is root-owned. The default applies to this Makefile only; CMAKE_INSTALL_PREFIX keeps CMake's usual /usr/local.
make uninstall reads the install_manifest.txt that cmake --install wrote under build/<config>/, so it needs the build directory the install came from. It deletes only the files listed there, never the directories that hold them. Note that the manifest records only the most recent install, so installing to two different prefixes from one build directory leaves the earlier copy orphaned.
make help lists every target with a one-line description.
CONFIG selects the preset: debug (default), release, relwithdebinfo, coverage. Each has an independent build directory under build/.
make qa only checks formatting; it never rewrites source files. Use make format to apply formatting intentionally.
make docs runs Doxygen and writes HTML to build/debug/docs/html/, using this README as the landing page. The Doxyfile is generated from CMake rather than checked in, so the project name keeps coming from the single project() call and make init needs no extra rewrite.
Document public declarations in include/ with @brief, @param and @return; see include/greeting.h for the expected style. docs is deliberately not part of make qa — an undocumented function warns, it does not block the build. To make it a hard gate, set DOXYGEN_WARN_AS_ERROR to FAIL_ON_WARNINGS in CMakeLists.txt.
On pushes to main, CI publishes the generated docs to GitHub Pages.
make qa is a hard gate. It fails on clang-tidy findings (--warnings-as-errors=*), on cppcheck findings (--error-exitcode=1), on compiler warnings (-Werror), and on sanitizer findings (-fno-sanitize-recover=all, so UBSan aborts rather than reporting and continuing). Debug builds run under AddressSanitizer and UBSan, tests included.
The same gate runs in CI on macos-latest for both debug and release.