Linux - SoftwareThis forum is for Software issues.
Having a problem installing a new program? Want to know which application is best for the job? Post your question in this forum.
Notices
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
If I make foo.c, then make foo.o (in two separate steps), it works fine.
But if I directly make foo.o, it says foo.c not found after foo.c is actually generated.
And, if I am in the directory where .c should be, then, make foo.o also works. But if I am not in that directory, then cc complains that foo.c doesn't exist if I directly make foo.o. So it seems cc cannot search foo.c in vpath?
---------- Post added 11-15-11 at 04:04 AM ----------
[/COLOR]Forgot to mention I did this on Oracle Linux 5.7. make 3.81 and gcc 4.1.2.
Okay, I think I figured it out. The problem is that make doesn't apply vpath to targets, only prerequisites. Furthermore when you put a rule that says foo.c: foo.pc, you're telling make that foo.c will be built in this directory not somewhere else. I put together a simpler example to understand this better. As you can see below make doesn't analyse the contents of the target building rules, so in the first case you get:
Code:
#Using
#%.c : %.pc
# cp $< $(CDIR)/$@
cp pcfiles/foo.pc cfiles/foo.c
Successfully remade target file `foo.c'. # make is confused
But you can fix it by telling make where foo.c will be created:
Code:
#Using
#$(CDIR)/%.c : %.pc
# cp $< $@
cp pcfiles/foo.pc cfiles/foo.c
Successfully remade target file `cfiles/foo.c'. # now make has the right idea
Code:
~/tmp/scratch$ ls -R
.:
cfiles Makefile.broken Makefile.fixed ofiles pcfiles
./cfiles:
./ofiles:
./pcfiles:
foo.pc
~/tmp/scratch$ cat Makefile.broken
CDIR=cfiles
PCDIR=pcfiles
ODIR=ofiles
vpath %.c $(CDIR)
vpath %.pc $(PCDIR)
vpath %.o $(ODIR)
%.c : %.pc
cp $< $(CDIR)/$@
%.o : %.c
cp $< $(ODIR)/$@
foo.c : foo.pc
foo.o : foo.c
clean :
rm -f $(CDIR)/*.c $(ODIR)/*.o
~/tmp/scratch$ make --no-builtin-rules --no-builtin-variables --makefile=Makefile.broken --debug=implicit foo.o
GNU Make 3.81
Copyright (C) 2006 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.
There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE.
This program built for x86_64-pc-linux-gnu
Reading makefiles...
Updating goal targets....
File `foo.o' does not exist.
Looking for an implicit rule for `foo.o'.
Trying pattern rule with stem `foo'.
Trying implicit prerequisite `foo.c'.
Found an implicit rule for `foo.o'.
File `foo.c' does not exist.
Looking for an implicit rule for `foo.c'.
Trying pattern rule with stem `foo'.
Trying implicit prerequisite `foo.pc'.
Found an implicit rule for `foo.c'.
Looking for an implicit rule for `foo.pc'.
No implicit rule found for `foo.pc'.
Must remake target `foo.c'.
cp pcfiles/foo.pc cfiles/foo.c
Successfully remade target file `foo.c'.
Must remake target `foo.o'.
cp foo.c ofiles/foo.o
cp: cannot stat `foo.c': No such file or directory
make: *** [foo.o] Error 1
~/tmp/scratch$ cat Makefile.fixed
CDIR=cfiles
PCDIR=pcfiles
ODIR=ofiles
vpath %.c $(CDIR)
vpath %.pc $(PCDIR)
vpath %.o $(ODIR)
$(CDIR)/%.c : %.pc
cp $< $@
%.o : %.c
cp $< $(ODIR)/$@
$(CDIR)/foo.c : foo.pc
foo.o : foo.c
clean :
rm -f $(CDIR)/*.c $(ODIR)/*.o
~/tmp/scratch$ make -f Makefile.fixed clean
rm -f cfiles/*.c ofiles/*.o
~/tmp/scratch$ make --no-builtin-rules --no-builtin-variables --makefile=Makefile.fixed --debug=implicit foo.o
GNU Make 3.81
Copyright (C) 2006 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.
There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE.
This program built for x86_64-pc-linux-gnu
Reading makefiles...
Updating goal targets....
File `foo.o' does not exist.
Looking for an implicit rule for `foo.o'.
Trying pattern rule with stem `foo'.
Trying implicit prerequisite `foo.c'.
Found an implicit rule for `foo.o'.
File `cfiles/foo.c' does not exist.
Looking for an implicit rule for `cfiles/foo.c'.
Trying pattern rule with stem `foo'.
Trying implicit prerequisite `foo.pc'.
Found an implicit rule for `cfiles/foo.c'.
Looking for an implicit rule for `foo.pc'.
No implicit rule found for `foo.pc'.
Must remake target `cfiles/foo.c'.
cp pcfiles/foo.pc cfiles/foo.c
Successfully remade target file `cfiles/foo.c'.
Must remake target `foo.o'.
cp cfiles/foo.c ofiles/foo.o
Successfully remade target file `foo.o'.
I agree that vpath doesn't apply to targets, only apply to prerequests.
In my case, foo.c is both a target (in rule foo.c:foo.pc) and a prerequest (in rule foo.o:foo.c).
Now, the first rule always works, that is, no matter which folder I'm in, I can make foo.c from foo.pc, so make uses vpath to find foo.pc.
and if I then run make again to make foo.o, no matter which folder I'm in, it also works, so in second run of make it also uses vpath to find foo.c.
But, if I remove foo.c and foo.o, then make foo.o directly, problem occurs. Only foo.c is made, then it complains foo.c cannot be found.
So I don't understand why make cannot find foo.c that is just generated? In rule foo.o:foo.c, foo.c is a prerequest, why it doesn't use vpath to find it?
But, if I remove foo.c and foo.o, then make foo.o directly, problem occurs. Only foo.c is made, then it complains foo.c cannot be found.
So I don't understand why make cannot find foo.c that is just generated? In rule foo.o:foo.c, foo.c is a prerequest, why it doesn't use vpath to find it?
The problem is the rule foo.c : foo.pc, make will apply it and then assume that foo.c has been generated (rather than the ${WPCP}/foo.c that is actually generated) so it won't look for it in vpath.
So isn't it better if make separates the two rules, and uses vpath on second rule as well? What could be the possible reason of doing so?
It does use vpath in the second rule, but it doesn't try to find foo.c in vpath after applying foo.c : foo.pc, because that rule (wrongly) claims to already create foo.c in the current directory. If you wonder why make doesn't check that rules actually generate what they are supposed to, I would say it's likely for performance reasons.
So make somehow inherits? The first rule only says how to generate foo.c from foo.pc, it doesn't say foo.c must be in the current folder. If make restarts vpath search in second rule, it will find foo.c.
Besides, I suppose the performance loss is tiny
The first rule only says how to generate foo.c from foo.pc, it doesn't say foo.c must be in the current folder.
You might think foo.c means foo.c anywhere, but really it means the same as ./foo.c, ie in the current directory. You are breaking Paul's Second Rule of Makefiles.
Quote:
If make restarts vpath search in second rule, it will find foo.c.
Besides, I suppose the performance loss is tiny
Well, the performance thing is only my guess, you can ask the GNU make developers about it for a definitive answer. I think this person had a similar problem.
I meant, make 'inherits' the results from previous rule and assumes the previous target is built in the current folder. I cannot find a good reason to explain this. The reference you gave describes exactly the same case. I'd rather consider it a bug. And so far the solution is not to use vpath in such cases.
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.