[comp.unix.programmer] Make doesn't understand .SUFFIXES: .b .c .s .i .o

jc@netrix.nac.dec.com (06/05/91)

This has bothered me for some time, and it sure seems that make oughta
know how to handle it, but it never does.  What  I've  been  doing  is
using  a  local preprocessor to convert foo.b to foo.c, where foo.b is
basically C with a bunch of extra stuff that cpp can't  handle.   I've
written a simple translator b-c and told make:
	.SUFFIXES: .b .c .s .i .o
	.b.c:   ;b-c 0-8t 9 <$*.b >$@
	.c.o:   ;cc -c $(CFLAGS) $*.c

The  b-c  params to make are irrelevant to this example; the annoyance
is that these three lines don't explain to make how to  convert  foo.b
to foo.o, as is shown by:
	% touch foo.b
	% make foo.o
	Make:  Don't know how to make foo.o.  Stop.

If I tell it to make foo.c, it works, and then it knows  how  to  make
foo.o  from  foo.c;  the problem is that it doesn't seem to understand
the .b -> .c -> .o sequence, although it appears to  be  explained  in
the  above.   But  this is a pain, because the clean:  entry of course
tosses out the .c files, and then the chain is broken.

What I've been doing is adding lines to the makefile like:
 foo.c:  foo.b
and then it works fine.  But this seems stupid; every time I add a new
source module, I have to add a line like this.  It is obvious that the
.SUFFIXES was intended to handle cases like this, but it doesn't.   So
why doesn't it?  I've dug around in TFM several times, to no avail...

Am I crazy for expecting this to work?  Does anyone  have  a  makefile
that does this successfully?

torek@elf.ee.lbl.gov (Chris Torek) (06/05/91)

In article <23182@shlump.lkg.dec.com> jc@netrix.nac.dec.com writes:
>If I tell [make] to make foo.c, it works, and then it knows how to make
>foo.o from foo.c; the problem is that it doesn't seem to understand
>the .b -> .c -> .o sequence ...

This kind of thing---taking the b->c and c->o sequence and deriving
the b->o sequence from that---is called `transitive closure'.

Most `make' programs do not do transitive closure.

What you must do, then, is define not only a b->c rule and a c->o rule
but also a b->o rule.

>What I've been doing is adding lines to the makefile like:
> foo.c:  foo.b
>and then it works fine.

Right: because this adds an implicit rule via an explicit dependency.
-- 
In-Real-Life: Chris Torek, Lawrence Berkeley Lab CSE/EE (+1 415 486 5427)
Berkeley, CA		Domain:	torek@ee.lbl.gov

wolfgang@wsrcc.com (Wolfgang S. Rupprecht) (06/06/91)

jc@netrix.nac.dec.com writes:
>	.SUFFIXES: .b .c .s .i .o
>	.b.c:   ;b-c 0-8t 9 <$*.b >$@
>	.c.o:   ;cc -c $(CFLAGS) $*.c

>If I tell it to make foo.c, it works, and then it knows  how  to  make
>foo.o  from  foo.c;  the problem is that it doesn't seem to understand
>the .b -> .c -> .o sequence

You never told it how to make a .b -> .o .

add this:

.b.o:   
	b-c 0-8t 9 <$*.b >$@
	cc -c $(CFLAGS) $*.c

-wolfgang
-- 
Wolfgang Rupprecht    wolfgang@wsrcc.com (or) uunet!wsrcc!wolfgang
Snail Mail Address:   Box 6524, Alexandria, VA 22306-0524

martin@mwtech.UUCP (Martin Weitzel) (06/06/91)

