Follow-up Comment #1, bug #68716 (group groff):

Hi Ingo,

At 2026-09-26T12:13:25-0400, Ingo Schwarze wrote:
> Date: Sat 26 Sep 2026 04:13:24 PM UTC By: Ingo Schwarze <schwarze>
> https://pubs.opengroup.org/onlinepubs/9799919799/utilities/make.html defines
> the semantics of suffix rules in two paragraphs.
>
> The first paragraph (starting with "When no target rule with commands
> ...") defines the behaviour of double-suffix rules.
>
> The second paragraph defines the behaviour of single-suffix rules and
> starts as follows:  "If the target to be built does not contain a
> suffix and there is no rule for the target, the single-suffix
> inference rules shall be checked.  [...]"
>
> The condition "there is no rule for the target" makes no exception for
> rules without commands.  That means, if there is _any_ rule for a
> target, even a rule with no commands, the whole paragraph does not
> apply and no search for single-suffix inference rules takes place.

Hmm, yes, I see.  I re-read the entire POSIX spec for make(1) when Issue
8 was finalized, but evidently the foregoing didn't stick in my brain.

I wonder if it is arguable that a target rule that lists only
prerequisites, and lacks a recipe, isn't actually a "target rule" since
it gives no _rule_ for constructing the _target_.

Thus, prerequisite-only "target rules" aren't target rules at all, but
simply update the dependency graph.  A "real" target rule, a suffix
rule, a pattern rule (in GNU Make), or an implicit rule is still
necessary to tell Make how to update the file/node.

But even if my case _is_ arguable, if BSD Make doesn't behave that way,
I have a problem.

> This means that the line "$(GROFF_MAN_PAGES_ALL): soelim" in
> _doc/doc.am_ prevents all files listed in GROFF_MAN_PAGES_ALL from
> ever getting built because this line overrides the suffix rule ".man:"
> in _Makefile.am_ with a more specific target rule that never does
> anything but always succeds.

Gar.

> Later in the build, the following two targets crash because they try
> to read from non-existent files that were not built because the rule
> supposed to build them actually did nothing: _doc/groff-man-pages.pdf_
> and _doc/groff-man-pages.utf8.txt_ .
>
> I see two ways to fix this.
>
> Option 1:
> Since _man/groff.7.man_ appears to be the only manual page file
> actually using a _.so_ request (which is arguably a bad idea in the
> first place, but, oh well),

I don't think so.  Using the `so` request here honors the DRY principle.

I want an ASCII art fallback for a pic(1) diagram, and we also use said
pic(1) diagram in our Texinfo manual.  Thus, it needs to live in its own
file.  An alternative would be to sed(1) out the pic(1) region from the
groff(7) man page at build time, which I think you'll agree trades one
kind of fragility for another.

And in my experience, getting Texinfo to include image files in all of
its output formats is a much more fragile process than anything groff
imposes on people.

> rename that file and generate _man/groff.7.man_ from the renamed file
> using a dedicated target rule that runs nothing but soelim and depends on
> soelim.  That allows deleting the troublesome dependency rule
> "$(GROFF_MAN_PAGES_ALL): soelim".

I'm kind of loath to do that, but there is precedent.


$ sed -n 293,301p tmac/tmac.am
tmac/groff_man.7.man: tmac/groff_man.7.man.in $(M4CHECK)
        $(AM_V_GEN)$(M4) -D_groff_man_not_style \
          -DREVISION_DATE=`$(PERL) $(top_srcdir)/mdate.pl
$(top_srcdir)/tmac/groff_man.7.man.in` \
          $(tmac_srcdir)/groff_man.7.man.in > $@

tmac/groff_man_style.7.man: tmac/groff_man.7.man.in $(M4CHECK)
        $(AM_V_GEN)$(M4) -D_groff_man_style \
          -DREVISION_DATE=`$(PERL) $(top_srcdir)/mdate.pl
$(top_srcdir)/tmac/groff_man.7.man.in` \
          $(tmac_srcdir)/groff_man.7.man.in > $@


> Option 2:
> Use double-suffix rules instead of a single-suffix rule, for example
> ".1man.1:" - of course, that causes some churn because it requires
> renaming the input files, for example from "*.1.man*" to "*.1man*".

I like that even less!

(a) That naming convention strikes me as ugly.
(b) I can't count on BSD Make to not break the non-POSIX-conforming hack
    that I rely upon to get work done.


$ sed -n 328,375p doc/doc.am
# Generating *.me from *.me.in is, surprisingly, a challenge.
# 1.  A pattern rule ("%.me: %.me.in") is not portable to NetBSD or
#     OpenBSD make.
# 2.  A single-suffix rule works in an isolated Makefile, but _only_
#     with the .SUFFIXES special target, not with the
#     (Automake-specific) SUFFIXES macro.
#       .SUFFIXES: .in
#       .in:
#               $(DOC_SED) $< >$@
#     (One can validly complain that this approach is too general.)
# 3.  GNU Automake insists that we use the SUFFIXES macro and not the
#     special target.
#       error: use variable 'SUFFIXES', not target '.SUFFIXES'
# 4.  What about a target rule?  We'd have to explicitly write the first
#     preprequisite name in the rule commands because NetBSD make (and
#     reportedly OpenBSD) refuses to honor the $< variable in target
#     rules.
#
# So what is left?  A double-suffix rule--but you have to use it in a
# special way that is explicitly not countenanced by POSIX.
#
#   "The application shall ensure that the target portion is a valid
#   target name (see Target Rules, ...) of the form .s2 or .s1.s2 (where
#   .s1 and .s2 are suffixes that have been given as prerequisites of
#   the .SUFFIXES special target and s1 and s2 do not contain any
#   <slash> or <period> characters.) If there is only one <period> in
#   the target, it is a single-suffix inference rule. Targets with two
#   periods are double-suffix inference rules. Inference rules can have
#   only one target before the <colon>."
#     (POSIX Issue 8 Draft 4.1, make(1), "Inference Rules")
#
# A double-suffix rule won't work in an obvious way because its
# semantics are that the suffix is replaced, not removed.  You have to
# add both suffixes to the .SUFFIXES special target, in order with the
# prerequisite first.
#   .SUFFIXES: .me.in .me
#   .me.in.me:
#       $(DOC_SED) $< >$@
# Thanks to Automake, we must say
#   SUFFIXES += .me.in .me
# for reason 3 above.  The GNU Automake manual does not explicitly state
# that it preserves the ordering of the suffixes, but for now it does.
#
# It appears to be dumb luck that this works; the rigamarole by itself
# justifies to me the worth of GNU Make's pattern rules (which require
# neither '.SUFFIXES' nor 'SUFFIXES') and establishing semantics for $<
# in target rules.  But I won't hold my breath waiting on other make(1)
# implementors to agree.  -- GBR




    _______________________________________________________

Reply to this item at:

  <https://savannah.gnu.org/bugs/?68716>

_______________________________________________
Message sent via Savannah
https://savannah.gnu.org/

Attachment: signature.asc
Description: PGP signature

Reply via email to