C β€” Makefile
C β€” Makefile

C β€” Makefile

Created on:
Team Size: 1
Tool Used: C/GCC/Makefile

A Makefile automates compilation. Instead of retyping gcc commands every time, you run make and the build system figures out what needs to be rebuilt.

A Minimal Makefile

NAME    = my_program
CC      = gcc
CFLAGS  = -Wall -Wextra -Werror
SRCS    = main.c utils.c
OBJS    = $(SRCS:.c=.o)

all: $(NAME)

$(NAME): $(OBJS)
	$(CC) $(CFLAGS) $(OBJS) -o $(NAME)

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

clean:
	rm -f $(OBJS)

fclean: clean
	rm -f $(NAME)

re: fclean all

.PHONY: all clean fclean re

How It Works

Variables

NAME    = my_program          # output binary name
CC      = gcc                 # compiler
CFLAGS  = -Wall -Wextra -Werror  # compiler flags
SRCS    = main.c utils.c      # source files
OBJS    = $(SRCS:.c=.o)       # replace .c with .o automatically

$(VAR) expands a variable. $(SRCS:.c=.o) is a substitution reference β€” it produces main.o utils.o from main.c utils.c.

Rules

A rule has the form:

target: prerequisites
	recipe
  • target β€” the file to produce (or a phony label like clean)
  • prerequisites β€” files the target depends on; if any are newer, the recipe runs
  • recipe β€” shell commands to run (must be indented with a real tab, not spaces)

Pattern Rule

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

% is a wildcard. $< is the first prerequisite (the .c file), $@ is the target (the .o file). This single rule compiles every .c into its matching .o.

.PHONY

.PHONY: all clean fclean re

Tells make these targets are not real files. Without this, if a file named clean existed, make clean would do nothing.

Mandatory Rules

RuleEffect
make / make allcompile the program
make cleanremove .o object files
make fcleanremove .o files and the binary
make refull rebuild from scratch (fclean then all)

Every C project should have all four.

Incremental Compilation

make only recompiles files that changed. If you edit utils.c, only utils.o is rebuilt β€” main.o is untouched. This saves time on large projects.

Common Mistakes

Spaces instead of tabs β€” the recipe line must start with a tab character. Most editors show them the same but make will refuse:

Makefile:10: *** missing separator. Stop.

Forgetting fclean removes the binary β€” clean only removes .o files. fclean also removes $(NAME). Both are required.

Not listing all source files β€” if SRCS is incomplete, some files won’t compile and you’ll get linker errors about undefined symbols.

Quick Reference

SyntaxMeaning
$(VAR)expand variable
$(SRCS:.c=.o)substitution: replace .c with .o
$@the target of the current rule
$<the first prerequisite
%.o: %.cpattern rule matching any .c β†’ .o
.PHONYdeclare targets that are not files
-c flagcompile to .o without linking
© 2026 Samuel Styles