They remove repetition from recipes and are essential for the pattern rules every real Makefile uses.
Inside a recipe, make sets automatic variables describing the rule being run:
$@the target file name.$<the first prerequisite.$^all prerequisites, duplicates removed ($+keeps them, sometimes needed for link order).$?the prerequisites that are newer than the target.$*the stem matched by%in a pattern rule.$(@D)and$(@F)the directory and file parts of$@.
So a link rule becomes $(CC) $(LDFLAGS) -o $@ $^ $(LDLIBS), the same text whatever the target is called.
A common pattern is creating the output directory in the recipe: @mkdir -p $(@D) before writing into build/obj/x.o.
Automatic variables only have values inside recipes. Using $@ in a prerequisite list or a variable definition outside a recipe doesn't work (GNU make's secondary expansion is the rare exception).
The order of prerequisites matters for $<: put the main source file first and headers after it, so $< is the .c file you want to compile.
Example
CC := cc
CFLAGS := -Wall -O2
build/app: build/main.o build/util.o
$(CC) -o $@ $^
build/main.o: main.c util.h
@mkdir -p $(@D)
$(CC) $(CFLAGS) -c $< -o $@
build/util.o: util.c util.h
@mkdir -p $(@D)
$(CC) $(CFLAGS) -c $< -o $@
# $ make
# cc -Wall -O2 -c main.c -o build/main.o
# cc -Wall -O2 -c util.c -o build/util.o
# cc -o build/app build/main.o build/util.oRemember
- $@ target, $< first prerequisite, $^ all prerequisites
- $(@D) is the target's directory: mkdir -p $(@D) before writing
- Automatic variables only exist inside recipes
Watch out for
- Listing a header before the .c file, so $< passes the header to the compiler.