Reputation: 11
I have the following simple problem in a Makefile:
%.o:: %.c
gcc -o $@ -c $<
lib1.a: test.o
ar -r $@ test.o
rm *.o
lib2.a: test.o
ar -r $@ test.o
rm *.o
all: lib1.a lib2.a
make lib1.a
or make lib2.a
work properly. However, make all
gives:
gcc -o test.o -c test.c
ar -r lib1.a test.o
rm *.o
ar -r lib2.a test.o
ar: test.o: No such file or directory
make: *** [lib2.a] Error 1
I need to do the rm *.o
cause I want the object file to compile each time (in my real Makefile, I have a more complex use case where I compile with different flags).
How can I fix this problem? It seems that make
compiles the object file only once.
I tried with .PHONY
instead of doing the rm
, but again, it compiles only once.
Upvotes: 0
Views: 2654
Reputation: 1336
Your makefile is a bit against the make
logic, this is why the result is not what you expect:
lib1.a
and lib2.a
) with a common dependency: test.o
.all
(which, by the way, should be .PHONY
but this isn't a problem here) that depends on lib1.a
and lib2.a
.So, in order to "do" all
, make
have to build lib1.a
and lib2.a
. They both depend on test.o
, so make
builds test.o
once, then build lib1.a
and lib2.a
, expecting that the recipes you defined will just build those files, and nothing more.
The problem is that you delete test.o
in the recipe for lib1.a
and lib2.a
, although this action is not needed to build them, this is something you want to do when cleaning, not building.
There are two solutions:
.PHONY
rule named clean
for example).%.o:: %.c
one), because make
already has an implicit rule that does that using intermediate targets.Upvotes: 2
Reputation: 8591
Make is a rule-based system. Rules are declarative: you declare what you want built from what, you don't specify the order in which this happens (unless you can't avoid it). So a good Makefile is declarative: all results are declared like in a declarative programming language. They are like final
variables in Java: you bind them to a value, you don't reassign them to a different value afterwards.
Make is also file-based: its "variables", targets and prerequisites are files.
So if you want to build two different things, don't call them by the same name! If you want two different test.o
files, call them differently. The problem will go away without you needing to try and convince make
that it should be like an imperative programming language, which it was specifically designed not to be. If you want an imperative build specification, use a shell script.
Upvotes: 0