In article <23182@shlump.lkg.dec.com> jc@netrix.nac.dec.com writes:
[about a problem he has with make's suffix rules]

Chris Torek already posted one perfectly valid solution to this
problem (adding a `.b.o:' rule).

But as often, there are several possible solutions, and though I'd
probably too solve it as Chris recommended, I'll point to an alternative.

>What I've been doing is adding lines to the makefile like:
> foo.c:  foo.b
>and then it works fine.  But this seems stupid; every time I add a new
>source module, I have to add a line like this.

You can save a little typing if you do this as follows:

	C_B = $(@:.c=.b) # never change this macro

	# add new modules to the LHS of the following dependency
	foo1.c foo2.c ... fooN.c : $$(C_B)

This may not seem to be big win as long as you type it as shown above, but
if it is changed it a little,

	C_B = $(@:.c=.b) # never change this macro

	# add new modules here
	B_SOURCES = foo1.b foo2.b ... fooN.b

	# never change this dependency
	$(B_SOURCES:.b=.c) : $$(C_B)

there is the advantage that all the *.b modules are now listed in the
make macro B_SOURCES. If this is a win or not largely depends whether
there is the necessity for B_SOURCES anywhere else in the Makefile
(e.g. if there is any other general processing of *.b modules you
sometimes want, say a special pretty printer, a special lint or
whatever). Note also that it can be sometimes an advantage to put
things into a make macro since there are several ways to set macros
when you run make (i.e. without changing the makefile).

(As I posted some of the backgrounds how this works not so long ago,
I'll not repeat it here. If anybody has a questions, please contact
me by mail.)
-- 
Martin Weitzel, email: martin@mwtech.UUCP, voice: 49-(0)6151-6 56 83

src@scuzzy.in-berlin.de (Heiko Blume) (06/08/91)

i'd recommend to use GNU make in the first place, which handles
things like RCS->yacc->cc->ld chains nicely. see the node
"Chained Rules" in the GNU make documentation for details.
-- 
   Heiko Blume <-+-> src@scuzzy.in-berlin.de <-+-> (+49 30) 691 88 93 [voice!]
                  public UNIX source archive [HST V.42bis]:
        scuzzy Any ACU,f 38400 6919520 gin:--gin: nuucp sword: nuucp
                     uucp scuzzy!/src/README /your/home

gilles@diox.Convergent.COM (Gilles COURCOUX) (06/11/91)

In article <23182@shlump.lkg.dec.com> jc@netrix.nac.dec.com writes:

[I tried to answer directly by Email, but mails bounced back with:
   ----- Transcript of session follows -----
User "jc" is no longer employed here and has moved to a site that
does not have electronic mail access. We therefore cannot forward the mail.]

>This has bothered me for some time, and it sure seems that make oughta
>know how to handle it, but it never does.  What  I've  been  doing  is
>using  a  local preprocessor to convert foo.b to foo.c, where foo.b is
>basically C with a bunch of extra stuff that cpp can't  handle.   I've
>written a simple translator b-c and told make:
>	.SUFFIXES: .b .c .s .i .o
>	.b.c:   ;b-c 0-8t 9 <$*.b >$@
>	.c.o:   ;cc -c $(CFLAGS) $*.c

You inverted the sequence of suffixes in the .SUFFIXES line. It must be
	.SUFFIXES: .o .i .s .c .b 

Note that to make 'make' forget all its previous prefixes you must 'erase' them
with the line
	.SUFFIXES:

Your makefile should now be:
	.SUFFIXES:
	.SUFFIXES: .o .i .s .c .b 
	.b.c:   ;b-c 0-8t 9 <$*.b >$@
	.c.o:   ;cc -c $(CFLAGS) $*.c

From the SVR3.2 online manual:

       Additional suffixes are given as the dependency list for
       .SUFFIXES.  Order is significant; the first possible name
       for which both a file and a rule exist is inferred as a
       prerequisite.  The default list is:

       .SUFFIXES: .o .c .c~ .y .y~ .l .l~ .s .s~ .sh .sh~ .h .h~ .f .f~

       Here again, the above command for printing the internal
       rules will display the list of suffixes implemented on the
       current machine.  Multiple suffix lists accumulate;
       .SUFFIXES: with no dependencies clears the list of suffixes.

I agree, it is not very explicit (as usual :-). But by looking closely at the
default suffixes list, you could have noticed that.

Makes you happy?

--
Gilles Courcoux                        E-mail: gilles@Convergent.COM
Chorus Systems Inc                     Phone:  (408) 435-7692