Site

Tools — C++ Build Toolchain

Tutorial 2.0  •  C++ / Learn

2.0 What This Teaches

C++ has no single official toolchain - you choose a compiler and, for anything beyond a single file, a build system. This tutorial covers:

2.1 Choosing a Compiler

CompilerPlatformNotes
g++Linux, macOS, Windows (MinGW/MSYS2)Default on most Linux distros; install with your package manager
clang++Linux, macOS, WindowsExcellent error messages; default on macOS via Xcode tools
MSVC (cl)Windows onlyShips with Visual Studio; best Windows integration
All three implement the same standard. The command-line flags differ slightly; CMake abstracts them.

2.2 Single-File Compilation

g++     -std=c++17 -Wall -o program main.cpp
clang++ -std=c++17 -Wall -o program main.cpp
For a single source file this is enough. For projects with multiple files, a build system handles dependencies and recompilation.

2.3 Useful Compiler Flags

FlagMeaning
-std=c++17Enable C++17; use -std=c++20 for C++20
-WallEnable the most common warnings
-WextraAdditional warnings beyond -Wall
-O0No optimization (default; best for debugging)
-O2Optimize for speed (release builds)
-gInclude debug symbols for gdb/lldb
-o <name>Name the output executable

2.4 CMake Basics

CMake is a meta-build system: it generates Makefiles, Visual Studio projects, or Ninja build files from a single CMakeLists.txt. The same CMakeLists.txt works on every platform. Install CMake from cmake.org or via your package manager (apt install cmake, brew install cmake, winget install cmake).

2.5 A Minimal CMakeLists.txt

cmake_minimum_required(VERSION 3.15)
project(hello)

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

add_executable(hello src/hello.cpp)
Place this file at the project root. add_executable names the output binary and lists its source files. Add more .cpp files to that list as the project grows.

2.6 Build and Run with CMake

cmake -S . -B build        # configure: generate build files in build/
cmake --build build        # compile
./build/hello              # run (Linux/macOS)
.\build\Debug\hello.exe    # run (Windows)
-S . specifies the source directory (where CMakeLists.txt lives). -B build puts all generated files in a build/ subdirectory, keeping the source tree clean. Run cmake --build build again after any source change; CMake only recompiles what changed.

2.7 Multi-Directory Project with a Library

Real projects split code into a main executable and one or more libraries. CMake models this as separate targets connected with target_link_libraries. A typical layout:
myproject/
  CMakeLists.txt       <-- root: wires everything together
  src/
    main.cpp
  mylib/
    CMakeLists.txt     <-- library: compiled independently
    mylib.h
    mylib.cpp
The library's own CMakeLists.txt defines the target and exports its include path:
# mylib/CMakeLists.txt
add_library(mylib STATIC mylib.cpp)
target_include_directories(mylib PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
The root CMakeLists.txt pulls in the subdirectory and links the executable against it:
# CMakeLists.txt (root)
cmake_minimum_required(VERSION 3.15)
project(myproject)

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

add_subdirectory(mylib)          # process mylib/CMakeLists.txt

add_executable(myproject src/main.cpp)
target_link_libraries(myproject PRIVATE mylib)
The source files:
// mylib/mylib.h
#pragma once
int add(int a, int b);
int multiply(int a, int b);
// mylib/mylib.cpp
#include "mylib.h"
int add(int a, int b)      { return a + b; }
int multiply(int a, int b) { return a * b; }
// src/main.cpp
#include <iostream>
#include "mylib.h"

int main() {
    std::cout << add(3, 4)      << "\n";   // 7
    std::cout << multiply(3, 4) << "\n";   // 12
}
add_library(mylib STATIC ...) compiles mylib.cpp into a static archive (.a / .lib). target_include_directories(mylib PUBLIC ...) with PUBLIC means any target that links mylib automatically gets mylib/ on its include path — main.cpp can #include "mylib.h" without any extra flags. PRIVATE on target_link_libraries means the link dependency stays internal to myproject and is not exported further. Build and run exactly as before:
cmake -S . -B build
cmake --build build
./build/myproject

2.8 Exercise

Exercise
  • Compile hello.cpp directly with g++ or clang++ and run it.
  • Create a CMakeLists.txt for the same file, build it with CMake, and confirm the output is identical.
  • Add -Wall -Wextra to your direct compile command. Introduce a variable that is declared but never used and observe the warning.
  • Build the src + mylib layout from section 2.7. Add a third function subtract to the library, call it from main.cpp, and rebuild with cmake --build build. Confirm only the changed files are recompiled.

2.9 Key Terms

TermMeaning
g++GNU C++ compiler; standard on Linux
clang++LLVM C++ compiler; standard on macOS
MSVCMicrosoft Visual C++ compiler; Windows only
CMakeMeta-build system that generates platform-specific build files
CMakeLists.txtCMake configuration file describing the project
-std=c++17Compiler flag selecting the C++17 language standard
-WallEnable common compiler warnings
cmake -S . -B buildConfigure step: generate build files in build/
cmake --build buildBuild step: compile the project
add_subdirectoryProcesses a child CMakeLists.txt and adds its targets to the build
add_libraryDefines a library target; STATIC produces a .a/.lib archive
target_link_librariesLinks a target against another; PRIVATE keeps the dep internal
target_include_directoriesAdds include paths; PUBLIC propagates them to dependents