]> git.ipfire.org Git - thirdparty/man-pages.git/blobdiff - Makefile
Makefile: CFLAGS: Don't trigger errors for some warnings
[thirdparty/man-pages.git] / Makefile
index 0da0328d879c0751b4181d2c4b22e9e7ce51637a..cea48edae41cc60f6ff8652350971d9fb2efca8d 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -8,7 +8,10 @@
 #   However, when something could be improved, don't follow those.
 # - Uppercase variables, when referring files, refer to files in this repo.
 # - Lowercase variables, when referring files, refer to system files.
-# - Variables starting with '_' refer to absolute paths, including $(DESTDIR).
+# - Lowercase variables starting with '_' refer to absolute paths,
+#   including $(DESTDIR).
+# - Uppercase variables starting with '_' refer to temporary files produced
+#   in $builddir.
 # - Variables ending with '_' refer to a subdir of their parent dir, which
 #   is in a variable of the same name but without the '_'.  The subdir is
 #   named after this project: <*/man>.
 #
 ########################################################################
 
+SHELL := /bin/bash -Eeuo pipefail
+
+
 MAKEFLAGS += --no-print-directory
-MAKEFLAGS += --silent
 MAKEFLAGS += --warn-undefined-variables
 
 
-htmlbuilddir := $(CURDIR)/.html
-HTOPTS :=
+srcdir   := .
+builddir := tmp
+DESTDIR  :=
+prefix   := /usr/local
+
+SYSCONFDIR  := $(srcdir)/etc
+TMACDIR     := $(SYSCONFDIR)/groff/tmac
+MANDIR      := $(srcdir)
+MAN0DIR     := $(MANDIR)/man0
+MAN1DIR     := $(MANDIR)/man1
+MAN2DIR     := $(MANDIR)/man2
+MAN3DIR     := $(MANDIR)/man3
+MAN4DIR     := $(MANDIR)/man4
+MAN5DIR     := $(MANDIR)/man5
+MAN6DIR     := $(MANDIR)/man6
+MAN7DIR     := $(MANDIR)/man7
+MAN8DIR     := $(MANDIR)/man8
 
-DESTDIR :=
-prefix := /usr/local
 datarootdir := $(prefix)/share
