Reputation: 57764
I am stumped coming up with a makefile rule to have several executables where each depends on its respective source file. There is a library common to all and each program has a single source file: a.c
compiled and linked with the library produces executable a
, etc.
LIB_C_FILES = f1.c f2.c f3.c
LIB_H_FILES = f1.h f2.h f3.h
TARGETS = a b c
CFLAGS = -g -O0 -DDEBUG
.PHONY : all clean
.c.o:
g++ -c $(CFLAGS) -o $@ $<
all: $(TARGETS)
${TARGETS} : lib.a ${@:%=%.c}
g++ $(CFLAGS) ${@:=.c} -o $@ lib.a
lib.a: ${LIB_C_FILES:.c=.o} $(LIB_H_FILES)
ar r $@ $?
The library portion works fine. And when an executable does not exist, it also works fine. But when one of the standalone source files is modified it says make: Nothing to be done for 'all'.
I don't understand the proper way to make target a
depend on source a.c
individually in a list. What am I missing?
Upvotes: 0
Views: 1923
Reputation: 15483
Just for completeness: you can do what you want with plain old static pattern rules, so long as you can match all of ${TARGETS}
with make's (noddy) pattern matching.
${TARGETS}: %: %.C lib.a
g++ ${CFLAGS} $< -o $@ lib.a
lib.a: ...
ar ...
A tad more readable, and perhaps more compatible than .SECONDEXPANSION
?
Upvotes: 3
Reputation: 2021
First, I assume fio.a was a typo (you probably meant lib.a).
Second, I think the tricky part is your ${@:%=%.c} prerequisite. AFAIK, $@ can't be used this way.
I think you can get the behavior you're looking for using .SECONDEXPANSION though.
Try:
.SECONDEXPANSION:
${TARGETS} : lib.a $$(patsubst %,%.c,$$@)
There may be an old-style substitution way to do this, but I find the patsubst line to be more readable than ${@:%=%.c}.
(I should add that this applies to Gnu make 3.82. YMMV with older versions of Gnu make, or [heaven forbid] non-Gnu versions of make).
Upvotes: 2