LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Linux - Software (https://www.linuxquestions.org/questions/linux-software-2/)
-   -   Question on GNU make concerning vpath (https://www.linuxquestions.org/questions/linux-software-2/question-on-gnu-make-concerning-vpath-913609/)

olivexer 11-15-2011 03:03 AM

Question on GNU make concerning vpath
 
I have a simple make file like this:

vpath %.c ${WPCP}:${CPCP}
vpath %.pc ${WPGM}:${CPGM}
vpath %.o $(WOBJ):$(COBJ)

PCCFLAGS = maxopencursors=30 \
sqlcheck=semantics \
userid=$(USERID) \
code=ansi_c mode=oracle ltype=none \
include=$(WINC) include=$(CINC) \
include=$(ORACLE_HOME_DTB)/rdbms/public \
$(DEBUGPL)

foo.c: foo.pc
proc $(PCCFLAGS) oname=${WPCP}/$*.c iname=$<;\

CFLAG = $(DBG) $(DEBUG) \
$(ICIS_CC_OPT) \
-I $(WINC) -I $(CINC) \
-I$(ORACLE_HOME_DTB)/rdbms/demo \
-I$(ORACLE_HOME_DTB)/rdbms/public \
-I$(ORACLE_HOME_DTB)/precomp/public \
$(C64BIT:64=-q64)
foo.o: foo.c
$(CC) $(CFLAG) -fPIC -c $< -o ${WOBJ}/$*.o

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.

olivexer 11-16-2011 08:13 PM

Pump for help!

olivexer 11-18-2011 02:33 AM

Nobody has any idea?

olivexer 11-19-2011 04:33 PM

please help

olivexer 11-21-2011 11:47 PM

is it a right place for my post?

ntubski 11-25-2011 12:34 AM

Quote:

Originally Posted by olivexer (Post 4524380)
So it seems cc cannot search foo.c in vpath?

Yes, vpath is only known to make, the compiler has no idea about it.

olivexer 11-25-2011 01:24 AM

Quote:

Originally Posted by ntubski (Post 4533335)
Yes, vpath is only known to make, the compiler has no idea about it.

Yes but make should somehow feed vpath to cc, otherwise how to make use of vpath?

ntubski 12-03-2011 11:53 AM

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'.


olivexer 12-03-2011 04:57 PM

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?

ntubski 12-03-2011 07:51 PM

Quote:

Originally Posted by olivexer (Post 4541276)
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.

olivexer 12-03-2011 11:45 PM

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?

ntubski 12-04-2011 09:19 AM

Quote:

Originally Posted by olivexer (Post 4541414)
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.

olivexer 12-04-2011 04:08 PM

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

ntubski 12-04-2011 10:34 PM

Quote:

Originally Posted by olivexer (Post 4541954)
So make somehow inherits?

What? I don't understand this question.

Quote:

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.

olivexer 12-05-2011 04:50 AM

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.


All times are GMT -5. The time now is 01:16 PM.