-docdir := $(datarootdir)/doc
-MANDIR := $(CURDIR)
-mandir := $(datarootdir)/man
-MAN1DIR := $(MANDIR)/man1
-MAN2DIR := $(MANDIR)/man2
-MAN3DIR := $(MANDIR)/man3
-MAN4DIR := $(MANDIR)/man4
-MAN5DIR := $(MANDIR)/man5
-MAN6DIR := $(MANDIR)/man6
-MAN7DIR := $(MANDIR)/man7
-MAN8DIR := $(MANDIR)/man8
-man1dir := $(mandir)/man1
-man2dir := $(mandir)/man2
-man3dir := $(mandir)/man3
-man4dir := $(mandir)/man4
-man5dir := $(mandir)/man5
-man6dir := $(mandir)/man6
-man7dir := $(mandir)/man7
-man8dir := $(mandir)/man8
-manext := \.[0-9]
-man1ext := .1
-man2ext := .2
-man3ext := .3
-man4ext := .4
-man5ext := .5
-man6ext := .6
-man7ext := .7
-man8ext := .8
-htmldir := $(docdir)
-htmldir_ := $(htmldir)/man
-htmlext := .html
-
-INSTALL := install
+docdir      := $(datarootdir)/doc
+mandir      := $(datarootdir)/man
+man0dir     := $(mandir)/man0
+man1dir     := $(mandir)/man1
+man2dir     := $(mandir)/man2
+man3dir     := $(mandir)/man3
+man4dir     := $(mandir)/man4
+man5dir     := $(mandir)/man5
+man6dir     := $(mandir)/man6
+man7dir     := $(mandir)/man7
+man8dir     := $(mandir)/man8
+manext      := \.[0-9]
+man0ext     := .0
+man1ext     := .1
+man2ext     := .2
+man3ext     := .3
+man4ext     := .4
+man5ext     := .5
+man6ext     := .6
+man7ext     := .7
+man8ext     := .8
+htmldir     := $(docdir)
+htmlext     := .html
+
+htmldir_    := $(htmldir)/man
+
+_LINTDIR    := $(builddir)/lint
+_HTMLDIR    := $(builddir)/html
+_SRCDIR     := $(builddir)/src
+
+_mandir     := $(DESTDIR)$(mandir)
+_htmldir    := $(DESTDIR)$(htmldir_)
+
+
+clang-tidy_config       := $(SYSCONFDIR)/clang-tidy/config.yaml
+DEFAULT_CLANG-TIDYFLAGS := --config-file=$(clang-tidy_config)
+DEFAULT_CLANG-TIDYFLAGS += --quiet
+DEFAULT_CLANG-TIDYFLAGS += --use-color
+EXTRA_CLANG-TIDYFLAGS   :=
+CLANG-TIDYFLAGS         := $(DEFAULT_CLANG-TIDYFLAGS) $(EXTRA_CLANG-TIDYFLAGS)
+
+DEFAULT_IWYUFLAGS := -Xiwyu --no_fwd_decls
+DEFAULT_IWYUFLAGS += -Xiwyu --error
+EXTRA_IWYUFLAGS   :=
+IWYUFLAGS         := $(DEFAULT_IWYUFLAGS) $(EXTRA_IWYUFLAGS)
+
+DEFAULT_CPPFLAGS :=
+EXTRA_CPPFLAGS   :=
+CPPFLAGS         := $(DEFAULT_CPPFLAGS) $(EXTRA_CPPFLAGS)
+
+DEFAULT_CFLAGS := -std=gnu17
+DEFAULT_CFLAGS += -Wall
+DEFAULT_CFLAGS += -Wextra
+DEAFULT_CFLAGS += -Wstrict-prototypes
+DEFAULT_CFLAGS += -Werror
+DEFAULT_CFLAGS += -Wno-error=unused-parameter
+DEFAULT_CFLAGS += -Wno-error=sign-compare
+DEFAULT_CFLAGS += -Wno-error=format
+DEFAULT_CFLAGS += -Wno-error=uninitialized
+EXTRA_CFLAGS   :=
+CFLAGS         := $(DEFAULT_CFLAGS) $(EXTRA_CFLAGS)
+
+DEFAULT_LDFLAGS := -Wl,--as-needed
+DEFAULT_LDFLAGS += -Wl,--no-allow-shlib-undefined
+DEFAULT_LDFLAGS += -Wl,--no-copy-dt-needed-entries
+DEFAULT_LDFLAGS += -Wl,--no-undefined
+EXTRA_LDFLAGS   :=
+LDFLAGS         := $(DEFAULT_LDFLAGS) $(EXTRA_LDFLAGS)
+
+DEFAULT_LDLIBS := -lc
+EXTRA_LDLIBS   :=
+LDLIBS         := $(DEFAULT_LDLIBS) $(EXTRA_LDLIBS)
+
+TMACFILES            := $(sort $(shell find $(TMACDIR) -not -type d))
+TMACNAMES            := $(basename $(notdir $(TMACFILES)))
+GROFF_CHECKSTYLE_LVL := 3
+DEFAULT_GROFFFLAGS   := -man
+DEFAULT_GROFFFLAGS   += -t
+DEFAULT_GROFFFLAGS   += -M $(TMACDIR)
+DEFAULT_GROFFFLAGS   += $(foreach x,$(TMACNAMES),-m $(x))
+DEFAULT_GROFFFLAGS   += -rCHECKSTYLE=$(GROFF_CHECKSTYLE_LVL)
+DEFAULT_GROFFFLAGS   += -ww
+EXTRA_GROFFFLAGS     :=
+GROFFFLAGS           := $(DEFAULT_GROFFFLAGS) $(EXTRA_GROFFFLAGS)
+
+DEFAULT_MANDOCFLAGS := -man
+DEFAULT_MANDOCFLAGS += -Tlint
+EXTRA_MANDOCFLAGS   :=
+MANDOCFLAGS         := $(DEFAULT_MANDOCFLAGS) $(EXTRA_MANDOCFLAGS)
+
+DEFAULT_MAN2HTMLFLAGS :=
+EXTRA_MAN2HTMLFLAGS   :=
+MAN2HTMLFLAGS         := $(DEFAULT_MAN2HTMLFLAGS) $(EXTRA_MAN2HTMLFLAGS)
+
+
+INSTALL      := install
 INSTALL_DATA := $(INSTALL) -m 644
