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