~nabijaczleweli/voreutils

ref: e9db514acd52547bbc9a5f56e64d833163540197 voreutils/Makefile -rw-r--r-- 10.7 KiB
e9db514aнаб Generate index HTML page 5 months ago
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
# SPDX-License-Identifier: 0BSD


CXX ?= c++
MANDOC ?= mandoc
AWK ?= awk
SED ?= sed
SHELLLCHECK ?= shellcheck
SYMLINK ?= n
LTO ?= y
VOREUTILS_VERSION ?= $(shell git describe --always)
# Date modes:
#   * git-global       – git log -1
#   * git-file         – git log -1 $file-at-hand
#   * stat             – stat changed $file-at-hand
#   * constant-epoch   – $VOREUTILS_DATE – seconds since epoch
#   * constant-literal – $VOREUTILS_DATE – must be in "%B %e, %Y" (Fullmonth space-padded-day-number, YYYY) format
VOREUTILS_DATE_MODE ?= git-file
VOREUTILS_DATE ?=
CFLAGS ?=
CPPFLAGS ?=
LDFLAGS ?=
OUTDIR ?= out/
OBJDIR ?= $(OUTDIR)obj/
CMDDIR ?= $(OUTDIR)cmd/
LIBDIR ?= $(OUTDIR)lib/
MANDIR ?= $(OUTDIR)man/
HTMLMANDIR ?= $(OUTDIR)man-html/
VOREUTILS_LIB_PREFIX ?= /usr/lib/voreutils/
HTMLMAN_OUTSIDE_FORMAT ?= https://manpages.debian.org/bullseye/%N.%S
# K/V list of the diff between the default mandoc style and ours; grep for "mandoc compat": https://inbox.vuxu.org/mandoc-discuss/20220529001500.gnxuiiawdegcjwy7@tarta.nabijaczleweli.xyz/T/
HTMLMAN_FONT_OVERRIDES ?= Ar CI  Nm CB


DATE_EPOCH := date $(shell date --version > /dev/null 2>&1 && echo "--date @" || echo "-r ")
STAT_CHANGED := stat $(shell stat -c"%i" /dev/null > /dev/null 2>&1 && echo "-c%Y" || echo "-f%c")

ifeq "$(VOREUTILS_DATE_MODE)" "git-global"
DATE_F := $(shell $(DATE_EPOCH)$(shell git log -1 --no-show-signature --format=%at) +"%B %e, %Y")
else ifeq "$(VOREUTILS_DATE_MODE)" "git-file"
DATE_F  = $(shell $(DATE_EPOCH)$(shell git log -1 --no-show-signature --format=%at "$(1)") +"%B %e, %Y")
else ifeq "$(VOREUTILS_DATE_MODE)" "stat"
DATE_F  = $(shell $(DATE_EPOCH)$(shell $(STAT_CHANGED) "$(1)") +"%B %e, %Y")
else ifeq "$(VOREUTILS_DATE_MODE)" "constant-epoch"
DATE_F := $(shell $(DATE_EPOCH)$(VOREUTILS_DATE) +"%B %e, %Y")
else ifeq "$(VOREUTILS_DATE_MODE)" "constant-literal"
DATE_F := $(VOREUTILS_DATE)
else
$(error VOREUTILS_DATE_MODE=$(VOREUTILS_DATE_MODE) must be any of git-{global,file}, stat, constant-{epoch,literal})
endif

ifeq "$(VOREUTILS_DATE_MODE)" "git-file"
# Same as git-global
INDEX_PAGE_DATE := $(shell $(DATE_EPOCH)$(shell git log -1 --no-show-signature --format=%at) +"%B %e, %Y")
else ifeq "$(VOREUTILS_DATE_MODE)" "stat"
INDEX_PAGE_DATE := $(shell date +"%B %e, %Y")
else
INDEX_PAGE_DATE := $(DATE_F)
endif


ifneq "$(subst constant-,,$(VOREUTILS_DATE_MODE))" "$(VOREUTILS_DATE_MODE)"
ifeq "$(VOREUTILS_DATE)" ""
$(error VOREUTILS_DATE_MODE=$(VOREUTILS_DATE_MODE) and no date specified)
endif
endif