-INSTALL_DIR := $(INSTALL) -m 755 -d
-RM := rm
-RMDIR := rmdir --ignore-fail-on-non-empty
+INSTALL_DIR  := $(INSTALL) -m 755 -d
+MKDIR        := mkdir -p
+RM           := rm
+RMDIR        := rmdir --ignore-fail-on-non-empty
+CLANG-TIDY   := clang-tidy
+IWYU         := iwyu
+CC           := cc
+LD           := $(CC) $(CFLAGS)
+GROFF        := groff
+MAN          := man
+MANDOC       := mandoc
+MAN2HTML     := man2html
+
 
-MAN_SECTIONS := 1 2 3 4 5 6 7 8
+MAN_SECTIONS := 1 2 3 4 5 6 7 8
 
 
 .PHONY: all
@@ -82,17 +173,16 @@ all:
        $(MAKE) uninstall
        $(MAKE) install
 
-
 %/.:
-       $(info -        INSTALL $(@D))
+       $(info INSTALL  $(@D)/)
        $(INSTALL_DIR) $(@D)
 
 %-rm:
-       $(info -        RM      $*)
+       $(info RM       $*)
        $(RM) $*
 
 %-rmdir:
-       $(info -        RMDIR   $(@D))
+       $(info RMDIR    $(@D))
        $(RMDIR) $(@D)
 
 
@@ -110,38 +200,64 @@ uninstall remove: uninstall-man
 
 .PHONY: clean
 clean:
-       find man?/ -type f \
-       |while read f; do \
-               rm -f "$(htmlbuilddir)/$$f".*; \
-       done;
+       $(RM) -rf $(builddir)
+
 
 ########################################################################
 # man
 
 MANPAGES   := $(sort $(shell find $(MANDIR)/man?/ -type f | grep '$(manext)$$'))
