12
votes

While using GNU-make, my Makefile has some pattern rule as:

%.o:%.c
    gcc $< -o:$@

This rule is added by me.

But when I do make it gives an error saying No rule to make target %.o and doesn't build the targets.

At times, there is this other behaviour as well. It does not build the target when I say make first time(It gives error saying No rule to make target), but when i say make again immediately, it does build correctly.

So when i explicity specify each source file separately, then it builds the targets fine first time itself.

EDIT: I am using GNU-make on a Centos (v6.3 i guess, not sure). Could this be some permission/user id /group id issue?

Any pointers to understand what might be happening and solution for this?

thank you, -AD.

5
Having the exact same problem here. God, I hate makefiles and their stupid syntax and arbitrary limitations.antred

5 Answers

16
votes

Make only uses a pattern rule as a sort of fallback. For example:

$ ls
Makefile
$ cat Makefile
%.o: %.c
    gcc $< -o $@
$ make
make: *** No targets.  Stop.

This is fine. Make does not consider the pattern rule as you have not asked it to make anything, and there is no default target in the makefile. Let's ask it to make something that might use the pattern rule.

$ make 1.o
make: *** No rule to make target `1.o'.  Stop.

Expected. 1.c does not exist, so the pattern rule is not considered. Let's try again.

$ touch 1.c
$ make 1.o
gcc 1.c -o 1.o

(and then some error about main being missing).

Personally I dislike these fallback rules intensely. I much prefer listing the targets explicitly. Something like

file.o file2.o f.o: %.o: %.c
    ...

gives you a Target Specific Pattern Rule. These are quite different (see the manual). [Oh, and the pattern gives you no advantage in this noddy example.]

1
votes

You might need spaces around the : in the first line of your rule. Also, gcc does not take a colon before the output file name; just use -o $@.

1
votes

Just ran through this problem.

If this is your rule:

%.o:%.c
    gcc $< -o:$@

Make sure that you have a tab and not spaces on the second line before the gcc. Took me a couple of hours to figure out. Also no ':' after the -o flag, as somebody else pointed out.

0
votes

Are you sure the .c file exists? I think using -d as suggested earlier should help debug this.

0
votes

If you put only this in a Makefile and call make:

%.o: %.cpp
  g++ -g -o $@ -c $<

It tells: make: *** No targets. Stop.

Because it's not a target. It's a rule.

It will work if your another target needs a .o file.

main.exe: main.o add.o
  g++ -g -o $@ $^

%.o: %.cpp
  g++ -g -o $@ -c $<