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.