-_manpages  := $(patsubst $(MANDIR)/%,$(DESTDIR)$(mandir)/%,$(MANPAGES))
-_man1pages := $(filter %$(man1ext),$(_manpages))
-_man2pages := $(filter %$(man2ext),$(_manpages))
-_man3pages := $(filter %$(man3ext),$(_manpages))
-_man4pages := $(filter %$(man4ext),$(_manpages))
-_man5pages := $(filter %$(man5ext),$(_manpages))
-_man6pages := $(filter %$(man6ext),$(_manpages))
-_man7pages := $(filter %$(man7ext),$(_manpages))
-_man8pages := $(filter %$(man8ext),$(_manpages))
-
-MANDIRS  := $(sort $(shell find $(MANDIR)/man? -type d))
-_mandirs := $(patsubst $(MANDIR)/%,$(DESTDIR)$(mandir)/%/.,$(MANDIRS))
-_man1dir := $(filter %man1/.,$(_mandirs))
-_man2dir := $(filter %man2/.,$(_mandirs))
-_man3dir := $(filter %man3/.,$(_mandirs))
-_man4dir := $(filter %man4/.,$(_mandirs))
-_man5dir := $(filter %man5/.,$(_mandirs))
-_man6dir := $(filter %man6/.,$(_mandirs))
-_man7dir := $(filter %man7/.,$(_mandirs))
-_man8dir := $(filter %man8/.,$(_mandirs))
-_mandir  := $(DESTDIR)$(mandir)/.
-
+LINTMAN    := $(sort $(shell find $(MANDIR)/man?/ -type f | grep '$(manext)$$' \
+                             | xargs grep -l '^\.TH '))
+_HTMLPAGES  := $(patsubst $(MANDIR)/%,$(_HTMLDIR)/%.html,$(MANPAGES))
+_htmlpages  := $(patsubst $(_HTMLDIR)/%,$(_htmldir)/%,$(_HTMLPAGES))
+_manpages   := $(patsubst $(MANDIR)/%,$(_mandir)/%,$(MANPAGES))
+_man0pages  := $(filter %$(man0ext),$(_manpages))
+_man1pages  := $(filter %$(man1ext),$(_manpages))
+_man2pages  := $(filter %$(man2ext),$(_manpages))
+_man3pages  := $(filter %$(man3ext),$(_manpages))
+_man4pages  := $(filter %$(man4ext),$(_manpages))
+_man5pages  := $(filter %$(man5ext),$(_manpages))
+_man6pages  := $(filter %$(man6ext),$(_manpages))
+_man7pages  := $(filter %$(man7ext),$(_manpages))
+_man8pages  := $(filter %$(man8ext),$(_manpages))
+_LINT_groff :=$(patsubst $(MANDIR)/%,$(_LINTDIR)/%.lint.groff.touch,$(LINTMAN))
+_LINT_mandoc:=$(patsubst $(MANDIR)/%,$(_LINTDIR)/%.lint.mandoc.touch,$(LINTMAN))
+_SRCPAGEDIRS:=$(patsubst $(MANDIR)/%,$(_SRCDIR)/%.d,$(LINTMAN))
+_UNITS_src  :=$(sort $(patsubst $(MANDIR)/%,$(_SRCDIR)/%,$(shell \
+               find $(MANDIR)/man?/ -type f \
+               | grep '$(manext)$$' \
+               | xargs grep -l '^\.TH ' \
+               | while read m; do \
+                       <$$m \
+                       sed -n "s,^\... SRC BEGIN (\(.*.[ch]\))$$,$$m.d/\1,p"; \
+               done)))
+_UNITS_h    := $(filter %.h,$(_UNITS_src))
+_UNITS_c    := $(filter %.c,$(_UNITS_src))
+_UNITS_o    := $(patsubst %.c,%.o,$(_UNITS_c))
+_UNITS_bin  := $(patsubst %.c,%,$(_UNITS_c))
+_LINT_clang-tidy := $(patsubst %.c,%.lint.clang-tidy.touch,$(_UNITS_c))
+_LINT_iwyu       := $(patsubst %.c,%.lint.iwyu.touch,$(_UNITS_c))
+
+MANDIRS   := $(sort $(shell find $(MANDIR)/man? -type d))
+_HTMLDIRS  := $(patsubst $(MANDIR)/%,$(_HTMLDIR)/%/.,$(MANDIRS))
+_LINTDIRS  := $(patsubst $(MANDIR)/%,$(_LINTDIR)/%/.,$(MANDIRS))
+_SRCDIRS   := $(patsubst $(MANDIR)/%,$(_SRCDIR)/%/.,$(MANDIRS))
+_htmldirs := $(patsubst $(_HTMLDIR)/%,$(_htmldir)/%,$(_HTMLDIRS))
+_mandirs  := $(patsubst $(MANDIR)/%,$(_mandir)/%/.,$(MANDIRS))
+_man0dir  := $(filter %man0/.,$(_mandirs))
+_man1dir  := $(filter %man1/.,$(_mandirs))
+_man2dir  := $(filter %man2/.,$(_mandirs))
+_man3dir  := $(filter %man3/.,$(_mandirs))
+_man4dir  := $(filter %man4/.,$(_mandirs))
+_man5dir  := $(filter %man5/.,$(_mandirs))
+_man6dir  := $(filter %man6/.,$(_mandirs))
+_man7dir  := $(filter %man7/.,$(_mandirs))
+_man8dir  := $(filter %man8/.,$(_mandirs))
+
+_htmlpages_rm := $(addsuffix -rm,$(wildcard $(_htmlpages)))
 _manpages_rm  := $(addsuffix -rm,$(wildcard $(_manpages)))
