Automatic variables: $@, $<, $^

Make · Practical · 10 min

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.o

Remember

  • $@ 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.

Check yourself

  1. In the rule lib.a: x.o y.o z.o, after only y.o changed, what is $? in the recipe?

Sign in to answer, see the explanations, and get this lesson back as a quick review later.

Official docs: www.gnu.org/software/make/manual/make.html#Automatic-Variables