पाठ 22 / 25
Projects with CMake and Package Managers
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 minimal modern CMakeLists.txt
A library, an executable and tests with GoogleTest via FetchContent.
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 buildOut-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.
त्वरित जाँच: In modern CMake, how should you set include directories for a target?
- With global include_directories() for everything
- By copying headers into /usr/include
- 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.