C++ Project Layout
Goal of a Good Layout
A C++ project layout should answer four questions quickly: where are public headers, where are implementation files, where do tests live, and where does generated build output go? If the layout answers those questions, the build system becomes simpler and teammates can navigate the project without guessing.
Small Executable Layout
For a tiny project, keep it simple:
This is enough when there is only one executable and no reusable library code.
Reusable Library Layout
Once code is shared across files, split public headers from implementation files:
| Folder | Purpose |
|---|---|
include/ | Public headers that other targets are allowed to include. |
src/ | Implementation files, private headers, and executable entry points. |
tests/ | Test programs for the library or executable. |
examples/ | Small programs that demonstrate how the project should be used. |
build/ | Generated files from CMake, Ninja, Make, object files, and executables. This should be ignored by Git. |
Public vs Private Headers
Public headers are part of the interface. If another target includes them, changes to those headers can force wide recompilation. Private headers are implementation details and should stay near the source files that use them.
Naming Conventions
- Use one main type per header when possible:
vector2.hcontainsVector2. - Match source and header names:
vector2.hpairs withvector2.cpp. - Use a project prefix folder under
include/, for exampleinclude/math_demo/vector2.h. This avoids include-name collisions. - Keep generated build output out of the source tree by using
cmake -S . -B build.
What Comes Next
After the folders are clear, the next question is what goes inside a header. That is the topic of Header Files.