symlink.2: Clarify symlink ownership matters when protected_symlinks=1
[man-pages.git] / Makefile
bloba8f5cff0e48b9868e3aa551c2420c3a8befe1fd5
1 ########################################################################
2 # Copyright (C) 2021 Alejandro Colomar <alx.manpages@gmail.com>
3 # SPDX-License-Identifier: GPL-2.0 OR LGPL-2.0
4 ########################################################################
5 # Conventions:
7 # - Follow "Makefile Conventions" from the "GNU Coding Standards" closely.
8 # However, when something could be improved, don't follow those.
9 # - Uppercase variables, when referring files, refer to files in this repo.
10 # - Lowercase variables, when referring files, refer to system files.
11 # - Variables starting with '_' refer to absolute paths, including $(DESTDIR).
12 # - Variables ending with '_' refer to a subdir of their parent dir, which
13 # is in a variable of the same name but without the '_'. The subdir is
14 # named after this project: <*/man>.
15 # - Variables ending in '_rm' refer to files that can be removed (exist).
16 # - Variables ending in '_rmdir' refer to dirs that can be removed (exist).
17 # - Targets of the form '%-rm' remove their corresponding file '%'.
18 # - Targets of the form '%/.-rmdir' remove their corresponding dir '%/'.
19 # - Targets of the form '%/.' create their corresponding directory '%/'.
20 # - Every file or directory to be created depends on its parent directory.
21 # This avoids race conditions caused by `mkdir -p`. Only the root
22 # directories are created with parents.
23 # - The 'FORCE' target is used to make phony some variables that can't be
24 # .PHONY to avoid some optimizations.
26 ########################################################################
28 MAKEFLAGS += --no-print-directory
29 MAKEFLAGS += --silent
30 MAKEFLAGS += --warn-undefined-variables
33 htmlbuilddir := $(CURDIR)/.html
34 HTOPTS :=
36 DESTDIR :=
37 prefix := /usr/local
38 datarootdir := $(prefix)/share
39 docdir := $(datarootdir)/doc
40 MANDIR := $(CURDIR)
41 mandir := $(datarootdir)/man
42 MAN0DIR := $(MANDIR)/man0
43 MAN1DIR := $(MANDIR)/man1
44 MAN2DIR := $(MANDIR)/man2
45 MAN3DIR := $(MANDIR)/man3
46 MAN4DIR := $(MANDIR)/man4
47 MAN5DIR := $(MANDIR)/man5
48 MAN6DIR := $(MANDIR)/man6
49 MAN7DIR := $(MANDIR)/man7
50 MAN8DIR := $(MANDIR)/man8
51 man0dir := $(mandir)/man0
52 man1dir := $(mandir)/man1
53 man2dir := $(mandir)/man2
54 man3dir := $(mandir)/man3
55 man4dir := $(mandir)/man4
56 man5dir := $(mandir)/man5
57 man6dir := $(mandir)/man6
58 man7dir := $(mandir)/man7
59 man8dir := $(mandir)/man8
60 manext := \.[0-9]
61 man0ext := .0
62 man1ext := .1
63 man2ext := .2
64 man3ext := .3
65 man4ext := .4
66 man5ext := .5
67 man6ext := .6
68 man7ext := .7
69 man8ext := .8
70 htmldir := $(docdir)
71 htmldir_ := $(htmldir)/man
72 htmlext := .html
74 INSTALL := install
75 INSTALL_DATA := $(INSTALL) -m 644
76 INSTALL_DIR := $(INSTALL) -m 755 -d
77 RM := rm
78 RMDIR := rmdir --ignore-fail-on-non-empty
80 MAN_SECTIONS := 0 1 2 3 4 5 6 7 8
83 .PHONY: all
84 all:
85 $(MAKE) uninstall
86 $(MAKE) install
89 %/.:
90 $(info - INSTALL $(@D))
91 $(INSTALL_DIR) $(@D)
93 %-rm:
94 $(info - RM $*)
95 $(RM) $*
97 %-rmdir:
98 $(info - RMDIR $(@D))
99 $(RMDIR) $(@D)
102 .PHONY: install
103 install: install-man | installdirs
106 .PHONY: installdirs
107 installdirs: | installdirs-man
110 .PHONY: uninstall remove
111 uninstall remove: uninstall-man
114 .PHONY: clean
115 clean:
116 find man?/ -type f \
117 |while read f; do \
118 rm -f "$(htmlbuilddir)/$$f".*; \
119 done;
121 ########################################################################
122 # man
124 MANPAGES := $(sort $(shell find $(MANDIR)/man?/ -type f | grep '$(manext)$$'))
125 _manpages := $(patsubst $(MANDIR)/%,$(DESTDIR)$(mandir)/%,$(MANPAGES))
126 _man0pages := $(filter %$(man0ext),$(_manpages))
127 _man1pages := $(filter %$(man1ext),$(_manpages))
128 _man2pages := $(filter %$(man2ext),$(_manpages))
129 _man3pages := $(filter %$(man3ext),$(_manpages))
130 _man4pages := $(filter %$(man4ext),$(_manpages))
131 _man5pages := $(filter %$(man5ext),$(_manpages))
132 _man6pages := $(filter %$(man6ext),$(_manpages))
133 _man7pages := $(filter %$(man7ext),$(_manpages))
134 _man8pages := $(filter %$(man8ext),$(_manpages))
136 MANDIRS := $(sort $(shell find $(MANDIR)/man? -type d))
137 _mandirs := $(patsubst $(MANDIR)/%,$(DESTDIR)$(mandir)/%/.,$(MANDIRS))
138 _man0dir := $(filter %man0/.,$(_mandirs))
139 _man1dir := $(filter %man1/.,$(_mandirs))
140 _man2dir := $(filter %man2/.,$(_mandirs))
141 _man3dir := $(filter %man3/.,$(_mandirs))
142 _man4dir := $(filter %man4/.,$(_mandirs))
143 _man5dir := $(filter %man5/.,$(_mandirs))
144 _man6dir := $(filter %man6/.,$(_mandirs))
145 _man7dir := $(filter %man7/.,$(_mandirs))
146 _man8dir := $(filter %man8/.,$(_mandirs))
147 _mandir := $(DESTDIR)$(mandir)/.
149 _manpages_rm := $(addsuffix -rm,$(wildcard $(_manpages)))
150 _man0pages_rm := $(filter %$(man0ext)-rm,$(_manpages_rm))
151 _man1pages_rm := $(filter %$(man1ext)-rm,$(_manpages_rm))
152 _man2pages_rm := $(filter %$(man2ext)-rm,$(_manpages_rm))
153 _man3pages_rm := $(filter %$(man3ext)-rm,$(_manpages_rm))
154 _man4pages_rm := $(filter %$(man4ext)-rm,$(_manpages_rm))
155 _man5pages_rm := $(filter %$(man5ext)-rm,$(_manpages_rm))
156 _man6pages_rm := $(filter %$(man6ext)-rm,$(_manpages_rm))
157 _man7pages_rm := $(filter %$(man7ext)-rm,$(_manpages_rm))
158 _man8pages_rm := $(filter %$(man8ext)-rm,$(_manpages_rm))
160 _mandirs_rmdir := $(addsuffix -rmdir,$(wildcard $(_mandirs)))
161 _man0dir_rmdir := $(addsuffix -rmdir,$(wildcard $(_man0dir)))
162 _man1dir_rmdir := $(addsuffix -rmdir,$(wildcard $(_man1dir)))
163 _man2dir_rmdir := $(addsuffix -rmdir,$(wildcard $(_man2dir)))
164 _man3dir_rmdir := $(addsuffix -rmdir,$(wildcard $(_man3dir)))
165 _man4dir_rmdir := $(addsuffix -rmdir,$(wildcard $(_man4dir)))
166 _man5dir_rmdir := $(addsuffix -rmdir,$(wildcard $(_man5dir)))
167 _man6dir_rmdir := $(addsuffix -rmdir,$(wildcard $(_man6dir)))
168 _man7dir_rmdir := $(addsuffix -rmdir,$(wildcard $(_man7dir)))
169 _man8dir_rmdir := $(addsuffix -rmdir,$(wildcard $(_man8dir)))
170 _mandir_rmdir := $(addsuffix -rmdir,$(wildcard $(_mandir)))
172 install_manX := $(foreach x,$(MAN_SECTIONS),install-man$(x))
173 installdirs_manX := $(foreach x,$(MAN_SECTIONS),installdirs-man$(x))
174 uninstall_manX := $(foreach x,$(MAN_SECTIONS),uninstall-man$(x))
177 .SECONDEXPANSION:
178 $(_manpages): $(DESTDIR)$(mandir)/man%: $(MANDIR)/man% | $$(@D)/.
179 $(info - INSTALL $@)
180 $(INSTALL_DATA) -T $< $@
182 $(_mandirs): %/.: | $$(dir %). $(_mandir)
184 $(_mandirs_rmdir): $(DESTDIR)$(mandir)/man%/.-rmdir: $$(_man%pages_rm) FORCE
185 $(_mandir_rmdir): $(uninstall_manX) FORCE
188 .PHONY: $(install_manX)
189 $(install_manX): install-man%: $$(_man%pages) | installdirs-man%
192 .PHONY: install-man
193 install-man: $(install_manX)
196 .PHONY: $(installdirs_manX)
197 $(installdirs_manX): installdirs-man%: $$(_man%dir) $(_mandir)
200 .PHONY: installdirs-man
201 installdirs-man: $(installdirs_manX)
204 .PHONY: $(uninstall_manX)
205 $(uninstall_manX): uninstall-man%: $$(_man%pages_rm) $$(_man%dir_rmdir)
208 .PHONY: uninstall-man
209 uninstall-man: $(_mandir_rmdir) $(uninstall_manX)
213 ########################################################################
214 # html
216 # Use with
217 # make HTOPTS=whatever html
218 # The sed removes the lines "Content-type: text/html\n\n"
219 .PHONY: html
220 html: | builddirs-html
221 find man?/ -type f \
222 |while read f; do \
223 man2html $(HTOPTS) "$$f" \
224 |sed -e '1,2d' \
225 >"$(htmlbuilddir)/$${f}$(htmlext)" \
226 || exit $$?; \
227 done;
229 .PHONY: builddirs-html
230 builddirs-html:
231 find man?/ -type d \
232 |while read d; do \
233 $(INSTALL_DIR) "$(htmlbuilddir)/$$d" || exit $$?; \
234 done;
236 .PHONY: install-html
237 install-html: | installdirs-html
238 cd $(htmlbuilddir) && \
239 find man?/ -type f \
240 |while read f; do \
241 $(INSTALL_DATA) -T "$$f" "$(DESTDIR)$(htmldir_)/$$f" || exit $$?; \
242 done;
244 .PHONY: installdirs-html
245 installdirs-html:
246 find man?/ -type d \
247 |while read d; do \
248 $(INSTALL_DIR) "$(DESTDIR)$(htmldir_)/$$d" || exit $$?; \
249 done;
251 .PHONY: uninstall-html
252 uninstall-html:
253 find man?/ -type f \
254 |while read f; do \
255 rm -f "$(DESTDIR)$(htmldir_)/$$f".* || exit $$?; \
256 done;
259 ########################################################################
260 # tests
262 # Check if groff reports warnings (may be words of sentences not displayed)
263 # from https://lintian.debian.org/tags/groff-message.html
264 .PHONY: check-groff-warnings
265 check-groff-warnings:
266 GROFF_LOG="$$(mktemp --tmpdir manpages-checksXXXX)" || exit $$?; \
267 for i in man?/*.[0-9]; \
268 do \
269 if grep -q 'SH.*NAME' "$$i"; then \
270 LC_ALL=en_US.UTF-8 MANWIDTH=80 man --warnings -E UTF-8 -l "$$i" > /dev/null 2>| "$$GROFF_LOG"; \
271 [ -s "$$GROFF_LOG" ] && { echo "$$i: "; cat "$$GROFF_LOG"; echo; }; \
272 fi; \
273 done; \
274 rm -f "$$GROFF_LOG"
276 # someone might also want to look at /var/catman/cat2 or so ...
277 # a problem is that the location of cat pages varies a lot
279 ########################################################################
281 FORCE: