]> git.ipfire.org Git - thirdparty/man-pages.git/blob - Makefile
Makefile, etc/clang-tidy/config.yaml: lint-clang-tidy: Add target to run clang-tidy...
[thirdparty/man-pages.git] / Makefile
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:
6 #
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 # - Lowercase variables starting with '_' refer to absolute paths,
12 # including $(DESTDIR).
13 # - Uppercase variables starting with '_' refer to temporary files produced
14 # in $builddir.
15 # - Variables ending with '_' refer to a subdir of their parent dir, which
16 # is in a variable of the same name but without the '_'. The subdir is
17 # named after this project: <*/man>.
18 # - Variables ending in '_rm' refer to files that can be removed (exist).
19 # - Variables ending in '_rmdir' refer to dirs that can be removed (exist).
20 # - Targets of the form '%-rm' remove their corresponding file '%'.
21 # - Targets of the form '%/.-rmdir' remove their corresponding dir '%/'.
22 # - Targets of the form '%/.' create their corresponding directory '%/'.
23 # - Every file or directory to be created depends on its parent directory.
24 # This avoids race conditions caused by `mkdir -p`. Only the root
25 # directories are created with parents.
26 # - The 'FORCE' target is used to make phony some variables that can't be
27 # .PHONY to avoid some optimizations.
28 #
29 ########################################################################
30
31 MAKEFLAGS += --no-print-directory
32 MAKEFLAGS += --warn-undefined-variables
33
34
35 srcdir := .
36 builddir := tmp
37 DESTDIR :=
38 prefix := /usr/local
39
40 SYSCONFDIR := $(srcdir)/etc
41 TMACDIR := $(SYSCONFDIR)/groff/tmac
42 MANDIR := $(srcdir)
43 MAN0DIR := $(MANDIR)/man0
44 MAN1DIR := $(MANDIR)/man1
45 MAN2DIR := $(MANDIR)/man2
46 MAN3DIR := $(MANDIR)/man3
47 MAN4DIR := $(MANDIR)/man4
48 MAN5DIR := $(MANDIR)/man5
49 MAN6DIR := $(MANDIR)/man6
50 MAN7DIR := $(MANDIR)/man7
51 MAN8DIR := $(MANDIR)/man8
52
53 datarootdir := $(prefix)/share
54 docdir := $(datarootdir)/doc
55 mandir := $(datarootdir)/man
56 man0dir := $(mandir)/man0
57 man1dir := $(mandir)/man1
58 man2dir := $(mandir)/man2
59 man3dir := $(mandir)/man3
60 man4dir := $(mandir)/man4
61 man5dir := $(mandir)/man5
62 man6dir := $(mandir)/man6
63 man7dir := $(mandir)/man7
64 man8dir := $(mandir)/man8
65 manext := \.[0-9]
66 man0ext := .0
67 man1ext := .1
68 man2ext := .2
69 man3ext := .3
70 man4ext := .4
71 man5ext := .5
72 man6ext := .6
73 man7ext := .7
74 man8ext := .8
75 htmldir := $(docdir)
76 htmlext := .html
77
78 htmldir_ := $(htmldir)/man
79
80 _LINTDIR := $(builddir)/lint
81 _HTMLDIR := $(builddir)/html
82 _SRCDIR := $(builddir)/src
83
84 _mandir := $(DESTDIR)$(mandir)
85 _htmldir := $(DESTDIR)$(htmldir_)
86
87
88 clang-tidy_config := $(SYSCONFDIR)/clang-tidy/config.yaml
89 DEFAULT_CLANG-TIDYFLAGS := --config-file=$(clang-tidy_config)
90 DEFAULT_CLANG-TIDYFLAGS += --quiet
91 DEFAULT_CLANG-TIDYFLAGS += --use-color
92 EXTRA_CLANG-TIDYFLAGS :=
93 CLANG-TIDYFLAGS := $(DEFAULT_CLANG-TIDYFLAGS) $(EXTRA_CLANG-TIDYFLAGS)
94
95 DEFAULT_IWYUFLAGS := -Xiwyu --no_fwd_decls
96 DEFAULT_IWYUFLAGS += -Xiwyu --error
97 EXTRA_IWYUFLAGS :=
98 IWYUFLAGS := $(DEFAULT_IWYUFLAGS) $(EXTRA_IWYUFLAGS)
99
100 DEFAULT_CPPFLAGS :=
101 EXTRA_CPPFLAGS :=
102 CPPFLAGS := $(DEFAULT_CPPFLAGS) $(EXTRA_CPPFLAGS)
103
104 DEFAULT_CFLAGS := -std=gnu17
105 DEFAULT_CFLAGS += -Wall
106 DEFAULT_CFLAGS += -Wextra
107 DEAFULT_CFLAGS += -Wstrict-prototypes
108 DEFAULT_CFLAGS += -Werror
109 EXTRA_CFLAGS :=
110 CFLAGS := $(DEFAULT_CFLAGS) $(EXTRA_CFLAGS)
111
112 DEFAULT_LDFLAGS := -Wl,--as-needed
113 DEFAULT_LDFLAGS += -Wl,--no-allow-shlib-undefined
114 DEFAULT_LDFLAGS += -Wl,--no-copy-dt-needed-entries
115 DEFAULT_LDFLAGS += -Wl,--no-undefined
116 EXTRA_LDFLAGS :=
117 LDFLAGS := $(DEFAULT_LDFLAGS) $(EXTRA_LDFLAGS)
118
119 DEFAULT_LDLIBS := -lc
120 EXTRA_LDLIBS :=
121 LDLIBS := $(DEFAULT_LDLIBS) $(EXTRA_LDLIBS)
122
123 TMACFILES := $(sort $(shell find $(TMACDIR) -not -type d))
124 TMACNAMES := $(basename $(notdir $(TMACFILES)))
125 GROFF_CHECKSTYLE_LVL := 3
126 DEFAULT_GROFFFLAGS := -man
127 DEFAULT_GROFFFLAGS += -t
128 DEFAULT_GROFFFLAGS += -M $(TMACDIR)
129 DEFAULT_GROFFFLAGS += $(foreach x,$(TMACNAMES),-m $(x))
130 DEFAULT_GROFFFLAGS += -rCHECKSTYLE=$(GROFF_CHECKSTYLE_LVL)
131 DEFAULT_GROFFFLAGS += -ww
132 EXTRA_GROFFFLAGS :=
133 GROFFFLAGS := $(DEFAULT_GROFFFLAGS) $(EXTRA_GROFFFLAGS)
134
135 DEFAULT_MANDOCFLAGS := -man
136 DEFAULT_MANDOCFLAGS += -Tlint
137 EXTRA_MANDOCFLAGS :=
138 MANDOCFLAGS := $(DEFAULT_MANDOCFLAGS) $(EXTRA_MANDOCFLAGS)
139
140 DEFAULT_MAN2HTMLFLAGS :=
141 EXTRA_MAN2HTMLFLAGS :=
142 MAN2HTMLFLAGS := $(DEFAULT_MAN2HTMLFLAGS) $(EXTRA_MAN2HTMLFLAGS)
143
144
145 INSTALL := install
146 INSTALL_DATA := $(INSTALL) -m 644
147 INSTALL_DIR := $(INSTALL) -m 755 -d
148 MKDIR := mkdir -p
149 RM := rm
150 RMDIR := rmdir --ignore-fail-on-non-empty
151 CLANG-TIDY := clang-tidy
152 IWYU := iwyu
153 CC := cc
154 LD := $(CC) $(CFLAGS)
155 GROFF := groff
156 MAN := man
157 MANDOC := mandoc
158 MAN2HTML := man2html
159
160
161 MAN_SECTIONS := 0 1 2 3 4 5 6 7 8
162
163
164 .PHONY: all
165 all:
166 $(MAKE) uninstall
167 $(MAKE) install
168
169 %/.:
170 $(info INSTALL $(@D)/)
171 $(INSTALL_DIR) $(@D)
172
173 %-rm:
174 $(info RM $*)
175 $(RM) $*
176
177 %-rmdir:
178 $(info RMDIR $(@D))
179 $(RMDIR) $(@D)
180
181
182 .PHONY: install
183 install: install-man | installdirs
184 @:
185
186 .PHONY: installdirs
187 installdirs: | installdirs-man
188 @:
189
190 .PHONY: uninstall remove
191 uninstall remove: uninstall-man
192 @:
193
194 .PHONY: clean
195 clean:
196 $(RM) -rf $(builddir)
197
198
199 ########################################################################
200 # man
201
202 MANPAGES := $(sort $(shell find $(MANDIR)/man?/ -type f | grep '$(manext)$$'))
203 LINTMAN := $(sort $(shell find $(MANDIR)/man?/ -type f | grep '$(manext)$$' \
204 | xargs grep -l '^\.TH '))
205 _HTMLPAGES := $(patsubst $(MANDIR)/%,$(_HTMLDIR)/%.html,$(MANPAGES))
206 _htmlpages := $(patsubst $(_HTMLDIR)/%,$(_htmldir)/%,$(_HTMLPAGES))
207 _manpages := $(patsubst $(MANDIR)/%,$(_mandir)/%,$(MANPAGES))
208 _man0pages := $(filter %$(man0ext),$(_manpages))
209 _man1pages := $(filter %$(man1ext),$(_manpages))
210 _man2pages := $(filter %$(man2ext),$(_manpages))
211 _man3pages := $(filter %$(man3ext),$(_manpages))
212 _man4pages := $(filter %$(man4ext),$(_manpages))
213 _man5pages := $(filter %$(man5ext),$(_manpages))
214 _man6pages := $(filter %$(man6ext),$(_manpages))
215 _man7pages := $(filter %$(man7ext),$(_manpages))
216 _man8pages := $(filter %$(man8ext),$(_manpages))
217 _LINT_groff :=$(patsubst $(MANDIR)/%,$(_LINTDIR)/%.lint.groff.touch,$(LINTMAN))
218 _LINT_mandoc:=$(patsubst $(MANDIR)/%,$(_LINTDIR)/%.lint.mandoc.touch,$(LINTMAN))
219 _SRCPAGEDIRS:=$(patsubst $(MANDIR)/%,$(_SRCDIR)/%.d,$(LINTMAN))
220 _UNITS_c :=$(sort $(patsubst $(MANDIR)/%,$(_SRCDIR)/%,$(shell \
221 find $(MANDIR)/man?/ -type f \
222 | grep '$(manext)$$' \
223 | xargs grep -l '^\.TH ' \
224 | while read m; do \
225 <$$m \
226 sed -n "s,^\... SRC BEGIN (\(.*.c\))$$,$$m.d/\1,p"; \
227 done)))
228 _UNITS_o := $(patsubst %.c,%.o,$(_UNITS_c))
229 _UNITS_bin := $(patsubst %.c,%,$(_UNITS_c))
230 _LINT_clang-tidy := $(patsubst %.c,%.lint.clang-tidy.touch,$(_UNITS_c))
231 _LINT_iwyu := $(patsubst %.c,%.lint.iwyu.touch,$(_UNITS_c))
232
233 MANDIRS := $(sort $(shell find $(MANDIR)/man? -type d))
234 _HTMLDIRS := $(patsubst $(MANDIR)/%,$(_HTMLDIR)/%/.,$(MANDIRS))
235 _LINTDIRS := $(patsubst $(MANDIR)/%,$(_LINTDIR)/%/.,$(MANDIRS))
236 _SRCDIRS := $(patsubst $(MANDIR)/%,$(_SRCDIR)/%/.,$(MANDIRS))
237 _htmldirs := $(patsubst $(_HTMLDIR)/%,$(_htmldir)/%,$(_HTMLDIRS))
238 _mandirs := $(patsubst $(MANDIR)/%,$(_mandir)/%/.,$(MANDIRS))
239 _man0dir := $(filter %man0/.,$(_mandirs))
240 _man1dir := $(filter %man1/.,$(_mandirs))
241 _man2dir := $(filter %man2/.,$(_mandirs))
242 _man3dir := $(filter %man3/.,$(_mandirs))
243 _man4dir := $(filter %man4/.,$(_mandirs))
244 _man5dir := $(filter %man5/.,$(_mandirs))
245 _man6dir := $(filter %man6/.,$(_mandirs))
246 _man7dir := $(filter %man7/.,$(_mandirs))
247 _man8dir := $(filter %man8/.,$(_mandirs))
248
249 _htmlpages_rm := $(addsuffix -rm,$(wildcard $(_htmlpages)))
250 _manpages_rm := $(addsuffix -rm,$(wildcard $(_manpages)))
251 _man0pages_rm := $(filter %$(man0ext)-rm,$(_manpages_rm))
252 _man1pages_rm := $(filter %$(man1ext)-rm,$(_manpages_rm))
253 _man2pages_rm := $(filter %$(man2ext)-rm,$(_manpages_rm))
254 _man3pages_rm := $(filter %$(man3ext)-rm,$(_manpages_rm))
255 _man4pages_rm := $(filter %$(man4ext)-rm,$(_manpages_rm))
256 _man5pages_rm := $(filter %$(man5ext)-rm,$(_manpages_rm))
257 _man6pages_rm := $(filter %$(man6ext)-rm,$(_manpages_rm))
258 _man7pages_rm := $(filter %$(man7ext)-rm,$(_manpages_rm))
259 _man8pages_rm := $(filter %$(man8ext)-rm,$(_manpages_rm))
260
261 _htmldirs_rmdir := $(addsuffix -rmdir,$(wildcard $(_htmldirs)))
262 _mandirs_rmdir := $(addsuffix -rmdir,$(wildcard $(_mandirs)))
263 _man0dir_rmdir := $(addsuffix -rmdir,$(wildcard $(_man0dir)))
264 _man1dir_rmdir := $(addsuffix -rmdir,$(wildcard $(_man1dir)))
265 _man2dir_rmdir := $(addsuffix -rmdir,$(wildcard $(_man2dir)))
266 _man3dir_rmdir := $(addsuffix -rmdir,$(wildcard $(_man3dir)))
267 _man4dir_rmdir := $(addsuffix -rmdir,$(wildcard $(_man4dir)))
268 _man5dir_rmdir := $(addsuffix -rmdir,$(wildcard $(_man5dir)))
269 _man6dir_rmdir := $(addsuffix -rmdir,$(wildcard $(_man6dir)))
270 _man7dir_rmdir := $(addsuffix -rmdir,$(wildcard $(_man7dir)))
271 _man8dir_rmdir := $(addsuffix -rmdir,$(wildcard $(_man8dir)))
272 _mandir_rmdir := $(addsuffix -rmdir,$(wildcard $(_mandir)/.))
273 _htmldir_rmdir := $(addsuffix -rmdir,$(wildcard $(_htmldir)/.))
274
275 install_manX := $(foreach x,$(MAN_SECTIONS),install-man$(x))
276 installdirs_manX := $(foreach x,$(MAN_SECTIONS),installdirs-man$(x))
277 uninstall_manX := $(foreach x,$(MAN_SECTIONS),uninstall-man$(x))
278
279
280 .SECONDEXPANSION:
281 $(_manpages): $(_mandir)/man%: $(MANDIR)/man% | $$(@D)/.
282 $(info INSTALL $@)
283 $(INSTALL_DATA) -T $< $@
284
285 $(_mandirs): %/.: | $$(dir %). $(_mandir)/.
286
287 $(_mandirs_rmdir): $(_mandir)/man%/.-rmdir: $$(_man%pages_rm) FORCE
288 $(_mandir_rmdir): $(uninstall_manX) FORCE
289
290
291 .PHONY: $(install_manX)
292 $(install_manX): install-man%: $$(_man%pages) | installdirs-man%
293 @:
294
295 .PHONY: install-man
296 install-man: $(install_manX)
297 @:
298
299 .PHONY: $(installdirs_manX)
300 $(installdirs_manX): installdirs-man%: $$(_man%dir)
301 @:
302
303 .PHONY: installdirs-man
304 installdirs-man: $(installdirs_manX)
305 @:
306
307 .PHONY: $(uninstall_manX)
308 $(uninstall_manX): uninstall-man%: $$(_man%pages_rm) $$(_man%dir_rmdir)
309 @:
310
311 .PHONY: uninstall-man
312 uninstall-man: $(_mandir_rmdir) $(uninstall_manX)
313 @:
314
315
316 ########################################################################
317 # src
318
319 $(_SRCPAGEDIRS): $(_SRCDIR)/%.d: $(MANDIR)/% | $$(@D)/.
320 $(info MKDIR $@)
321 $(MKDIR) $@
322 touch $@
323
324 $(_UNITS_c): $$(@D)
325 $(info SED $@)
326 <$(patsubst $(_SRCDIR)/%.d,$(MANDIR)/%,$<) \
327 sed -n \
328 -e '/^\.TH/,/^\.SH/{/^\.SH/!p}' \
329 -e '/^\.SH EXAMPLES/p' \
330 -e "/^\... SRC BEGIN ($(@F))$$/,/^\... SRC END$$/p" \
331 | $(MAN) -P cat -l - \
332 | sed '/^[^ ]/d' \
333 | sed 's/^ //' \
334 >$@ \
335 || exit $$?
336
337 $(_UNITS_o): $(_SRCDIR)/%.o: $(_SRCDIR)/%.c
338 $(info CC $@)
339 $(CC) -c $(CPPFLAGS) $(CFLAGS) -o $@ $<
340
341 $(_UNITS_bin): $(_SRCDIR)/%: $(_SRCDIR)/%.o
342 $(info LD $@)
343 $(LD) $(LDFLAGS) -o $@ $< $(LDLIBS)
344
345 $(_SRCDIRS): %/.: | $$(dir %). $(_SRCDIR)/.
346
347
348 .PHONY: build-src src
349 build-src src: $(_UNITS_c) | builddirs-src
350 @:
351
352 .PHONY: build-cc
353 build-cc: $(_UNITS_o)
354 @:
355
356 .PHONY: build-ld
357 build-ld: $(_UNITS_bin)
358 @:
359
360 .PHONY: builddirs-src
361 builddirs-src: $(_SRCDIRS)
362 @:
363
364
365 ########################################################################
366 # lint
367
368 linters := clang-tidy iwyu groff mandoc
369 lint := $(foreach x,$(linters),lint-$(x))
370
371 $(_LINT_clang-tidy): %.lint.clang-tidy.touch: %.c
372 $(info LINT (clang-tidy) $@)
373 $(CLANG-TIDY) $(CLANG-TIDYFLAGS) $< -- $(CPPFLAGS) $(CFLAGS) 2>&1 \
374 | sed '/generated\.$$/d' || exit $$?
375 touch $@
376
377 $(_LINT_iwyu): %.lint.iwyu.touch: %.c
378 $(info LINT (iwyu) $@)
379 $(IWYU) $(IWYUFLAGS) $(CPPFLAGS) $(CFLAGS) $<
380 touch $@
381
382 $(_LINT_groff): $(_LINTDIR)/%.lint.groff.touch: $(MANDIR)/% | $$(@D)/.
383 $(info LINT (groff) $@)
384 $(GROFF) $(GROFFFLAGS) -z $<
385 touch $@
386
387 $(_LINT_mandoc): $(_LINTDIR)/%.lint.mandoc.touch: $(MANDIR)/% | $$(@D)/.
388 $(info LINT (mandoc) $@)
389 $(MANDOC) $(MANDOCFLAGS) $<
390 touch $@
391
392 $(_LINTDIRS): %/.: | $$(dir %). $(_LINTDIR)/.
393
394
395 .PHONY: $(lint)
396 $(lint): lint-%: $$(_LINT_%) | lintdirs
397 @:
398
399 .PHONY: lintdirs
400 lintdirs: $(_LINTDIRS) $(_SRCDIRS)
401 @:
402
403 .PHONY: lint
404 lint: $(lint)
405 @:
406
407
408 ########################################################################
409 # html
410
411 # Use with
412 # make MAN2HTMLFLAGS=whatever html
413 # The sed removes the lines "Content-type: text/html\n\n"
414 $(_HTMLPAGES): $(_HTMLDIR)/%.html: $(MANDIR)/% | $$(@D)/.
415 $(info MAN2HTML $@)
416 $(MAN2HTML) $(MAN2HTMLFLAGS) $< | sed -e 1,2d >$@ || exit $$?
417
418 $(_HTMLDIRS): %/.: | $$(dir %). $(_HTMLDIR)/.
419
420 $(_htmlpages): $(_htmldir)/%: $(_HTMLDIR)/% | $$(@D)/.
421 $(info INSTALL $@)
422 $(INSTALL_DATA) -T $< $@
423
424 $(_htmldirs): %/.: | $$(dir %). $(_htmldir)/.
425
426
427 .PHONY: build-html html
428 build-html html: $(_HTMLPAGES) | builddirs-html
429 @:
430
431 .PHONY: builddirs-html
432 builddirs-html: $(_HTMLDIRS)
433 @:
434
435 .PHONY: install-html
436 install-html: $(_htmlpages) | installdirs-html
437 @:
438
439 .PHONY: installdirs-html
440 installdirs-html: $(_htmldirs)
441 @:
442
443 .PHONY: uninstall-html
444 uninstall-html: $(_htmldir_rmdir) $(_htmldirs_rmdir) $(_htmlpages_rm)
445 @:
446
447
448 ########################################################################
449
450 $(V).SILENT:
451 FORCE: