I am using the following code:
HELLO_WORLD=hello $(HELLO_WORLD): $(addsuffix .c,$@) gcc $< -o $@
However, when I run the code, I receive the following error, implying that $< is not evaluating to anything:
gcc -o hello gcc: fatal error: no input files
When I use the following code…
HELLO_WORLD=hello $(HELLO_WORLD): $(addsuffix .c,$@) gcc $(addsuffix .c,$@) -o $@
…the Makefile evaluates to the following command…
gcc hello.c -o hello
…which is precisely what I would like. However, I do not want to use addsuffix twice. I would like to use $< in the event that I change the prerequisite. How would I go about doing this?
Advertisement
Answer
The problem is not with the expansion of $<
in the recipe. The problem is the expansion of $@
in the prerequisite list.
Automatic variables, such as $@
, are only defined in the recipe, not in the target or prerequisite lists. This is highlighted in the GNU Make manual section on automatic variables:
A common mistake is attempting to use
$@
within the prerequisites list; this will not work.
The fact that hello.c
is not actually in the prerequisite list does not prevent you from invoking make hello
. It just means that make hello
will always invoke the compiler, even if hello.c
has not been modified. But it does mean the $<
will be as empty as the computed prerequisite list.
GNU make does have a feature to let you do a second expansion of prerequisites; this is explained in the manual. But the simpler solution is to simply not rely on $@
in the prerequisite list. If you’re trying to create your own generic C compile recipe, use a pattern rule for object file (.o
) targets. For the final executable, list all the prerequisites for the final executable (which will almost certainly be more than one file).
Typically this is done using separate variable with names like SRCS
and OBJS
(or SOURCES
and OBJECTS
if you don’t mind typing vowels). Normally you make the object files prerequisites for the final executable (which will be a link operation), since each individual source file will have its own header prerequisites.