Phase 4 — Build, Test, Tooling (Months 6–7, Weeks 21–26)

Your projects look amateur without this. A senior C++ engineer is judged as much by their CMakeLists.txt, their .github/workflows/ci.yml, and their sanitizer coverage as by the code itself. In studies, “I use CMake” means nothing — “I have a target-based CMake preset with Conan 2, sanitizer matrices in CI, and gtest+Google Benchmark wired” means you’ve done this before. Phase 4 is the boring, non-negotiable infrastructure that turns your side projects into artifacts you can put in front of a hiring committee at Meta, NVIDIA, Hudson River, Zoho ML platform, or any team that ships C++ to production.

You just spent five months getting fluent in the language and its performance model. Nothing in Phase 1–3 was “look, professional”. Everything here is. Two things happen at the end of Phase 4: (1) you own a reference C++20 project template — your personal starter kit that you’ll fork for every future project including all of Phase 5, and (2) you go back to your Phase 3 thread pool and rebuild it against that template, so you can point at one repo and say “this is how I ship C++”.

Why this phase matters more than it looks

Most self-taught C++ developers hit a ceiling here. They can write correct code, but they can’t:

  • Set up a project that a colleague can git clone && cmake --preset default && cmake --build --preset default and have it Just Work on both Linux and macOS.

  • Explain what PUBLIC vs PRIVATE vs INTERFACE actually does to the transitive property propagation graph.

  • Run their tests under ASan+UBSan by default in CI, and know why they can’t add MSan to the same build.

  • Write a benchmark::State loop that doesn’t get erased by the optimizer.

  • Debug a “works on my machine, breaks in CI” toolchain drift bug.

Every one of those failures reads on your GitHub in fifteen seconds. Fix them here, once, forever.

Exit criteria — you cannot leave Phase 4 until

  1. You own a public GitHub template repository (raghul-cpp-template or similar) that any C++ dev can fork.

  2. That template uses modern target-based CMake (CMake ≥ 3.28) with CMakePresets.json for at least debug, release, release-asan, release-ubsan, release-tsan.

  3. It builds cleanly with both Conan 2.x and vcpkg manifest mode on a single external dep (e.g. fmt or spdlog) — you have written both flavors and can pick either.

  4. It ships a GoogleTest suite discovered via gtest_discover_tests, plus one Catch2 v3 file so you know both.

  5. It ships a Google Benchmark suite with at least one meaningful BENCHMARK that uses benchmark::DoNotOptimize correctly.

  6. All four sanitizers (ASan, UBSan, TSan, MSan) are wired as CMake options; you can produce a single command to run each locally.

  7. .clang-tidy and .clang-format files are committed with Google or LLVM base + your justified overrides.

  8. GitHub Actions matrix: {ubuntu-24.04, macos-14} × {clang-18, gcc-13 on Linux; apple-clang on Mac} × {Debug, Release, Release+ASan+UBSan}, all green.

  9. A Dockerfile based on Ubuntu 24.04 with LLVM 18+, CMake 3.28+, Conan 2 produces the same green build inside a container.

  10. You have read and can navigate a real Bazel BUILD file (know it exists; know when Google/Databricks/Snowflake use it and why you probably don’t need to).

  11. Your Phase 3 thread pool (P3.2) is refactored on top of this template with gtest suite, benchmark suite, and sanitizers running in CI.

  12. Onboarding time for a new contributor to your template repo (based on the README alone) is under 5 minutes to first successful test run.

If any single item above is not true, you are not done with Phase 4. Do not proceed to Phase 5.

Week-by-week breakdown

Week

Focus

Deliverable

W21

Modern CMake deep dive. Targets, propagation, presets, FetchContent. Rebuild an old toy project purely target-based.

Working CMakeLists.txt for one binary + one library, no globals, no include_directories.

W22

Conan 2.x + vcpkg. Do the same dep (fmt) both ways. Read one real-world open source conanfile.py and one vcpkg.json.

Two branches of the same repo — conan-flavor, vcpkg-flavor — both green.

W23

Project P4.1: reference template. Assemble everything. gtest + Google Benchmark + sanitizers + .clang-tidy + .clang-format + Docker + GHA matrix + README.

Public template repo, CI green, README onboarding < 5 min.

W24

Sanitizers deep dive. Read the ASan/TSan design papers/blog posts (Google, LLVM docs). Reproduce a real heap-use-after-free, data race, integer overflow, use-of-uninitialized in tiny bugs, watch each sanitizer catch it.

Blog post or gist: “four sanitizers, four bugs, four reports.”

W25

clang-tidy + IWYU + static analysis pass. Turn on bugprone-*, modernize-*, performance-*, cppcoreguidelines-* (curated) on your template. Fix everything it finds.

Zero clang-tidy warnings on your template with your chosen ruleset.

W26

Project P4.2: refactor P3.2 thread pool on the template. gtest suite (unit + stress under TSan). Google Benchmark (throughput at 1/4/8/16 workers). CI matrix green.

Second polished repo referencing template patterns.

What most people get wrong

They copy-paste CMake from Stack Overflow forever, and never learn the target model. They think include_directories(...) at the top of the file is normal. They set CMAKE_CXX_FLAGS globally. They use file(GLOB ...) for sources (“but the docs tell you not to”). They add -Wall -Wextra to PUBLIC and wonder why downstream consumers of their library are forced to compile with -Werror. They write one test/main.cpp that dumps a hundred assert()s instead of using a real framework. Their CI has one job on ubuntu-latest and nothing else.

You are going to be different. The rule is: every property on a target has a scope — PRIVATE (this target only), PUBLIC (this target and things that link to it), INTERFACE (only things that link to it, not this target itself). If you can’t tell me which scope to use for target_include_directories on a header-only library, come back to 01_modern_cmake.md and read again.

Bazel is worth knowing exists. You are unlikely to use it in a Zoho ML platform role. You are much more likely to use CMake + Conan or CMake + vcpkg. Learn the primary stack cold, know Bazel exists so you’re not surprised in an study.

Files in this phase

  1. 01_modern_cmake.md — target-based CMake, propagation model, presets, FetchContent, exporting your library.

  2. 02_conan_and_vcpkg.md — both package managers, honest 2026 comparison.

  3. 03_testing_and_benchmarks.md — GoogleTest, Catch2 v3, Google Benchmark, nanobench.

  4. 04_sanitizers_and_static_analysis.md — ASan/UBSan/TSan/MSan + clang-tidy + clang-format + IWYU.

  5. 05_ci_and_docker.md — GitHub Actions matrices, caching, Dockerfile, Bazel primer.

  6. projects.md — P4.1 (template repo), P4.2 (thread pool refactor).


Nav: ← Phase 3 · Phase 5 → · Roadmap Home