]> Lady’s Gitweb - Caudex/blob - GNUmakefile
Make repository REUSE‐compliant
[Caudex] / GNUmakefile
1 # SPDX-FileCopyrightText: 2024 Lady <https://www.ladys.computer/about/#lady>
2 # SPDX-License-Identifier: MPL-2.0
3
4 SHELL = /bin/sh
5
6 # ━ § BASIC INFORMATION ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
7 override define makefileinfo
8 ╭──────────────────────────────╮
9 ╔╡ ⁌ 🪾📰 Caudex ∷ GNUmakefile ╞═══════════════════════════════╗
10 ║╰──────────────────────────────╯ ║
11 ╟┬ ¶ Prerequisites ───────────────────────────────────────────┬╢
12 ║│ │║
13 ║│ Requires G·N·U Make, at least version 3.81, and all of the │║
14 ║│ requirements of ⛩📰 书社, which is included as a git │║
15 ║│ submodule. Run `make help-shushe´ for more information. │║
16 ║╰────────────────────────────────────────────────────────────╯║
17 ╟┬ ¶ Usage ───────────────────────────────────────────────────┬╢
18 ║│ │║
19 ║│ • `make all´ (default): Compile, but do not install, all │║
20 ║│ files. │║
21 ║│ │║
22 ║│ • `make clean´: Remove `BUILDDIR´. │║
23 ║│ │║
24 ║│ • `make clean´: Remove `BUILDDIR´. │║
25 ║│ │║
26 ║│ • `make gone´: Remove `BUILDDIR´ and installed files. │║
27 ║│ │║
28 ║│ • `make help´: Print this message. │║
29 ║│ │║
30 ║│ • `make install´: Compile all files and install in │║
31 ║│ `DESTDIR´. │║
32 ║│ │║
33 ║│ • `make list´: List all recognized source files and their │║
34 ║│ classification (including media type and dependencies). │║
35 ║│ │║
36 ║│ • `make uninstall´: Remove installed files, but not │║
37 ║│ `BUILDDIR´. │║
38 ║│ │║
39 ║│ • `make +⟨CATEGORY⟩´: Create a new entry in ⟨CATEGORY⟩ and │║
40 ║│ output its path. │║
41 ║│ │║
42 ║│ Set `VERBOSE=1´ to see the text of commands as they are │║
43 ║│ executed. │║
44 ║│ │║
45 ║│ See `README.markdown´ for a more involved description of │║
46 ║│ the capabilities and configuration of this program. │║
47 ║╰────────────────────────────────────────────────────────────╯║
48 ╟┬ ¶ Copyright & License ─────────────────────────────────────┬╢
49 ║│ │║
50 ║│ Copyright © 2024 Lady [@ Ladys Computer]. │║
51 ║│ │║
52 ║│ This Source Code Form is subject to the terms of the │║
53 ║│ Mozilla Public License, v 2.0. If a copy of the M·P·L was │║
54 ║│ not distributed with this file, You can obtain one at │║
55 ║│ <http://mozilla.org/MPL/2.0/>. │║
56 ║╰────────────────────────────────────────────────────────────╯║
57 ╚══════════════════════════════════════════════════════════════╝
58 endef
59
60 # ━ § MAKE·FILE SETUP ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
61
62 # Programs needed to run this make·file.
63 #
64 # If these are not installed on your computer, or you need to use a different implementation, you can override the appropriate variable.
65 #
66 # See also the documentation for ⛩📰 书社, which specifies additional programs.
67 AWK := awk
68 CAT := cat
69 GIT := git
70 MKDIR := mkdir
71 OD := od
72 PRINTF := printf
73 RM := rm
74 SED := sed
75 TEST := test
76 TR := tr
77 XARGS := xargs
78 XMLCATALOG := xmlcatalog
79
80 # The directory which contains the codex entries and related metadata.
81 SRCDIR := entries
82
83 # The directory which contains additional assets for the codex generator.
84 ASSETDIR := assets
85
86 # The directory which contains includes for additional assets for the codex generator.
87 ASSETINCLUDEDIR := $(ASSETDIR)/includes
88
89 # The directory in which to generate temporary buildfiles.
90 BUILDDIR := build
91
92 # The directory into which to output files on `make´.
93 DESTDIR := public
94
95 # The location of this Makefile, relative to the current working directory.
96 #
97 # It is expected that other files packaged as a part of 🪾📰 Caudex can also be found in this directory.
98 #
99 # By default, this is inferred from the variable `MAKEFILE_LIST´.
100 THISDIR := $(patsubst %/,%,$(dir $(lastword $(MAKEFILE_LIST))))
101
102 # Extra magic files to forward to ⛩📰 书社.
103 #
104 # Your computer probably has several already installed at `/usr/share/file/magic´.
105 EXTRAMAGIC :=
106
107 # Extra parsers to forward to ⛩📰 书社.
108 #
109 # Which parsers are provided will influence which kinds of files are recognized as plaintext.
110 EXTRAPARSERS :=
111
112 # Extra transforms to forward to ⛩📰 书社.
113 EXTRATRANSFORMS :=
114
115 # A description of the current git revision of 🪾📰 Caudex.
116 THISREV := $(shell cd $(THISDIR); $(GIT) describe 2> /dev/null || $(GIT) rev-parse HEAD 2> /dev/null || true)
117
118 # Variables to communicate to further calls to Make.
119 #
120 # By default, `MAKEOVERRIDES´ contains all variable overrides specified on the commandline.
121 # However, some values are specific to 🪾📰 Caudex and may have different meaning in other make·files; filter these out.
122 MAKEOVERRIDES := $(filter-out SRCDIR=% ASSETDIR=% BUILDDIR=% DESTDIR=% THISDIR=% EXTRAMAGIC=% EXTRAPARSERS=% EXTRATRANSFORMS=% THISREV=%,$(MAKEOVERRIDES))
123
124 # The location of 💄📝 Les·M·L.
125 LESML := $(THISDIR)/.💄📝
126
127 # The location of ⛩📰 书社.
128 SHUSHE := $(THISDIR)/.⛩📰
129
130 # Set to a non·empty value to print all commands as they run.
131 VERBOSE :=
132
133 # The default target for this makefile.
134 .DEFAULT_GOAL := all
135
136 # ━ § BEGIN MAKE·FILE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
137
138 # ─ ¶ Non‐Recipe Variable Definitions ─────────────────────────────────
139
140 # A variable which contains a newline, to allow the generation of multiline strings in function calls.
141 override define newline
142
143
144 endef
145
146 # (callable) Quote the given string for use within shell calls.
147 override quote = '$(subst ','"'"',$1)'
148
149 # Outputs an `@´ to silence rules, unless `VERBOSE´ is nonempty.
150 override silent := $(if $(VERBOSE),,@)
151
152 # The list of categories, determined by the set of directories in `SRCDIR´ with corresponding metadata files.
153 override categories := $(sort $(patsubst $(SRCDIR)/%/@,%,$(wildcard $(SRCDIR)/*/@)))
154
155 # (callable) The set of file locations for the entries of the provided categories.
156 override entriesforcategory = $(sort $(foreach category,$1,$(wildcard $(SRCDIR)/$(category)/???-????) $(wildcard $(SRCDIR)/$(category)/???-????,*)))
157
158 # A random W·R·M·G(·like) base⹀32 identifier.
159 #
160 # This variable returns a different value each time it is referenced.
161 # Use `foreach´ to save the value for repeated usage.
162 #
163 # This variable recursively calls itself to ensure there is no existing entry with the resulting identifier.
164 override wrmg = $(foreach attempt,$(shell $(OD) -t u4 -N 4 /dev/random | $(SED) 's/^[0-9]* *//' | $(TR) -d ' \n' | $(AWK) 'BEGIN{chars="0123456789ABCDEFGHJKMNPQRSTVWXYZ&~@=U"}{d=32^5;r=$$0%(32^6);printf("%s",substr(chars,r%37,1));while(d>0){printf("%s", substr(chars,int(r/d),1));if(d==32^4)printf("%s", "-");r%=d;d=int(d/32)}}'),$(if $(wildcard $(SRCDIR)/*/($(attempt))*),$(call wrmg),$(attempt)))
165
166 # (callable) Returns the identifiers of the provided entries.
167 override identifier = $(shell $(PRINTF) '%s\n' $(call quote,$1) | $(TR) ' ' '\n' | $(SED) 's/^\(.*[/]\)\{0,1\}\(.\{3\}-.\{4\}\)\(,[^/]*\)\{0,1\}$$/\2/')
168
169 # Output locations for compiled catalog files for categories.
170 override categorycatalogs := $(patsubst %,$(BUILDDIR)/catalogs/categories/%/index,$(categories))
171
172 # Output locations for compiled catalog files for entries.
173 override entrycatalogs := $(foreach entry,$(call entriesforcategory,$(categories)),$(patsubst $(SRCDIR)/%,$(BUILDDIR)/catalogs/entries/%,$(entry)))
174
175 # Output locations for all compiled catalog files.
176 override allcatalogs := $(BUILDDIR)/catalogs/indices/index $(BUILDDIR)/catalogs/indices/fullindex $(categorycatalogs) $(entrycatalogs)
177
178 # (overridable) Options to pass to ⛩📰 书社.
179 override shusheopts := SRCDIR=$(call quote,$(if $(wildcard $(ASSETDIR)),$(ASSETDIR),) $(if $(entrycatalogs),$(BUILDDIR)/catalogs/entries,) $(BUILDDIR)/catalogs/indices) BUILDDIR=$(call quote,$(BUILDDIR)/⛩📰) INCLUDEDIR=$(call quote,$(SRCDIR) $(if $(wildcard $(ASSETINCLUDEDIR)),$(ASSETINCLUDEDIR),) $(if $(categorycatalogs),$(BUILDDIR)/catalogs/categories,)) DESTDIR=$(call quote,$(DESTDIR)) EXTRAMAGIC=$(call quote,$(sort $(patsubst ./%,%,$(wildcard $(THISDIR)/magic/*)) $(LESML)/magic $(EXTRAMAGIC))) EXTRAPARSERS=$(call quote,$(sort $(patsubst ./%,%,$(wildcard $(THISDIR)/parsers/*.xslt)) $(LESML)/parser.xslt $(EXTRAPARSERS))) EXTRATRANSFORMS=$(call quote,$(sort $(patsubst ./%,%,$(wildcard $(THISDIR)/transforms/*.xslt)) $(EXTRATRANSFORMS)))
180
181 # ─ ¶ Recipe Variable Definitions ─────────────────────────────────────
182
183 # (callable) Check to see if the given directory exists and create it if not.
184 override ensuredirectory = if $(TEST) ! -d $(call quote,$1); then $(MKDIR) -p $(call quote,$1); fi
185
186 # (callable) Test to see if the file provided by the first argument exists and the dependencies provided by the third argument matches the value in the file corresponding to the second argument in `$(BUILDDIR)/lastprereqs´.
187 # If not, return the fourth argument, plus an additional rule to save the new prerequisites.
188 #
189 # ※ If the third argument is empty, the fourth argument is always returned.
190 override makeandsavedeps = $(if $(or $(if $3,,1),$(if $(wildcard $1),,1),$(subst $(shell $(CAT) $(call quote,$(BUILDDIR)/lastdeps/$2) 2> /dev/null || true),,$3)),$4$(newline)$(silent)$(call ensuredirectory,$(BUILDDIR)/lastdeps)$(newline)$(silent)$(PRINTF) '%s\n' $(call quote,$3) > $(call quote,$(BUILDDIR)/lastdeps/$2),)
191
192 # (callable) Make the catalog for the provided category.
193 override define makecategorycatalog
194 @$(PRINTF) '%s\n' $(call quote,Generating catalog for category `$1´…)
195 $(silent)$(call ensuredirectory,$(BUILDDIR)/catalogs/categories/$1)
196 $(silent)$(XMLCATALOG) --create --noout $(call quote,$(BUILDDIR)/catalogs/categories/$1/index)
197 $(silent)$(XMLCATALOG) --add uri '?' 'about:category' --noout $(call quote,$(BUILDDIR)/catalogs/categories/$1/index)
198 $(silent)$(XMLCATALOG) --add uri '@' $(call quote,$1/@) --noout $(call quote,$(BUILDDIR)/catalogs/categories/$1/index)
199 $(foreach entry,$(call entriesforcategory,$1),$(silent)$(XMLCATALOG) --add uri $(call quote,$(call identifier,$(entry))) $(call quote,$(patsubst $(SRCDIR)/%,%,$(entry))) --noout $(call quote,$(BUILDDIR)/catalogs/categories/$1/index)$(newline))
200 endef
201
202 # (callable) Make the catalog for the dynamic or static index.
203 override define makeindexcatalog
204 @$(PRINTF) '%s\n' 'Generating $(if $1,static,dynamic) catalog index…'
205 $(silent)$(call ensuredirectory,$(BUILDDIR)/catalogs/indices)
206 $(silent)$(XMLCATALOG) --create --noout $(call quote,$(BUILDDIR)/catalogs/indices/$(if $1,full,)index)
207 $(silent)$(XMLCATALOG) --add uri '.' '$(if $1,standalone,index).xhtml' --noout $(call quote,$(BUILDDIR)/catalogs/indices/$(if $1,full,)index)
208 $(silent)$(XMLCATALOG) --add uri '?' 'about:$(if $1,full,)index' --noout $(call quote,$(BUILDDIR)/catalogs/indices/$(if $1,full,)index)
209 $(silent)$(XMLCATALOG) --add uri '@' '@' --noout $(call quote,$(BUILDDIR)/catalogs/indices/$(if $1,full,)index)
210 $(foreach category,$(categories),$(silent)$(XMLCATALOG) --add uri $(call quote,$(category)) $(call quote,$(category)/index) --noout $(call quote,$(BUILDDIR)/catalogs/indices/$(if $1,full,)index)$(newline))
211 endef
212
213 # ─ ¶ ⛩📰 书社 Targets ──────────────────────────────────────────────
214
215 # Targets to forward to ⛩📰 书社.
216 all install list uninstall : $(SHUSHE)/GNUmakefile catalogs
217 $(silent)$(MAKE) -f $(call quote,$<) $(call quote,$@) $(shusheopts)
218 %-shushe : $(SHUSHE)/GNUmakefile FORCE
219 $(silent)$(MAKE) -f $(call quote,$<) $(call quote,$*) $(shusheopts)
220 build/⛩📰/% : $(SHUSHE)/GNUmakefile catalogs FORCE
221 $(SILENT)$(MAKE) -f $(call quote,$<) $(call quote,$@) $(shusheopts)
222 public/% : $(SHUSHE)/GNUmakefile catalogs FORCE
223 $(SILENT)$(MAKE) -f $(call quote,$<) $(call quote,$@) $(shusheopts)
224
225 # ─ ¶ Phony Targets ───────────────────────────────────────────────────
226
227 # Generate all catalogs, then remove any which no longer have corresponding source files.
228 catalogs : $(allcatalogs)
229 @$(PRINTF) '%s\n' 'Removing any outdated catalogs…'
230 $(foreach deletedcategory,$(filter-out $(categorycatalogs),$(wildcard $(BUILDDIR)/catalogs/categories/*/index)),@$(PRINTF) '%s\n' $(call quote,Removing `$(patsubst $(BUILDDIR)/catalogs/categories/%/index,%,$(deletedcategory))´…)$(newline)$(silent)$(RM) -rf $(call quote,./$(dir $(deletedcategory)))$(newline)$(silent)$(RM) -rf $(call quote,./$(patsubst $(BUILDDIR)/catalogs/categories/%,$(BUILDDIR)/catalogs/entries/%,$(dir $(deletedcategory))))$(newline))
231 $(foreach deletedentry,$(filter-out $(entrycatalogs),$(wildcard $(BUILDDIR)/catalogs/entries/*/*)),@$(PRINTF) '%s\n' $(call quote,Removing `$(patsubst $(BUILDDIR)/catalogs/entries/%,%,$(deletedentry))´…)$(newline)$(silent)$(RM) $(call quote,./$(deletedentry))$(newline))
232
233 # Destroy buildfiles.
234 clean:
235 $(if $(BUILDDIR),$(silent)$(RM) -rf $(call quote,$(BUILDDIR)/),)
236
237 # Provide help.
238 help :
239 @$(PRINTF) '%b' '$(subst $(newline),\n,$(makefileinfo))'
240
241 # Destroy build directory and installed files.
242 gone : clean uninstall ;
243
244 # List the i·d’s of all recognized entries.
245 listids :
246 @$(TR) '| ' ' \n' <<< '$(strip $(foreach category,$(categories),\0033[1m$(category)\0033[22m: $(patsubst %,•|%,$(call identifier,$(call entriesforcategory,$(category)))) ))' | $(XARGS) -0 $(PRINTF) '%b'
247
248 # Output a random unused identifier.
249 wrmg :
250 @$(PRINTF) '%s\n' $(wrmg)
251
252 # Create a new entry in the provided category and output its path.
253 +% : FORCE
254 $(silent)$(call ensuredirectory,$(SRCDIR)/$*)
255 $(if $(wildcard $(SRCDIR)/$*/@),,$(silent)$(PRINTF) '%b' '%%\nCATEGORY : $*\n%%\n' > '$(SRCDIR)/$*/@')
256 $(foreach identifier,$(wrmg),@$(PRINTF) '%b' '\0043!lesml\nENTRY : $(identifier)\n%%\n\n' > '$(SRCDIR)/$*/$(identifier)'$(newline)@$(PRINTF) '%s\n' '$(SRCDIR)/$*/$(identifier)')
257
258 # ─ ¶ Special Targets ─────────────────────────────────────────────────
259
260 # Perform secondary expansion; this enables pattern rules to determine their prerequisites based on the matched pattern.
261 .SECONDEXPANSION : ;
262
263 # Don’t use any implicit rules.
264 .SUFFIXES : ;
265
266 # Treat targets with this as a prerequisite as though they were phony.
267 #
268 # Mainly useful in pattern rules.
269 FORCE : ;
270
271 # Phony rules; always consider these out·of·date.
272 .PHONY : FORCE all build catalogs clean gone help install list listids uninstall wrmg ;
273
274 # ─ ¶ Build Targets ───────────────────────────────────────────────────
275
276 # Initialize the ⛩📰 书社 repository if it is empty.
277 ifneq ($(filter $(THISDIR)/%,$(SHUSHE)),)
278 $(SHUSHE)/GNUmakefile : $(THISDIR)/%/GNUmakefile :
279 @$(PRINTF) '%s\n' $(call quote,Initializing git submodule at `$*´)
280 $(silent)cd $(THISDIR) && $(GIT) submodule update --init $(call quote,$*)
281 endif
282
283 # Initialize the 💄📝 Les·M·L repository if it is empty.
284 ifneq ($(filter $(THISDIR)/%,$(LESML)),)
285 $(LESML)/parser.xslt : $(THISDIR)/%/parser.xslt :
286 @$(PRINTF) '%s\n' $(call quote,Initializing git submodule at `$*´)
287 $(silent)cd $(THISDIR) && $(GIT) submodule update --init $(call quote,$*)
288 endif
289
290 # Create an empty codex metadata file if none exists.
291 $(SRCDIR)/@ :
292 $(silent)$(PRINTF) '%b' '%%\nCODEX :\n%%\n' > $(call quote,$@)
293
294 # Create category catalogs.
295 $(categorycatalogs) : $(BUILDDIR)/catalogs/categories/%/index : FORCE
296 $(call makeandsavedeps,$@,$*,$(call entriesforcategory,$*),$(call makecategorycatalog,$*))
297
298 # Create entry catalogs.
299 $(entrycatalogs) : $(BUILDDIR)/catalogs/entries/% :
300 @$(PRINTF) '%s\n' $(call quote,Generating catalog for document `$(call identifier,$*)´…)
301 $(silent)$(call ensuredirectory,$(dir $@))
302 $(silent)$(XMLCATALOG) --create --noout $(call quote,$@)
303 $(silent)$(XMLCATALOG) --add uri '.' '$(call identifier,$*).xhtml' --noout $(call quote,$@)
304 $(silent)$(XMLCATALOG) --add uri '?' 'about:entry' --noout $(call quote,$@)
305 $(silent)$(XMLCATALOG) --add uri '@' $(call quote,$*) --noout $(call quote,$@)
306
307 $(BUILDDIR)/catalogs/indices/index : FORCE | $(SRCDIR)/@
308 $(call makeandsavedeps,$@,index,$(categories),$(call makeindexcatalog,))
309
310 $(BUILDDIR)/catalogs/indices/fullindex : FORCE | $(SRCDIR)/@
311 $(call makeandsavedeps,$@,fullindex,$(categories),$(call makeindexcatalog,1))
This page took 0.133545 seconds and 5 git commands to generate.