[comp.bugs.misc] bug in make

brw@jim.odr.oz (Brian Wallis) (07/22/88)

Is this a bug in make, or am I just missing something obvious?
The simple example for the make file is as follows...

| 
| exe: file1.o
| 	ld -o exe file1.o
| 
| file1.o: dir1/file1.c
| 

'Makefile' is in '.' and the file 'file1.c' is in './dir1'

I want to make the file 'exe' from 'file1.o' in '.' where 'file1.o'
depends on './dir1/file1.c' as is stated in the Makefile. I expect
the default '.c.o:' rule to be used to generate the file 'file1.o'
from ./dir1/file1.c.

I can get this to work by including an explicit rule for the
'file1.o' dependency, but this is a little awkward since I use mkdep
to generate the dependancies and have a large number of source files in
a large number of subdirectories.

Here is the output from the make with debug on (and ignore errors, the
bug still exists without -i, but the debuging is truncated).

*** Note: that file1.o DOES NOT exist but a time is returned which
          is later that that returned for dir1/file1.c !!! ***

| 
| 127% ls -l
| total 2
| -rw-r-----  1 brw            65 Jul 22 17:23 Makefile
| drwxr-x---  2 brw           512 Jul 22 17:17 dir1
| 128% ls -l dir1
| total 1
| -rw-r-----  1 brw            87 Jul 22 14:51 file1.c
| 129% make -d -i exe
| doname(exe,0)
| doname(file1.o,1)
| doname(dir1/file1.c,2)
| TIME(dir1/file1.c)=585550307
| TIME(file1.o)=585559519    <<< where the hell does this time come from!!!!
| ld  -o exe file1.o
| ld:file1.o: cannot open
| *** Error code 4 (ignored)
| Open directories:
| 	4: .
| 	3: dir1
| Macros:
| 	? = file1.o
| 	@ = 
| 	* = file1

.... (deleted stuff)

| dir1/file1.c  done=2
| 
| file1.o:  done=2
|  depends on: dir1/file1.c 
| 
| exe:  done=2  (MAIN NAME)
|  depends on: file1.o 
|  commands:
| 	ld $(LFLAGS) -o exe file1.o

... (deleted stuff)

| .c.o:  done=0
|  commands:
| 	$(CC) $(CFLAGS) -c $<

... (deleted stuff)

| .SUFFIXES:  done=0
|  depends on: .out  .o  .c  .F  .f  .e  .r  .y  .yr  .ye  .l  .s  .cl  .p 

Can someone with source help out here???

I have tried this on...

MicroVax running Ultrix 2.0
Sun 3/110 running SunOS 3.2
Altos 586 running Xenix 3.0

with the same results each time (minor differences in debugging output).
-- 
Brian Wallis (brw@jim.odr.oz)		    O'Dowd Research P/L.
	(03) 562-0100 Fax: (03) 562-0616,
	Telex: Jacobs Radio (Bayswater) 152093

banderso@sagpd1.UUCP (Bruce Anderson) (07/31/88)

In article <525@jim.odr.oz> brw@jim.odr.oz (Brian Wallis) writes:
>
>Is this a bug in make, or am I just missing something obvious?
>The simple example for the make file is as follows...
>
>| 
>| exe: file1.o
>| 	ld -o exe file1.o
>| 
>| file1.o: dir1/file1.c
>| 
>
>'Makefile' is in '.' and the file 'file1.c' is in './dir1'
>
>I want to make the file 'exe' from 'file1.o' in '.' where 'file1.o'
>depends on './dir1/file1.c' as is stated in the Makefile. I expect
>the default '.c.o:' rule to be used to generate the file 'file1.o'
>from ./dir1/file1.c.
>
>I can get this to work by including an explicit rule for the
>'file1.o' dependency, but this is a little awkward since I use mkdep
>to generate the dependancies and have a large number of source files in
>a large number of subdirectories.
> [lots of debug output deleted]
>--
>Brian Wallis (brw@jim.odr.oz)		    O'Dowd Research P/L.
>	(03) 562-0100 Fax: (03) 562-0616,
>	Telex: Jacobs Radio (Bayswater) 152093


I had the same problem on our HP-9000 system running HP's version of Unix,
HP-UX and simply ended up using explicit rules because I couldn't figure out
any other way to do it. Then I ran across a PD version of make and looked
at the source (which I assume is similar in intent to the Unix version)
and discovered an explanation for the behaviour experienced.
Basically, when you have a dependency in the Makefile such as:

test.o: test.c

and don't give an explicit rule, it goes out and check the modifcation
times of the two files and then determining that is needs to update
test.o it goes out to itts implicit rule base
and looks for a way to generate test.o. It however, *TOTALLY IGNORES*
the test.c filename on the dependency line and generates the source
file name from the target file name. So for example, if you have a line

test.o: whatever.c

it will try to make test.o from test.c NOT whatever.c even though whatever.c
is in the same directory. So you can see that in the case of a subdirectory,
it will go out and check the dependency of the source file in the 
subdirectory but then generate an entirely new name which by default is
in the current directory to try to make the target out of.
As far as I can tell, this is the way that the Unix make works as well.

chris@mimsy.UUCP (Chris Torek) (08/01/88)

>In article <525@jim.odr.oz> brw@jim.odr.oz (Brian Wallis) writes:
>>[sample simple makefile] 
>>| exe: file1.o
>>| 	ld -o exe file1.o
>>| 
>>| file1.o: dir1/file1.c

>>'Makefile' is in '.' and the file 'file1.c' is in './dir1'.
>>I want to make the file 'exe' from 'file1.o' in '.' where 'file1.o'
>>depends on './dir1/file1.c' as is stated in the Makefile. I expect
>>the default '.c.o:' rule to be used to generate the file 'file1.o'

Good so far;

>>from ./dir1/file1.c.

oops.

In article <284@sagpd1.UUCP> banderso@sagpd1.UUCP (Bruce Anderson) writes:
>[make] goes out to itts implicit rule base
>and looks for a way to generate test.o. It however, *TOTALLY IGNORES*
>the test.c filename on the dependency line and generates the source
>file name from the target file name.

This is right, but a bit misleading.  Here is another makefile:

	foo: foo.o
		ld -o $@ foo.o

	foo.o: dir/foo.c
		${CC} -c ${CFLAGS} $*.c

This one has as an explicit line the same rule that appears in the
default .c.o.  The point is that $*.c (or $<, which works only in
generic rules, so I actually modified the rule a bit) expands to
`foo.c', not `dir/foo.c'.  The names of the files upon which foo.o
depends are irrelevant; they have nothing to do with the expansion
of the various macros.

Solutions to the original problem?  Unless you have VPATH, there
are no nice ones.  Make does not deal well with directories.
-- 
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163)
Domain:	chris@mimsy.umd.edu	Path:	uunet!mimsy!chris

rdt@teddy.UUCP (Ron D. Thornton) (08/02/88)

In article <525@jim.odr.oz> brw@jim.odr.oz (Brian Wallis) writes:
>
>Is this a bug in make, or am I just missing something obvious?
>The simple example for the make file is as follows...
>
>| 
>| exe: file1.o
>| 	ld -o exe file1.o
>| 
>| file1.o: dir1/file1.c
>| 
>
 ...
> I expect
>the default '.c.o:' rule to be used to generate the file 'file1.o'
>from ./dir1/file1.c.
 ...
>*** Note: that file1.o DOES NOT exist but a time is returned which
>          is later that that returned for dir1/file1.c !!! ***
 ...
>| 129% make -d -i exe
>| doname(exe,0)
>| doname(file1.o,1)
>| doname(dir1/file1.c,2)
>| TIME(dir1/file1.c)=585550307
>| TIME(file1.o)=585559519    <<< where the hell does this time come from!!!!
>| ld  -o exe file1.o
>| ld:file1.o: cannot open

Make has some subtle things going on.  '.c.o' is an inferred or implicit
rule, NOT a default rule.  Inferred rules are only used when make constructs
an inferred 'prerequisite' from the .SUFFIX list.

Since you supplied a dependency line AND make could not build an inferred
prerequisite from the .SUFFIX list, make assumed the target (file1.o) was 
successful and therefore assigned the current time to it.  This allows
constructs like:

	all: program_a program_b program_c

to work without getting an error because the target "all" never really
exists.

I think you are stuck with specifying explicit rules if you move the
source out of the current directory.  You might think about putting the
Makefile in with the sources and objects, just pushing the exe's into
something other than the current directory.

	-Ron-
	rdt@genrad.com