# Projects with CMake and Package Managers — C++

Source: https://www.skillbyai.com/en/cpp/p-build

> Structure a C++ project and build it with CMake and dependencies.

## Builds beyond one file

Real C++ projects use a **build system**. **CMake** is the de-facto standard: a `CMakeLists.txt` describes **targets** (executables and libraries), their sources, include directories, compile features and dependencies, and CMake generates build files for **Ninja**, **Make** or IDEs such as Visual Studio and CLion. Modern CMake is **target-based**: use `target_include_directories`, `target_compile_features(app PRIVATE cxx_std_20)` and `target_link_libraries` rather than global settings. Separate the **build directory** from the source (`cmake -S . -B build`). For third-party libraries, use a package manager: **vcpkg** (from Microsoft) or **Conan**, or CMake's **FetchContent** for source dependencies. A typical layout has `include/` for public headers, `src/` for sources, `tests/` for unit tests (GoogleTest or Catch2) and `CMakeLists.txt` at the root. Add `compile_commands.json` generation for editor tooling (clangd), and run tests with **CTest** in CI.

## A typical project layout

Headers, sources and tests organised under one CMake project.

![A folder tree: a root folder with a config file and three subfolders, each containing a couple of file icons.](assets/figures/cpp/section-8-map.svg) — Figure 8.1 — include, src and tests directories built by CMake.

## A minimal modern CMakeLists.txt

A library, an executable and tests with GoogleTest via FetchContent.

```text
cmake_minimum_required(VERSION 3.25)
project(shop LANGUAGES CXX)

set(CMAKE_EXPORT_COMPILE_COMMANDS ON)

add_library(shop_core src/cart.cpp src/pricing.cpp)
target_include_directories(shop_core PUBLIC include)
target_compile_features(shop_core PUBLIC cxx_std_20)
target_compile_options(shop_core PRIVATE -Wall -Wextra -Wpedantic)

add_executable(shop src/main.cpp)
target_link_libraries(shop PRIVATE shop_core)

include(FetchContent)
FetchContent_Declare(googletest URL https://github.com/google/googletest/archive/refs/tags/v1.15.2.zip)
FetchContent_MakeAvailable(googletest)

enable_testing()
add_executable(shop_tests tests/cart_test.cpp)
target_link_libraries(shop_tests PRIVATE shop_core GTest::gtest_main)
include(GoogleTest)
gtest_discover_tests(shop_tests)

# build and test:
# cmake -S . -B build -G Ninja -DCMAKE_BUILD_TYPE=Debug
# cmake --build build && ctest --test-dir build
```

## Out-of-source builds

Always build in a separate directory such as `build/`. It keeps generated files out of version control and lets you have debug, release and sanitizer builds side by side.

**Quiz:** In modern CMake, how should you set include directories for a target?

- [ ] With global include_directories() for everything
- [ ] By copying headers into /usr/include
- [x] With target_include_directories() on the specific target
- [ ] CMake cannot handle include directories

*Answer:* With target_include_directories() on the specific target. Target-based commands keep settings attached to the targets that need them.