AS_NEEDED := -Wl,--as-needed
SO := .so
SONAME := -soname
SYSTEM := $(shell uname)
ifeq "$(SYSTEM)" "NetBSD"
	#
else ifeq "$(SYSTEM)" "OpenBSD"
	#
else ifeq "$(SYSTEM)" "Darwin"
	AS_NEEDED :=
	SONAME := -install_name
	SO := .dylib
else ifeq "$(SYSTEM)" "Linux"
	CXXSPECIFICCC += -D_FILE_OFFSET_BITS=64
else ifeq "$(SYSTEM)" "SunOS"
	AS_NEEDED :=
	CXXSPECIFICCC += $(shell getconf LFS_CFLAGS)
	CXXSPECIFICLD += $(shell getconf LFS_LDFLAGS) $(shell getconf LFS_LIBS)
else
	#
endif

CXXVER := $(shell $(CXX) --version | head -1)
ifneq "$(findstring clang,$(CXXVER))" ""
	# GCC doesn't have this granularity
	CXXSPECIFICCC += -Wpedantic -Wno-c++20-designator -Wno-c99-extensions -Wno-unknown-warning-option
ifneq "$(findstring Apple,$(CXXVER))" ""
	# TODO: remove if we don't end up using CMSG_SPACE()
	# CMSG_SPACE() is a macro, and it's decidedly constexpr. i don't care if appleclang can't figure that out
	CXXSPECIFICCC += -Wno-vla-extension
endif
	CXXSPECIFICCC += -Wno-gnu-conditional-omitted-operand
	ifeq "$(LTO)" "y"
		CXXSPECIFICLD += -flto=full  # Clang produces .o files with LLVM bitcode, which cannot be linked to if put in .as
	else
		CXXSPECIFICLD +=
	endif
else
	CXXSPECIFICCC += -Wno-missing-field-initializers -fno-common
	ifeq "$(LTO)" "y"
		CXXSPECIFICCC += -flto
	endif
	CXXSPECIFICLD +=
endif

ifeq "$(SYMLINK)" "y"
SYMFLAG := s
endif

CCAR := -g -O3 -pipe -Wall -Wextra -fPIC -fno-math-errno $(CXXSPECIFICCC) $(CFLAGS)  $(shell pkg-config --cflags libselinux 2>/dev/null && echo -DVOREUTILS_LIBSELINUX) $(shell for l in b2 crypto; do pkg-config --cflags "lib$$l" 2>/dev/null; done)
LDAR := $(AS_NEEDED) -L$(OUTDIR)                         $(CXXSPECIFICLD) $(LDFLAGS) $(shell pkg-config --libs   libselinux 2>/dev/null                               ) $(shell for l in b2 crypto; do pkg-config --libs   "lib$$l" 2>/dev/null || echo "-l$$l"; done)
CPPAR = -Iinclude/ -DVOREUTILS_VERSION='"$(VOREUTILS_VERSION)"' -DVOREUTILS_DATE='"$(call DATE_F,$(1))"' -DVOREUTILS_SO='"$(SO)"' -DVOREUTILS_LIB_PREFIX='"$(VOREUTILS_LIB_PREFIX)"' -include vore-id.h $(CPPFLAGS)
BINARIES := $(filter-out cmd/aliases,$(wildcard cmd/*))
LIBRARIES := $(wildcard lib/*)
INCLUDES := $(wildcard include/*)
MANPAGES := $(wildcard man/*.?)


.PHONY : all binaries libraries manpages htmlpages clean test
.SECONDARY:

all : binaries libraries manpages htmlpages
allpages : manpages htmlpages
clean:
	rm -rf $(OUTDIR) $(OBJDIR)

test : binaries libraries
	CMDDIR=$(realpath $(CMDDIR))/ find "tests/" -mindepth 1 -maxdepth 1 -type f            -print -execdir ./{} \; 3>$(OBJDIR)testpsko
	CMDDIR=$(realpath $(CMDDIR))/ find "tests/" -mindepth 2 -maxdepth 2 -type f -name test -print -execdir ./{} \; 3>>$(OBJDIR)testpsko
	@cat $(OBJDIR)testpsko >&2
	@! [ -s $(OBJDIR)testpsko ]

rewrap_mandirs = $(patsubst %.8,man8/%.8,$(patsubst %.7,man7/%.7,$(patsubst %.6,man6/%.6,$(patsubst %.5,man5/%.5,$(patsubst %.4,man4/%.4,$(patsubst %.3,man3/%.3,$(patsubst %.2,man2/%.2,$(patsubst %.1,man1/%.1,$(patsubst %.0,man0/%.0,$(patsubst man/%,%,$(1)))))))))))
binaries : $(patsubst %.sh,%,$(patsubst %.cpp,%,$(patsubst cmd/%,$(CMDDIR)%,$(BINARIES)))) $(OBJDIR)aliases
libraries : $(patsubst %.cpp,%$(SO),$(patsubst lib/%,$(LIBDIR)%,$(LIBRARIES)))
manpages : $(patsubst %,$(MANDIR)%,$(call rewrap_mandirs,$(MANPAGES))) $(OBJDIR)man/aliases
htmlpages : $(patsubst %,$(HTMLMANDIR)%.html,$(call rewrap_mandirs,$(MANPAGES) index.0)) $(OBJDIR)man/aliases $(HTMLMANDIR)style.css


$(OBJDIR)man/aliases : man/aliases
	@mkdir -p $(@D) $(MANDIR) $(HTMLMANDIR)
	$(AWK) '!/^$$/ {                                                                                                       \
		tsec = substr($$1, length($$1));                                                                                     \
		for(i = 2; i <= NF; ++i) {                                                                                           \
			lsec = substr($$i, length($$i));                                                                                   \
			rel = (tsec == lsec) ? "" : "../man" tsec "/";                                                                     \
			print "(mkdir -p man" tsec " man" lsec " && cd man" lsec " && set -x && ln -fs " rel $$1 "$$suff " $$i "$$suff)";  \
		}                                                                                                                    \
	}' $^ > $@
	{ cd $(MANDIR)     && suff=        sh; } < $@
	{ cd $(HTMLMANDIR) && suff=".html" sh; } < $@

# This ordering is suboptimal
$(OBJDIR)aliases : cmd/aliases $(patsubst %.sh,%,$(patsubst %.cpp,%,$(patsubst cmd/%,$(CMDDIR)%,$(BINARIES))))
	@mkdir -p $(@D) $(CMDDIR)
	$(AWK) '!/^$$/ { for(i = 2; i <= NF; ++i) print "ln -f$(SYMFLAG) " $$1 " " $$i }' $< > $@
	{ cd $(CMDDIR) && sh -x; } < $@

# The d-v-o-s string starts at "BSD" (hence the "BSD General Commands Manual" default); we're not BSD, so hide it
# Can't put it at the very top, since man(1) only loads mdoc *after* the first mdoc macro (.Dd in our case)
$(OBJDIR)man/% : man/%
	@mkdir -p $(@D) $(dir $(patsubst %,$(MANDIR)%,$(call rewrap_mandirs,$<)))
	$(AWK) '$$0 == ".Dd" {$$2 = "$(call DATE_F,$<)"}  $$1 == ".Dt" { print ".ds doc-volume-operating-system" }  $$0 == ".Os" {$$2 = "voreutils"; $$3 = "$(VOREUTILS_VERSION)"}  {gsub(/@VOREUTILS_LIB_PREFIX@/, "$(VOREUTILS_LIB_PREFIX)"); gsub(/@VOREUTILS_SO@/, "$(SO)"); sub(/^\^/, "\\(ha"); gsub(/([^\\])\^/, "&_BUT-HA_"); gsub(/\^_BUT-HA_/, "\\(ha"); print}' $< | tee $(patsubst %,$(MANDIR)%,$(call rewrap_mandirs,$<)) > $@
	! $(MANDOC) -Tlint $@ 2>&1 | grep -vE -e 'mandoc: outdated mandoc.db' -e 'STYLE: referenced manual not found' -e 'WARNING: cross reference to self' -e 'WARNING: undefined string, using "": doc-str-St$$' -e 'WARNING: undefined string, using "": doc-Tn-font-size' -e 'STYLE: useless macro: Tn' -e 'WARNING: unknown font, skipping request: TS.+fC[RBI]' -e 'STYLE: input text line longer than 80 bytes:' -e 'WARNING: nested displays are not portable: D1 in Bd' -e 'STYLE: operating system explicitly specified: Os voreutils' $(shell $(AWK) '/mandoc-ignore/ {$$1 = ""; $$2 = "-e"; $$3 = "\"" $$3; $$NF = $$NF "\""; print}  /^.\\"$$/ {exit}' $<)
# The "WARNING: unknown font, skipping request: TS.+fC[RBI]" one: see https://bugs.debian.org/992002

# GNU Make needs an empty rule here so that it actually picks this up as an orderable rule, not a strict, unfulfillable, dependency
$(foreach l,1 2 3 4 5 6 7 8,$(MANDIR)man$(l)/%) : $(OBJDIR)man/%
	@

$(OBJDIR)manalias/es : man/ man/aliases
	@mkdir -p $(@D)
	cd $(OBJDIR)manalias && rm -f * && touch $(sort $(subst man/,,$(MANPAGES)) $(shell cat man/aliases)) es

$(OBJDIR)man/index.0 : $(MANPAGES)
	{ \
		printf "%s\n" ".Dd $(INDEX_PAGE_DATE)" ".Dt INDEX 0" ".Os voreutils $(VOREUTILS_VERSION)" ".Sh NAME" ".Nm index" ".Nd voreutils $(VOREUTILS_VERSION) manual index" ".Sh CONTENTS" "." '.Bl -tag -compact'; \
		awk '/^\.Nm/ {sub(/\./, " ", FILENAME); sub("man/", ".It Xr ", FILENAME); print FILENAME; print}  /^\.Nd/ {sub(/\.Nd/, "\\-"); print; nextfile}' $(shell printf "%s\n" $(call rewrap_mandirs,$^) | sort -n | cut -c -3,5-); \
		echo .El; \
	} > $@

# mandoc always evaluates n to true and t to false
$(foreach l,0 1 2 3 4 5 6 7 8,$(HTMLMANDIR)man$(l)/%.html) : $(OBJDIR)man/% $(OBJDIR)manalias/es
	@mkdir -p $(@D)
	printf '.ds doc-%s-font \\f[%s]\n' $(HTMLMAN_FONT_OVERRIDES) | \
		$(SED) -e 's/^\(\.i[ef]\) n/\1 0/' -e '/^\.Sh DESCRIPTION/r /dev/stdin' $< | \
		(cd $(OBJDIR)manalias; $(MANDOC) -Thtml -Ostyle="../style.css",man="../man%S/%N.%S.html;$(HTMLMAN_OUTSIDE_FORMAT)") | \
		$(AWK) '/^<h1/ {in_syn = $$0 ~ /id="SYNOPSIS"/}  /^<br/ {if(in_syn) next}  {print}' | \
		$(SED) -Ee 's/ title=".."//g' -e 's/<a class="permalink" href="#([^"]*)"><span class="No" id="([^"]*)">/<a><span class="No">/g' > $@

$(HTMLMANDIR)style.css : man/style.css
	@mkdir -p $(@D)
	cp $^ $@


$(OBJDIR)cmd/%.sh : cmd/%.sh
	$(SED) '/SPDX-License-Identifier/a # voreutils $(VOREUTILS_VERSION) ($(call DATE_F,$<))' < $< > $@
	chmod +x $@
	$(SHELLLCHECK) $@

$(CMDDIR)% : $(OBJDIR)cmd/%.sh
	@mkdir -p $(@D)
	cp $< $@


$(CMDDIR)% : $(OBJDIR)cmd/%.o
	@mkdir -p $(@D)
	$(CXX) $(CCAR) -fno-exceptions -o $@ $< $(LDAR)

$(LIBDIR)%$(SO) : $(OBJDIR)lib/%.o
	@mkdir -p $(@D)
	$(CXX) $(CCAR) -shared -o $@ $< $(LDAR) -Wl,$(SONAME),$(subst $(OUTDIR),,$@).$(VOREUTILS_VERSION)

$(OBJDIR)%.o : %.cpp $(INCLUDES)
	@mkdir -p $(@D)
	$(CXX) $(CCAR) $(call CPPAR,$<) -std=c++17 -fno-exceptions -c -o $@ $<