Skip to main content

Makefile Command Cheatsheet

Makefiles are the backbone of C/C++ projects and general build automation. GNU Make defines targets, dependencies, and command rules to enable incremental builds and task automation. This cheatsheet covers the most essential Makefile syntax and techniques — from basic variables and rules to advanced functions and conditionals — with practical examples.

Updated: 2026-07-16·40 commands

Quick Reference

TaskSyntax
Define a variableCC := gcc
Reference a variable$(CC) -o $@ $<
Write a compilation rule%.o: %.c ; $(CC) -c $< -o $@
Declare phony targets.PHONY: clean
Find all .c files$(wildcard src/*.c)
Pattern substitution on filenames$(patsubst %.c,%.o,$(wildcard *.c))
Conditional checkifeq ($(OS),Linux)

Variable Definition

``makefile # Assignment types CC = gcc # Recursively expanded (lazy evaluation) CC := gcc # Simply expanded (immediate evaluation, recommended) CC ?= gcc # Conditional (only if undefined) CFLAGS += -Wall -O2 # Append to existing value override CFLAGS += -g # Force override even if set on command line

# Variable references $(CC) -o hello hello.c # Standard reference ${CC} -o hello hello.c # Equivalent braced form $@ # Automatic: current target name $< # Automatic: first prerequisite $^ # Automatic: all prerequisites (deduplicated) $+ # Automatic: all prerequisites (with duplicates) $* # Automatic: pattern stem (% match) $? # Automatic: prerequisites newer than target

# Multi-line and shell variables define SCRIPT @echo "Running..." @echo "Done." endef

PATH := $(PATH):/usr/local/bin # Reference environment variable SHELL := /bin/bash # Specify shell (GNU make default: /bin/sh) `

Target Rules

`makefile # Basic rule target: prerequisites recipe # NOTE: Must use Tab indentation, not spaces

# Multi-dependency rule app: main.o utils.o $(CC) -o $@ $^ @echo "Build complete: $@" # @ prefix suppresses command echo

# Pattern rule (most commonly used) %.o: %.c $(CC) -c $(CFLAGS) $< -o $@

%.o: %.c %.h # Pattern rule with header dependency $(CC) -c $(CFLAGS) $< -o $@

# Multi-target rule obj1.o obj2.o: common.h # Multiple targets depending on the same file

# Static pattern rule objects = main.o utils.o $(objects): %.o: %.c $(CC) -c $(CFLAGS) $< -o $@

# Double-colon rule (each runs independently) clean:: rm -f *.o clean:: rm -f app # Multiple recipes — all are executed

# Implicit rule chain # make automatically knows how to build .o from .c (uses built-in rules) `

Function Usage

`makefile # File matching SOURCES := $(wildcard src/*.c) # Match all .c files OBJECTS := $(patsubst %.c,%.o,$(SOURCES)) # Replace .c with .o HEADERS := $(wildcard include/*.h) # Match header files OBJECTS := $(SOURCES:.c=.o) # Shorthand pattern substitution

# String operations FILES := foo.c bar.c baz.h $(filter %.c,$(FILES)) # Filter .c files $(filter-out %.h,$(FILES)) # Exclude .h files $(basename foo.c) # Filename without extension $(suffix foo.c) # File extension $(notdir src/main.c) # Filename part (strip directory) $(dir src/main.c) # Directory part

# List operations $(addprefix obj/,$(OBJECTS)) # Prefix each item $(addsuffix .bak,$(FILES)) # Suffix each item $(words $(FILES)) # Word count $(word 2,$(FILES)) # Get the 2nd word $(firstword $(FILES)) # Get the first word $(lastword $(FILES)) # Get the last word

# Looping and execution $(foreach src,$(SOURCES),$(info Processing $(src))) # Iterate over items

TAG := $(shell git describe --tags --always) # Execute shell command DATE := $(shell date +%Y-%m-%d) # Get current date $(shell mkdir -p build) # Create directory (at parse time) `

Conditionals

`makefile # Value comparison ifeq ($(CC),gcc) CFLAGS += -std=c11 endif

ifneq ($(shell uname),Linux) CFLAGS += -D_POSIX_C_SOURCE=200809L endif

# Variable definition check ifdef DEBUG CFLAGS += -g -O0 -DDEBUG LDFLAGS += -fsanitize=address endif

ifndef RELEASE CFLAGS += -Wall -Wextra endif

# Multi-way conditional ifeq ($(OS),Windows_NT) RM := del /Q EXT := .exe else ifeq ($(shell uname),Darwin) RM := rm -f EXT := else RM := rm -f EXT := endif

# $(if) function (evaluated during variable expansion) CFLAGS := $(if $(DEBUG),-g -O0,-O2) # Conditional value selection LIBDIR := $(if $(wildcard /usr/local/lib),/usr/local/lib,/usr/lib) `

Built-in Variables & Implicit Rules

`makefile # Common built-in variables CC := cc # C compiler CXX := g++ # C++ compiler AR := ar # Archiver CFLAGS := # C compiler flags CXXFLAGS := # C++ compiler flags LDFLAGS := # Linker flags LDLIBS := # Library linking (e.g. -lm) CPPFLAGS := # Preprocessor flags (e.g. -Iinclude) RM := rm -f # Remove command

# Built-in implicit rule examples # %.o: %.c — uses $(CC) $(CFLAGS) $(CPPFLAGS) -c -o $@ $< # %.o: %.cc — uses $(CXX) $(CXXFLAGS) $(CPPFLAGS) -c -o $@ $< # %: %.c — uses $(CC) $(LDFLAGS) $< $(LDLIBS) -o $@ # %: %.o — links .o files

# Override suffix list .SUFFIXES: # Clear suffix list .SUFFIXES: .c .o .h # Keep only needed suffixes

# Special variables $(MAKE) # make itself (for recursive make) $(MAKECMDGOALS) # Current command-line goals $(CURDIR) # Current working directory $(MAKEFLAGS) # Current make flags $(.VARIABLES) # All defined variables list $(.TARGETS) # All targets list `

Phony Targets & Best Practices

`makefile # Declare phony targets .PHONY: all clean install test help lint dist

# Default target (first one) all: app test # Executed when make is run without arguments

# Clean clean: $(RM) $(OBJECTS) $(TARGET) $(RM) -r build/

# Install install: app @mkdir -p $(DESTDIR)/usr/local/bin cp $< $(DESTDIR)/usr/local/bin/ @echo "Installed to $(DESTDIR)/usr/local/bin/"

# Test test: app ./app --test @echo "All tests passed!"

# Help help: @echo "Available targets:" @echo " all Build the project (default)" @echo " clean Remove build artifacts" @echo " install Install to \$$(DESTDIR)/usr/local/bin" @echo " test Run tests" @echo " lint Run code linting" @echo " dist Create distribution archive"

# Linting lint: $(info Running linter...) $(shell command -v cppcheck >/dev/null || (echo "cppcheck not found" && exit 1)) cppcheck --enable=all $(SOURCES)

# Distribution archive dist: $(info Creating distribution...) tar -czf $(TARGET)-$(TAG).tar.gz $(SOURCES) $(HEADERS) Makefile

# Best practice Makefile template CURRENT_DIR := $(notdir $(CURDIR)) TARGET := $(CURRENT_DIR) TAG := $(shell git describe --tags --always 2>/dev/null || echo "dev")

SOURCES := $(wildcard src/*.c) OBJECTS := $(SOURCES:.c=.o) HEADERS := $(wildcard include/*.h) CFLAGS := -Wall -Wextra -std=c11 -Iinclude LDFLAGS := LDLIBS := -lm

$(TARGET): $(OBJECTS) $(CC) $(LDFLAGS) -o $@ $^ $(LDLIBS)

%.o: %.c $(HEADERS) $(CC) -c $(CFLAGS) -o $@ $<

.PHONY: all clean install test help all: $(TARGET) clean: ; $(RM) $(OBJECTS) $(TARGET) ``

Variables(7)

CommandLevel
VAR := value
Simply expanded variable assignment (immediate evaluation, recommended)
Basic
VAR = value
Recursively expanded variable assignment (lazy evaluation)
Basic
VAR ?= value
Conditional assignment (assign only if variable is undefined)
Intermediate
VAR += value
Append value to an existing variable
Basic
override VAR += value
Force variable override even if specified on the command line
Intermediate
$(VAR) or ${VAR}
Reference a variable value
Basic
define VAR ... endef
Define a multi-line variable (useful for complex recipes)
Intermediate

Targets(6)

CommandLevel
target: prerequisites recipe
Basic target rule with prerequisites and recipe
Basic
app: main.o utils.o $(CC) -o $@ $^
Compilation rule with multiple dependencies
Basic
%.o: %.c $(CC) -c $< -o $@
Pattern rule — compile .c files into .o files
Intermediate
$(objects): %.o: %.c $(CC) -c $< -o $@
Static pattern rule — apply pattern only to a specific file list
Intermediate
target:: prerequisites
Double-colon rule (each recipe runs independently)
Expert
@echo 'Building...'
Silent command execution (@ prefix suppresses command echo)
Basic

Functions(7)

CommandLevel
$(wildcard pattern)
Match the list of actually existing files by pattern
Basic
$(patsubst %.c,%.o,$(SOURCES))
Pattern string substitution (replace .c with .o)
Intermediate
$(shell command)
Execute a shell command and return its output
Intermediate
$(filter pattern,text)
Filter text matching a pattern from a list
Intermediate
$(foreach var,list,text)
Iterate over a list and expand text for each item
Intermediate
$(addprefix prefix,names)
Prepend a prefix to each item in a list
Intermediate
$(notdir path)
Extract the filename portion from a path
Basic

Conditionals(6)

CommandLevel
ifeq (arg1, arg2) ... endif
Conditional comparison — test if two values are equal
Basic
ifneq (arg1, arg2) ... endif
Conditional comparison — test if two values are not equal
Basic
ifdef VAR ... endif
Check if a variable is defined
Basic
ifndef VAR ... endif
Check if a variable is not defined
Basic
ifeq ... else ifeq ... else ... endif
Multi-way conditional branching
Intermediate
$(if condition,then-part,else-part)
$(if) function — conditional value selection during variable expansion
Intermediate

Built-ins(6)

CommandLevel
$(CC) $(CFLAGS) $(LDFLAGS) $(LDLIBS)
Common built-in compilation variables
Basic
$(MAKE)
The make command itself (for recursive make invocations)
Intermediate
$(MAKECMDGOALS)
List of goals specified on the current command line
Intermediate
$(CURDIR)
Absolute path of the current working directory
Basic
$(.VARIABLES)
List of all defined variables (useful for debugging)
Expert
$(MAKEFLAGS)
Current make flags variable
Intermediate

Phony Targets(8)

CommandLevel
.PHONY: target1 target2
Declare phony targets (do not represent actual files)
Basic
clean: rm -f *.o $(TARGET)
Clean target to remove build artifacts
Basic
all: target1 target2
Default target (the first target executed when make is run without arguments)
Basic
install: app cp $< $(DESTDIR)/usr/local/bin/
Install target — copy build artifacts to system directories
Intermediate
test: app ./app --test
Test target — run test cases
Basic
help: @echo 'Available targets...'
Help target — list all available targets with descriptions
Intermediate
$(info message)
Print debug information at parse time
Intermediate
$(error message)
Print an error at parse time and abort the build
Intermediate

FAQ

This cheatsheet is compiled from official tool documentation. Last updated: 2026-07-16.