← Back to Docs
RECIPE

Makefile Patterns

Reusable templates for C++ projects — from single-binary builds to multi-target libraries with automatic dependency tracking.

Minimal Single Binary

CXX      := clang++
CXXFLAGS := -std=c++20 -Wall -Wextra -O2
LDFLAGS  :=

SRCS := $(wildcard src/*.cpp)
OBJS := $(SRCS:.cpp=.o)
BIN  := build/nimbus

$(BIN): $(OBJS)
	mkdir -p build
	$(CXX) $(LDFLAGS) $^ -o $@

%.o: %.cpp
	$(CXX) $(CXXFLAGS) -c $< -o $@

.PHONY: clean
clean:
	rm -rf build

Automatic Dependency Generation

DEPDIR := .deps
DEPFLAGS = -MT $@ -MMD -MP -MF $(DEPDIR)/$*.d

%.o: %.cpp | $(DEPDIR)
	$(CXX) $(CXXFLAGS) $(DEPFLAGS) -c $< -o $@

$(DEPDIR):
	mkdir -p $@

-include $(OBJS:.o=.d)

Multi-Target Library

STATIC_LIB  := build/libnimbus.a
SHARED_LIB  := build/libnimbus.so

$(STATIC_LIB): $(OBJS)
	mkdir -p build
	ar rcs $@ $^

$(SHARED_LIB): CXXFLAGS += -fPIC
$(SHARED_LIB): $(OBJS)
	mkdir -p build
	$(CXX) -shared $(LDFLAGS) $^ -o $@

all: $(STATIC_LIB) $(SHARED_LIB)

Release vs Debug

BUILD ?= debug

ifeq ($(BUILD),release)
  CXXFLAGS += -O3 -DNDEBUG
  BIN := build/release/nimbus
else
  CXXFLAGS += -O0 -g -DDEBUG
  BIN := build/debug/nimbus
endif

$(BIN): $(OBJS)
	mkdir -p $(dir $@)
	$(CXX) $(LDFLAGS) $^ -o $@

Tip: Always use .PHONY for targets that don't produce files. Combine with -j$(nproc) for parallel builds.