C++ Compilation & Build Systems
Compilation Stages
Preprocessor, compiler, assembler, linker
# Full compilation
g++ -std=c++20 -Wall -Wextra -o myapp main.cpp
# Stage by stage
g++ -E main.cpp > main.i # preprocess only (expand macros, includes)
g++ -S main.cpp # compile to assembly (main.s)
g++ -c main.cpp # compile to object file (main.o)
g++ main.o utils.o -o myapp # link object files into executable
The preprocessor handles #include and #define. The compiler produces assembly. The assembler produces object files. The linker combines them into an executable.
Compiler Flags
Essential flags for g and clang
# Standard version
g++ -std=c++17 main.cpp # C++17
g++ -std=c++20 main.cpp # C++20
# Warnings — always enable these
g++ -Wall -Wextra -Wpedantic -Werror main.cpp
# Optimization
g++ -O0 main.cpp # no optimization (debug)
g++ -O2 main.cpp # production optimization
g++ -O3 main.cpp # aggressive optimization
g++ -Os main.cpp # optimize for size
# Debug info
g++ -g main.cpp # generate debug symbols
g++ -g -fsanitize=address main.cpp # AddressSanitizer
# Multiple files
g++ -std=c++20 -Wall -o app main.cpp utils.cpp network.cpp
-Wall -Wextra -Wpedantic should be your default. -Werror treats warnings as errors — use it in CI.
Makefile
Build automation
CXX := g++
CXXFLAGS := -std=c++20 -Wall -Wextra -Wpedantic
LDFLAGS :=
SRCS := main.cpp utils.cpp network.cpp
OBJS := $(SRCS:.cpp=.o)
TARGET := netcheck
.PHONY: all clean
all: $(TARGET)
$(TARGET): $(OBJS)
$(CXX) $(LDFLAGS) -o $@ $^
%.o: %.cpp
$(CXX) $(CXXFLAGS) -c -o $@ $<
clean:
rm -f $(OBJS) $(TARGET)
$@ is the target, $^ is all prerequisites, $< is the first prerequisite. Tabs (not spaces) indent recipes.
CMake
The standard C++ build system generator
cmake_minimum_required(VERSION 3.20)
project(netcheck VERSION 1.0 LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
add_executable(netcheck
src/main.cpp
src/scanner.cpp
src/report.cpp
)
target_include_directories(netcheck PRIVATE include)
target_compile_options(netcheck PRIVATE -Wall -Wextra)
# External dependency
find_package(fmt REQUIRED)
target_link_libraries(netcheck PRIVATE fmt::fmt)
CMake build commands
mkdir build && cd build
cmake .. # configure
cmake --build . # build
cmake --build . --config Release # release build
ctest # run tests
Header Files
Header guards and forward declarations
// host.h — modern header guard
#pragma once
#include <string>
class Host {
public:
Host(std::string name, std::string ip, int port);
std::string address() const;
private:
std::string name_;
std::string ip_;
int port_;
};
// host.cpp — implementation
#include "host.h"
Host::Host(std::string name, std::string ip, int port)
: name_(std::move(name)), ip_(std::move(ip)), port_(port) {}
std::string Host::address() const {
return ip_ + ":" + std::to_string(port_);
}
#pragma once is the modern alternative to traditional #ifndef guards. Separate declaration (.h) from definition (.cpp) to manage compilation dependencies.
Static Analysis & Sanitizers
Catch bugs without running the code
# Clang-Tidy — static analysis
clang-tidy main.cpp -- -std=c++20
# AddressSanitizer — memory errors at runtime
g++ -g -fsanitize=address -o app main.cpp
./app # reports use-after-free, buffer overflow
# UndefinedBehaviorSanitizer
g++ -g -fsanitize=undefined -o app main.cpp
# ThreadSanitizer — data races
g++ -g -fsanitize=thread -o app main.cpp
Sanitizers add runtime checks with ~2x slowdown. Use them during development and in CI.