This assumes that all source files (.h, .c) are located in one flat src directory.
Makefile automatic variables used:
$<: first item in the prerequisite list$@: name of the target$^: items in the prerequiste list (deduped)
- Collect all source files:
SOURCES=(wildcard src/*.c) - 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 $@
- Collect all objects produced by the above:
OBJS=(patsubst src/%.c,out/%.o,$(SOURCES)) - Link all the objects together to make the final executable:
out/my_prog: $(OBJS)
$(CC) $^ -o $@
- Add the
-MMDand-MPflags to the compiler command to produce dependency files (.d) on the first and subsequent compiles. - We can use these files to trigger re-compilation when headers change. Add the following
-includedirective 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