In a GNU make rule, what's the difference between $< and $^, and how do I refer to just the order-only prerequisites?
In a GNU make rule, what's the difference between $< and $^, and how do I refer to just the order-only prerequisites?
In a GNU make rule, what's the difference between $< and $^, and how do I refer to just the order-only prerequisites?
$< vs $^ vs $| in GNU make$< = the first prerequisite only. If the recipe came from an implicit rule, it's the first prerequisite that rule added.
$^ = the names of all the (normal) prerequisites, space-separated, with duplicates removed. If a file is listed as a prerequisite more than once, $^ includes it only once.
So in foo.o: foo.c util.h common.h, $< is foo.c while $^ is foo.c util.h common.h. That's exactly the common split for a compile rule: $< is the source file you feed to the compiler, $^ is everything the target depends on.
$|Order-only prerequisites are the ones listed after a pipe (|) in the prerequisite list. make ensures they exist before building the target, but won't rebuild the target just because they're newer (the typical use is a directory that must exist but whose timestamp shouldn't trigger rebuilds).
$^ deliberately does not contain order-only prerequisites. To refer to them, use $| — "the names of all the order-only prerequisites, with spaces between them."
build/foo.o: src/foo.c src/util.h | build
@echo "first prereq ($$<): $<" # src/foo.c
@echo "normal prereqs ($$^): $^" # src/foo.c src/util.h (no 'build')
@echo "order-only prereq ($$|): $|" # build
$(CC) -c $< -o $@
build:
mkdir -p build
Here build is an order-only prerequisite: it shows up in $| but never in $^ or $<.
$+ is like $^ but keeps duplicates in the order they were listed in the makefile. This matters mainly for linker commands where repeating a library name in a specific order is meaningful. (Also: $? = only the prerequisites newer than the target.)
| Variable | Expands to |
|---|---|
$< |
first prerequisite |
$^ |
all normal prerequisites, duplicates removed, no order-only |
$+ |
all normal prerequisites, duplicates kept, in listed order |
$| |
all order-only prerequisites |
$? |
prerequisites newer than the target |
Sources: