Multi-file C Makefile

2026/10/10

This assumes that all source files (.h, .c) are located in one flat src directory.

Makefile automatic variables used:

  1. Collect all source files: SOURCES=(wildcard src/*.c)
  2. We can produce a pattern-based rule that compiles all these source files into respective object files:
out/%.o: src/%.c
  $(CC) $(CFLAGS) -c $< -o $@
  1. Collect all objects produced by the above: OBJS=(patsubst src/%.c,out/%.o,$(SOURCES))
  2. Link all the objects together to make the final executable:
out/my_prog: $(OBJS)
  $(CC) $^ -o $@
  1. Add the -MMD and -MP flags to the compiler command to produce dependency files (.d) on the first and subsequent compiles.
  2. We can use these files to trigger re-compilation when headers change. Add the following -include directive after the linking rule:
DEPS=(patsubst out/%.o,out/%.d,$(OBJS))
-include $(DEPS)

Here is the final, simple Makefile:

CC=gcc
CFLAGS=-std=c17 -Wall -Wextra -Wpedantic -MMD -MP
OUT=out
SOURCES=$(wildcard src/*.c)
OBJS=$(patsubst src/%.c,$(OUT)/%.o,$(SOURCES))
DEPS=$(patsubst $(OUT)/%.o,$(OUT)/%.d,$(OBJS))

$(OUT)/thex: $(OBJS) | $(OUT)
	$(CC) $^ -o $@

-include $(DEPS)

$(OUT)/%.o: src/%.c | $(OUT)
	$(CC) $(CFLAGS) -c $< -o $@

$(OUT):
	mkdir -p $(OUT)

clean:
	rm -rf $(OUT)

.PHONY: clean