+_man0pages_rm := $(filter %$(man0ext)-rm,$(_manpages_rm))
 _man1pages_rm := $(filter %$(man1ext)-rm,$(_manpages_rm))
 _man2pages_rm := $(filter %$(man2ext)-rm,$(_manpages_rm))
 _man3pages_rm := $(filter %$(man3ext)-rm,$(_manpages_rm))
@@ -151,16 +267,19 @@ _man6pages_rm := $(filter %$(man6ext)-rm,$(_manpages_rm))
 _man7pages_rm := $(filter %$(man7ext)-rm,$(_manpages_rm))
 _man8pages_rm := $(filter %$(man8ext)-rm,$(_manpages_rm))
 
-_mandirs_rmdir := $(addsuffix -rmdir,$(wildcard $(_mandirs)))
-_man1dir_rmdir := $(addsuffix -rmdir,$(wildcard $(_man1dir)))
-_man2dir_rmdir := $(addsuffix -rmdir,$(wildcard $(_man2dir)))
-_man3dir_rmdir := $(addsuffix -rmdir,$(wildcard $(_man3dir)))
-_man4dir_rmdir := $(addsuffix -rmdir,$(wildcard $(_man4dir)))
-_man5dir_rmdir := $(addsuffix -rmdir,$(wildcard $(_man5dir)))
-_man6dir_rmdir := $(addsuffix -rmdir,$(wildcard $(_man6dir)))
-_man7dir_rmdir := $(addsuffix -rmdir,$(wildcard $(_man7dir)))
-_man8dir_rmdir := $(addsuffix -rmdir,$(wildcard $(_man8dir)))
-_mandir_rmdir  := $(addsuffix -rmdir,$(wildcard $(_mandir)))
+_htmldirs_rmdir := $(addsuffix -rmdir,$(wildcard $(_htmldirs)))
+_mandirs_rmdir  := $(addsuffix -rmdir,$(wildcard $(_mandirs)))
+_man0dir_rmdir  := $(addsuffix -rmdir,$(wildcard $(_man0dir)))
+_man1dir_rmdir  := $(addsuffix -rmdir,$(wildcard $(_man1dir)))
+_man2dir_rmdir  := $(addsuffix -rmdir,$(wildcard $(_man2dir)))
+_man3dir_rmdir  := $(addsuffix -rmdir,$(wildcard $(_man3dir)))
+_man4dir_rmdir  := $(addsuffix -rmdir,$(wildcard $(_man4dir)))
+_man5dir_rmdir  := $(addsuffix -rmdir,$(wildcard $(_man5dir)))
+_man6dir_rmdir  := $(addsuffix -rmdir,$(wildcard $(_man6dir)))
+_man7dir_rmdir  := $(addsuffix -rmdir,$(wildcard $(_man7dir)))
+_man8dir_rmdir  := $(addsuffix -rmdir,$(wildcard $(_man8dir)))
+_mandir_rmdir   := $(addsuffix -rmdir,$(wildcard $(_mandir)/.))
+_htmldir_rmdir  := $(addsuffix -rmdir,$(wildcard $(_htmldir)/.))
 
 install_manX     := $(foreach x,$(MAN_SECTIONS),install-man$(x))
 installdirs_manX := $(foreach x,$(MAN_SECTIONS),installdirs-man$(x))
@@ -168,13 +287,13 @@ uninstall_manX   := $(foreach x,$(MAN_SECTIONS),uninstall-man$(x))
 
 
 .SECONDEXPANSION:
-$(_manpages): $(DESTDIR)$(mandir)/man%: $(MANDIR)/man% | $$(@D)/.
-       $(info -        INSTALL $@)
+$(_manpages): $(_mandir)/man%: $(MANDIR)/man% | $$(@D)/.
+       $(info INSTALL  $@)
        $(INSTALL_DATA) -T $< $@
 
-$(_mandirs): %/.: | $$(dir %). $(_mandir)
+$(_mandirs): %/.: | $$(dir %). $(_mandir)/.
 
