Reputation: 1
Given the following GNU Makefile:
OBJS = a.o b.o
LIB = libX.a
$(LIB): $(OBJS)
$(AR) cr $@ $^
$(LIB): CPPFLAGS = $(shell P)
When I build $(LIB)
, I can see that external program P is called twice, once each to build a.o
and b.o
(I have it just printing getpid()
to stderr
).
In my case, P will always produce the same result, so it's wasted cycles/time having P called for creation of every .o
. LIB
could be made of MANY .o's of course, and the problem worse.
Is there a way to get target-specific variables to only be evaluated once, i.e evaluated for the target $(LIB)
and that VALUE, verbatim, be passed to the prerequisite recipes (.o
from .c
)? Or am I misunderstanding their usage (I suspect that I am!)
Tried various variable assignment syntaxes, e.g. =
and :=
, even ::=
, all by trial and error. Read the manual over and over.
Upvotes: 0
Views: 172
Reputation: 180201
Is there a way to get target-specific variables to only be evaluated once, i.e evaluated for the target
$(LIB)
and that VALUE, verbatim, be passed to the prerequisite recipes (.o
from.c
)? Or am I misunderstanding their usage (I suspect that I am!)
The docs don't seem to specify the exact semantics of when and how target-specific variables are set for building the affected target's prerequisites. Your best bet for the behavior you want was to use simple variable assignment (:=
or ::=
), but you say that doesn't work. make
seems to be behaving as if the variable assignment were included, separately, in the rule for each prerequisite, and that makes sense because in general, there is no guarantee that the prerequisites will all be built one after another or immediately before the main target, and where they aren't all built one right after another, the variable must resume its global value between.
Really, I'd like to encourage you to minimize your use of features specific to GNU make
. Every one of them is a convenience, not a necessity, though occasionally, some of them are very convenient indeed. You might consider instead deploying Autoconf +/- Automake to (semi-)dynamically insert flags into your makefile.
But if you must use $(shell)
in your makefile, and you want to be certain that the command is executed only once per make
run, then your best bet is probably to run it outside any rule. If you don't want to modify the global CPPFLAGS then store the result instead in some other variable:
OBJS = a.o b.o
LIB = libX.a
X_CPPFLAGS := $(shell P)
$(LIB): $(OBJS)
$(AR) cr $@ $^
$(LIB): CPPFLAGS = $(X_CPPFLAGS)
Upvotes: 2