Home > Back-end >  Building binary with not default target 'all' in Makefile
Building binary with not default target 'all' in Makefile

Time:02-20

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.

  • Related