I have simple Makefile
below. That runs clear when using default target all
.
objects = foo.o bar.o all.o
all: $(objects)
all2: $(objects)
# These files compile via implicit rules
foo.o: foo.c
bar.o: bar.c
all.o: all.c
all.c:
echo "int main() { return 0; }" > all.c
%.c:
touch $@
clean:
rm -f *.c *.o all2
But when I execute make all2
I got:
touch foo.c
cc -c -o foo.o foo.c
touch bar.c
cc -c -o bar.o bar.c
echo "int main() { return 0; }" > all.c
cc -c -o all.o all.c
touch all2.c
cc -c -o all2.o all2.c
cc all2.o foo.o bar.o all.o -o all2
rm all2.o all2.c
all2
target depends on foo.o bar.o all.o
, but why it trying to get all2.c
?
Why it executes clean
target at he end? Line rm all2.o all2.c
CodePudding user response:
The reason is that make has a built-in rule that knows how to build a binary file from an object file that has the same prefix; that is, given a binary file foo
make has a built-in rule that knows how to build it from foo.o
.
You have a target all2
and normally that doesn't matter because you don't have an all2.c
and so make can't find a way to build all2.o
and so it decides there's no rule to build all2
.
But in your makefile, you've created a rule to build any .c
file, so when make tries to find a way to build all2.o
it discovers it can be built from all2.c
and there is a rule to build all2.c
, so the rule matches.
Of course, you won't have a rule like %.c : ; touch $@
in your non-test makefile so you won't see this problem in any real makefile.
If you want to make this work for your test environment you can, as @Cheatah says, declare the all2
rule to be phony which will prevent make from trying to look up any rules to build it.