Makefile Cheat Sheet

A Makefile is a build automation file used by make to define rules for compiling, building, and running projects efficiently.


Basic Structure

target: dependencies
<TAB> command

Example:

main:
	gcc main.c -o main

IMPORTANT

Commands MUST start with a TAB, not spaces.


Simple Example

all: build
 
build:
	gcc main.c utils.c -o app
 
clean:
	rm -f app

Usage:

make        # runs "all" by default
make build
make clean

Variables

Define reusable values.

CC = gcc
CFLAGS = -Wall -Wextra -O2
TARGET = app

Use them:

build:
	$(CC) $(CFLAGS) main.c -o $(TARGET)

Automatic Variables

VariableMeaning
$@Target name
$<First dependency
$^All dependencies

Example:

app: main.c utils.c
	$(CC) $^ -o $@

Equivalent to:

gcc main.c utils.c -o app

Pattern Rules

Compile many files automatically.

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

Explanation:

  • %.c → any C file

  • %.o → corresponding object file


Full Build Example

CC = gcc
CFLAGS = -Wall -Wextra -O2
SRC = main.c utils.c
OBJ = $(SRC:.c=.o)
 
app: $(OBJ)
	$(CC) $(OBJ) -o app
 
%.o: %.c
	$(CC) $(CFLAGS) -c $< -o $@
 
clean:
	rm -f $(OBJ) app

Phony Targets

Used for commands, not files.

.PHONY: clean run all

Example:

run:
	./app

Multiple Targets

all: build test
 
build:
	gcc main.c -o app
 
test:
	./app --test

Conditionals

ifeq ($(OS),Windows_NT)
	RM = del
else
	RM = rm -f
endif

Functions

String substitution

FILES = main.c utils.c
OBJ = $(FILES:.c=.o)

Wildcard

SRC = $(wildcard *.c)

Notdir

Remove directories:

SRC = src/main.c src/utils.c
FILES = $(notdir $(SRC))

Include Other Makefiles

include config.mk

Default Target

First target is default:

all:
	echo "default"

Or explicitly:

.DEFAULT_GOAL := all

Silent Commands

all:
	@echo "Building project"

@ prevents command echoing.


Export Variables

export PATH := $(PATH):/custom/bin

Recursive Make

make -C subdir

Debugging Makefiles

Print variable:

make -p

Dry run:

make -n

Verbose output:

make --debug

Common Build Flow

all: build run
 
build:
	gcc main.c -o app
 
run:
	./app
 
clean:
	rm -f app

Directory-Based Project Example

SRC = src
BIN = bin
CC = gcc
 
all:
	mkdir -p $(BIN)
	$(CC) $(SRC)/main.c -o $(BIN)/app
 
clean:
	rm -rf $(BIN)

Dependency Example

main.o: main.c main.h utils.h

Meaning:

  • rebuild main.o if any header changes

Recursive Pattern Build

SRCS = $(wildcard *.c)
OBJS = $(SRCS:.c=.o)
 
app: $(OBJS)
	$(CC) $^ -o $@

Key Concepts

  • Target → what you want to build

  • Dependency → what it needs

  • Recipe → commands to build it

  • Variables → reusable values

  • Pattern rules → generic compilation rules

  • Phony targets → commands like clean, run


Mental Model

file.c  → compile → file.o
file.o  → link    → executable
 
Make tracks timestamps:
If dependency is newer → rebuild target

Most Used Commands

make
make clean
make all
make run
make -j4
make -n
make -B

Parallel Build

make -j4

Builds using 4 threads (faster compilation).


Golden Rule

A good Makefile should:

  • avoid repetition
  • use variables
  • use pattern rules
  • include clean
  • be readable, not clever