-$(_mandirs_rmdir): $(DESTDIR)$(mandir)/man%/.-rmdir: $$(_man%pages_rm) FORCE
+$(_mandirs_rmdir): $(_mandir)/man%/.-rmdir: $$(_man%pages_rm) FORCE
 $(_mandir_rmdir): $(uninstall_manX) FORCE
 
 
@@ -187,7 +306,7 @@ install-man: $(install_manX)
        @:
 
 .PHONY: $(installdirs_manX)
-$(installdirs_manX): installdirs-man%: $$(_man%dir) $(_mandir)
+$(installdirs_manX): installdirs-man%: $$(_man%dir)
        @:
 
 .PHONY: installdirs-man
@@ -203,72 +322,140 @@ uninstall-man: $(_mandir_rmdir) $(uninstall_manX)
        @:
 
 
+########################################################################
+# src
+
+$(_SRCPAGEDIRS): $(_SRCDIR)/%.d: $(MANDIR)/% | $$(@D)/.
+       $(info MKDIR    $@)
+       $(MKDIR) $@
+       touch $@
+
+$(_UNITS_src): $$(patsubst $(_SRCDIR)/%.d,$(MANDIR)/%,$$(@D)) | $$(@D)
+$(_UNITS_c):   $$(filter $$(@D)/%.h,$(_UNITS_h))
+$(_UNITS_src):
+       $(info SED      $@)
+       <$< \
+       sed -n \
+               -e '/^\.TH/,/^\.SH/{/^\.SH/!p}' \
+               -e '/^\.SH EXAMPLES/p' \
+               -e "/^\... SRC BEGIN ($(@F))$$/,/^\... SRC END$$/p" \
+       | $(MAN) -P cat -l - \
+       | sed '/^[^ ]/d' \
+       | sed 's/^       //' \
+       >$@
+
+$(_UNITS_o): $(_SRCDIR)/%.o: $(_SRCDIR)/%.c
+       $(info CC       $@)
+       $(CC) -c $(CPPFLAGS) $(CFLAGS) -o $@ $<
+
+$(_UNITS_bin): $(_SRCDIR)/%: $(_SRCDIR)/%.o
+       $(info LD       $@)
+       $(LD) $(LDFLAGS) -o $@ $< $(LDLIBS)
+
+$(_SRCDIRS): %/.: | $$(dir %). $(_SRCDIR)/.
+
+
+.PHONY: build-src src
+build-src src: $(_UNITS_c) | builddirs-src
+       @:
+
+.PHONY: build-cc
+build-cc: $(_UNITS_o)
+       @:
+
+.PHONY: build-ld
+build-ld: $(_UNITS_bin)
+       @:
+
+.PHONY: builddirs-src
+builddirs-src: $(_SRCDIRS)
+       @:
+
+
+########################################################################
+# lint
+
+linters := clang-tidy iwyu groff mandoc
+lint    := $(foreach x,$(linters),lint-$(x))
+
+$(_LINT_clang-tidy): %.lint.clang-tidy.touch: %.c
+       $(info LINT (clang-tidy)        $@)
+       $(CLANG-TIDY) $(CLANG-TIDYFLAGS) $< -- $(CPPFLAGS) $(CFLAGS) 2>&1 \
+       | sed '/generated\.$$/d'
+       touch $@
+
+$(_LINT_iwyu): %.lint.iwyu.touch: %.c
+       $(info LINT (iwyu)      $@)
+       $(IWYU) $(IWYUFLAGS) $(CPPFLAGS) $(CFLAGS) $<
+       touch $@
+
+$(_LINT_groff): $(_LINTDIR)/%.lint.groff.touch: $(MANDIR)/% | $$(@D)/.
+       $(info LINT (groff)     $@)
+       $(GROFF) $(GROFFFLAGS) -z $<
+       touch $@
+
+$(_LINT_mandoc): $(_LINTDIR)/%.lint.mandoc.touch: $(MANDIR)/% | $$(@D)/.
+       $(info LINT (mandoc)    $@)
+       $(MANDOC) $(MANDOCFLAGS) $<
+       touch $@
+
+$(_LINTDIRS): %/.: | $$(dir %). $(_LINTDIR)/.
+
+
+.PHONY: $(lint)
+$(lint): lint-%: $$(_LINT_%) | lintdirs
+       @:
+
+.PHONY: lintdirs
+lintdirs: $(_LINTDIRS) $(_SRCDIRS)
+       @:
+
+.PHONY: lint
+lint: $(lint)
+       @:
+
+
 ########################################################################
 # html
 
 # Use with
