groff
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: an angry rant about *BSD Make


From: Ingo Schwarze
Subject: Re: an angry rant about *BSD Make
Date: Tue, 29 Mar 2022 23:39:45 +0200

Hi Branden,

G. Branden Robinson wrote on Wed, Mar 30, 2022 at 06:37:17AM +1100:
> At 2022-03-29T21:04:54+0200, Ingo Schwarze wrote:

>> This works for me and seems pretty simple and straightforward:
>> 
>>   SUFFIXES += .me.in
>> 
>>   .me.in.me:
>>      $(GROFF_V)$(MKDIR_P) `dirname $@` && $(DOC_SED) $< >$@

> It _doesn't_ work for me in a stripped-down scenario.
> 
> $ cat hello.me.in
> .p
> We're going to run @g@troff.
> $ cat Makefile.double-suffix.gnu
> SUFFIXES += .me.in

That is automake(1) syntax, not make(1) syntax...

> .me.in.me:
>         sed 's/@g@//' $< >$@
> 
> all: hello.me
> 
> clean:
>         rm -f *.me
>
> $ make -f Makefile.double-suffix.gnu

 ... but here you are running make(1) on the input designed for
automake(1), and that is indeed expected to not work.

> make: *** No rule to make target 'hello.me', needed by 'all'.  Stop.
> 
> Adding '.me' to the 'SUFFIXES' macro/variable doesn't help.

The reason why i did not write

  SUFFIXES += .me.in .me

is that while automake(1) does not figure out on its own that .me.in
is needed in .SUFFIXES, i does figure out without help that .me is
needed there, so manually adding .me to the SUFFIXES automake(1)
variable would be redundant.  As we discussed earlier, adding
redundant strings to the SUFFIXES automake(1) variable degrades
readability of the generated Makefile even further.

> The following works with NetBSD make ("bmake" on my Debian system) and
> GNU Make, but '.SUFFIXES' is unfortunately forbidden by Automake.
> 
> $ cat Makefile.double-suffix
> .SUFFIXES: .me.in .me

Yes.  That is the correct syntax if you want to use plain make(1)
without using automake(1).  The line ".SUFFIXES: .me.in .me"
is also what automake(1) generates from "SUFFIXES += .me.in".

> #.SUFFIXES: .me.in

It makes sense that you commented this line out.  With plain make(1),
it is indeed insufficient.  Plain make(1) requires listing all the
needed suffixes in .SUFFIXES and does not attempt to guess any of
them.

> .me.in.me:
>         sed 's/@g@//' $< >$@
> 
> all: hello.me
> 
> clean:
>         rm -f *.me
> 
> Note the commented line, corresponding to your original example.  _Both_
> suffixes must be present.  (In the groff build, I think '.in' is already
> in 'SUFFIXES', either thanks to "hdtbl.am" or GNU Make or Automake's own
> internal pre-definitions.)

I believe the confusion in part arises from the extensive layering:

     Makefile.am  # syntax processed by automake(1)
  -> Makefile.in  # syntax processed by ./configure
  -> Makefile     # syntax processed by make(1)

In a complex, multi-layered system involving multiple stages of
automatic code generation, it is easy to lose track of what kind of
input is intended to be processed by which program at which stage.
Leaving aside automake(1) and autoconf(1), the rules for make(1)
itself are substantially simpler than the full picture.

Regarding your question how make(1) disambiguates:

  .SUFFIXES: .me.in .me
  .me.in.me:

means "transform .me.in -> .me"

  .SUFFIXES: .me .in.me
  .me.in.me:

means "transform .me -> .in.me"

String lengths have nothing to do with it.
If i invented a fancy new object format, i would be free to write

  .SUFFIXES .c .fancy.new.object.format
  .c.fancy.new.object.format:
        my_fancy_compiler -c -o $@ $<

Note that i'm not saying you are being dense.  It is a lot easier
to see after the fact how some syntax is straighforward when a
solution is being shown than develop the solution from scratch
with help from nothing but (multiple and conflicting) manual pages,
in particular when a complex, multi-layered system of automatic
code generation gets in the way.  From my side, sorry for not
mentioning up front where my proposal was supposed to be put.

If you want to add a comment making the most obscure aspect of this
topic easier to understand, i believe something like in the patch
below might suffice.  Note, though, that automake(1) separates
that comment from the code it explains when writing Makefile.in,
and besides, it actually spreads the ".me.in" and ".me" across
two different .SUFFIXES rules, so neither the Makefile.in
created by automake(1) nor the final Makefile created by
./configure is particularly easy to read, in stark contrast
to a well-designed hand-written Makefile.

Are things clearer now?

Yours,
  Ingo


diff --git a/doc/doc.am b/doc/doc.am
index 544fe147a..6fd82bc0c 100644
--- a/doc/doc.am
+++ b/doc/doc.am
@@ -251,9 +251,13 @@ doc/meintro_fr.me: $(doc_srcdir)/meintro_fr.me.in
        $(GROFF_V)$(MKDIR_P) `dirname $@` \
        && $(DOC_SED) $? >$@
 
-doc/meref.me: $(doc_srcdir)/meref.me.in
-       $(GROFF_V)$(MKDIR_P) `dirname $@` \
-       && $(DOC_SED) $? >$@
+# automake(1) transforms the line "SUFFIXES += .me.in" from doc/doc.am
+# to the ".SUFFIXES: .me.in .me" needed by make(1);
+# no need to manually tell automake(1) about the ".me" suffix
+SUFFIXES += .me.in
+
+.me.in.me:
+       $(GROFF_V)$(MKDIR_P) `dirname $@` && $(DOC_SED) $< >$@
 
 $(PROCESSEDDOCFILES_PS): \
   $(dist_devpsfont_DATA) $(nodist_devpsfont_DATA)



reply via email to

[Prev in Thread] Current Thread [Next in Thread]