Pattern rules define a generic recipe for a class of targets. Instead of writing a rule for each .o file, write one pattern rule that matches all of them.
%.o: %.c gcc -c -o $@ $<
The % is a wildcard. This rule matches main.o (from main.c), util.o (from util.c), etc. $@ is the target (e.g., main.o), $< is the prerequisite (e.g., main.c).
Using pattern rules:
%.o: %.c gcc $(CFLAGS) -c -o $@ $< app: main.o util.o helper.o gcc -o app $^ clean: rm -f *.o app
Make automatically applies the %.o: %.c rule to build any .o file from its corresponding .c file. No need to list every file individually.
Multiple patterns:
%.o: %.c gcc -c -o $@ $< %.so: %.c gcc -fPIC -shared -o $@ $<
The first rule builds .o files, the second builds shared libraries (.so). Make chooses the appropriate rule based on the target.
Chained patterns: Make chains pattern rules automatically. If app needs main.o, and main.o can be built from main.c (which exists), Make chains the rules:
app: main.o gcc -o app main.o main.o: main.c gcc -c -o main.o main.c
This is equivalent to explicitly listing the prerequisites. Make infers the dependency.
Suffix rules (old style):
.c.o: gcc -c $<
This is an older syntax for the same pattern rule. Avoid in new Makefiles; use %.o: %.c instead. It's clearer and more flexible.
Modifying implicit rules:
Make has built-in implicit rules. You can add prerequisites or override flags:
CFLAGS = -O3 -Wall CXXFLAGS = -O3 -Wall -std=c++17 # Use the built-in %.o: %.c rule, but with our CFLAGS
The built-in rules use $(CFLAGS) and $(CXXFLAGS), so setting these variables affects all compilation.
Disabling patterns:
%.o: %.c @echo "Not using pattern rules" gcc -c -o $@ $< main.o: main.c helper.c gcc -c -o main.o main.c helper.c # explicit rule (overrides pattern)
Explicit rules take precedence over pattern rules. Use this for special cases.