-#  make HTOPTS=whatever html
+#  make MAN2HTMLFLAGS=whatever html
 # The sed removes the lines "Content-type: text/html\n\n"
-.PHONY: html
-html: | builddirs-html
-       find man?/ -type f \
-       |while read f; do \
-               man2html $(HTOPTS) "$$f" \
-               |sed -e '1,2d' \
-               >"$(htmlbuilddir)/$${f}$(htmlext)" \
-                       || exit $$?; \
-       done;
+$(_HTMLPAGES): $(_HTMLDIR)/%.html: $(MANDIR)/% | $$(@D)/.
+       $(info MAN2HTML $@)
+       $(MAN2HTML) $(MAN2HTMLFLAGS) $< | sed -e 1,2d >$@
+
+$(_HTMLDIRS): %/.: | $$(dir %). $(_HTMLDIR)/.
+
+$(_htmlpages): $(_htmldir)/%: $(_HTMLDIR)/% | $$(@D)/.
+       $(info INSTALL  $@)
+       $(INSTALL_DATA) -T $< $@
+
+$(_htmldirs): %/.: | $$(dir %). $(_htmldir)/.
+
+
+.PHONY: build-html html
+build-html html: $(_HTMLPAGES) | builddirs-html
+       @:
 
 .PHONY: builddirs-html
-builddirs-html:
-       find man?/ -type d \
-       |while read d; do \
-               $(INSTALL_DIR) "$(htmlbuilddir)/$$d" || exit $$?; \
-       done;
+builddirs-html: $(_HTMLDIRS)
+       @:
 
 .PHONY: install-html
-install-html: | installdirs-html
-       cd $(htmlbuilddir) && \
-       find man?/ -type f \
-       |while read f; do \
-               $(INSTALL_DATA) -T "$$f" "$(DESTDIR)$(htmldir_)/$$f" || exit $$?; \
-       done;
+install-html: $(_htmlpages) | installdirs-html
+       @:
 
 .PHONY: installdirs-html
-installdirs-html:
-       find man?/ -type d \
-       |while read d; do \
-               $(INSTALL_DIR) "$(DESTDIR)$(htmldir_)/$$d" || exit $$?; \
-       done;
+installdirs-html: $(_htmldirs)
+       @:
 
 .PHONY: uninstall-html
-uninstall-html:
-       find man?/ -type f \
-       |while read f; do \
-               rm -f "$(DESTDIR)$(htmldir_)/$$f".* || exit $$?; \
-       done;
-
+uninstall-html: $(_htmldir_rmdir) $(_htmldirs_rmdir) $(_htmlpages_rm)
+       @:
 
-########################################################################
-# tests
-
-# Check if groff reports warnings (may be words of sentences not displayed)
-# from https://lintian.debian.org/tags/groff-message.html
-.PHONY: check-groff-warnings
-check-groff-warnings:
-       GROFF_LOG="$$(mktemp --tmpdir manpages-checksXXXX)" || exit $$?; \
-       for i in man?/*.[1-9]; \
-       do \
-               if grep -q 'SH.*NAME' "$$i"; then \
-                       LC_ALL=en_US.UTF-8 MANWIDTH=80 man --warnings -E UTF-8 -l "$$i" > /dev/null 2>| "$$GROFF_LOG"; \
-                       [ -s "$$GROFF_LOG" ] && { echo "$$i: "; cat "$$GROFF_LOG"; echo; }; \
-               fi; \
-       done; \
-       rm -f "$$GROFF_LOG"
-
-# someone might also want to look at /var/catman/cat2 or so ...
-# a problem is that the location of cat pages varies a lot
 
 ########################################################################
 
+$(V).SILENT:
 FORCE: