X-Git-Url: https://git.ladys.computer/Shushe/blobdiff_plain/8b898cc1e883b2a5b3662a5c6b6913d5d0e7236d..c4c2cfb24adfa62c6b4cbd819b7efe80438d8d08:/GNUmakefile diff --git a/GNUmakefile b/GNUmakefile index 1cf21d2..99e94cf 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -6,7 +6,7 @@ SHELL = /bin/sh # ━ § BASIC INFORMATION ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ override define makefileinfo ╭────────────────────────────╮ -╔╡ ⁌ ⛩️📰 书社 ∷ GNUmakefile ╞═════════════════════════════════╗ +╔╡ ⁌ ⛩📰 书社 ∷ GNUmakefile ╞═════════════════════════════════╗ ║╰────────────────────────────╯ ║ ╟┬ ¶ Prerequisites ───────────────────────────────────────────┬╢ ║│ │║ @@ -83,7 +83,7 @@ override define makefileinfo ║╰────────────────────────────────────────────────────────────╯║ ╟┬ ¶ Copyright & License ─────────────────────────────────────┬╢ ║│ │║ -║│ Copyright © 2023–2024 Lady [@ Lady’s Computer]. │║ +║│ Copyright © 2023–2024 Lady [@ Ladys Computer]. │║ ║│ │║ ║│ This Source Code Form is subject to the terms of the │║ ║│ Mozilla Public License, v 2.0. If a copy of the M·P·L was │║ @@ -161,7 +161,7 @@ BUILDDIR := build # This variable is also used by the archiving `MODE´. DESTDIR := public -# The location of this Makefile (and related ⛩️📰 书社 files), relative to the current working directory. +# The location of this Makefile (and related ⛩📰 书社 files), relative to the current working directory. # # By default, this is inferred from the variable `MAKEFILE_LIST´. # @@ -205,7 +205,7 @@ FINALIZE := $(XMLLINT) --nonet --nsclean ifdef GIT ifneq ($(wildcard $(THISDIR)/.git),) -# A description of the current git revision of ⛩️📰 书社. +# A description of the current git revision of ⛩📰 书社. THISREV := $(shell $(CD) $(THISDIR); $(GIT) describe 2>>/dev/null || $(GIT) rev-parse HEAD 2>>/dev/null || :) endif @@ -233,6 +233,14 @@ QUIET := # Set to a non·empty value to print all commands as they run. VERBOSE := +# Posix locale information. +LC_ALL := C +export LC_ALL + +# Posix timezone information. +TZ := UTC0 +export UTC0 + # The default target for this makefile. .DEFAULT_GOAL := all @@ -264,16 +272,6 @@ override comma := , # (callable) Quote the given string for use within shell calls. override quote = '$(subst ','"'"',$1)' -# (callable) Get the modified time of the provided file. -# -# This touches a file containing only a newline and then diffs it with `/dev/null´ and extracts the timestamp from the diff. -# Interestingly, on Macintosh, the format of `diff -u´ is only Posixy (including a fractional component and timezone) when `COMMAND_MODE=legacy´; however, the timezone will always be zero and the fractional component is ignorable, so it’s not necessary to worry about that here. -# -# The diff will always have an exit status of 1, but this is ignored by piping into Sed. -# -# ☡ This variable creates a subshell every time it is computed. -override modtime = $(shell if $(TEST) ! -f $(call quote,$(BUILDDIR)/.mtime); then $(PRINTF) '%b' '\n' > $(call quote,$(BUILDDIR)/.mtime); fi; $(TOUCH) -r $(call quote,$1) $(call quote,$(BUILDDIR)/.mtime); TZ=UTC0 $(DIFF) -u $(call quote,$(BUILDDIR)/.mtime) /dev/null | $(SED) '1!d;s/.* \([^ ]*\) \([^ ]*\).*$$/\1T\2Z/') - # ─ ¶ Recipe Variable Definitions ───────────────────────────────────── # Outputs an `@´ to silence rules, unless `VERBOSE´ is non·empty. @@ -297,7 +295,7 @@ override xargsmultiquote = $(SED) $(call quote,s/'/'"'"'/g;s/^/'/;s/$$/'/) override xpath = $(XMLLINT) --noent --nonet --xpath $(call quote,$1) $(call quote,$2) >>/dev/null 2>>/dev/null # (callable) Extract the value of the text nodes in the provided X·M·L document and print them to `stdout´. -override extracttext = $(PRINTF) '%s' '' | $(XSLTPROC) --nonet --novalid - $(call quote,$1) +override extracttext = $(PRINTF) '%s' '' | $(XSLTPROC) --nonet --novalid --nomkdir --nowrite - $(call quote,$1) # (callable) Process the provided transformation result and output the result to the provided location, given the provided relative path. override processresultto = if $(call xpath,/*[local-name()="raw-text" and namespace-uri()="urn:fdc:ladys.computer:20231231:Shu1She4"],$1); then $(call extracttext,$1) >|$(call quote,$2); elif $(call xpath,/*[local-name()="base64-binary" and namespace-uri()="urn:fdc:ladys.computer:20231231:Shu1She4"],$1); then { $(PRINTF) '%s\n' 'begin-base64 644 -'; $(call extracttext,$1) | $(TR) -d '\t\n\f\r '; $(PRINTF) '\n%s\n' '===='; } | $(UUDECODE) -o /dev/stdout >|$(call quote,$2); elif $(call xpath,/*[local-name()="archive" and namespace-uri()="urn:fdc:ladys.computer:20231231:Shu1She4"],$1); then $(MAKE) -f $(call quote,$(abspath $(THISDIR)/GNUmakefile)) NAME=$(call quote,$3) SRC=$(call quote,$1) BUILDDIR=$(call quote,$(BUILDDIR)/archive/$3) DESTDIR=$(call quote,$(patsubst %/,%,$(dir $2))) MODE='urn:fdc:ladys.computer:20231231:Shu1She4:mode:archive' $(call quote,$2); else $(FINALIZE) $(call quote,$1) >|$(call quote,$2); fi @@ -436,10 +434,10 @@ override parsed = $(foreach file,$1,$(patsubst $(file)|%,%,$(filter $(file)|%,$( # (callable) Get the source files for the given parsed file. override unparsed = $(foreach file,$1,$(patsubst %|$(file),%,$(filter %|$(file),$(sourceparsedpair)))) -# Pair each parser, transform, source file, or parsed file with its file u·r·i. -override fileuripairs := $(join $(patsubst %,%|,$(PARSERS) $(TRANSFORMS) $(sourcefiles) $(sourceincludes) $(call parsed,$(sourcefiles) $(sourceincludes))),$(call pathenc,$(foreach uriable,$(PARSERS) $(TRANSFORMS) $(sourcefiles) $(sourceincludes) $(call parsed,$(sourcefiles) $(sourceincludes)),file://$(abspath $(uriable))))) +# Pair each build directory, parser, transform, or source file with its file u·r·i. +override fileuripairs := $(join $(patsubst %,%|,$(BUILDDIR) $(PARSERS) $(TRANSFORMS) $(sourcefiles) $(sourceincludes)),$(call pathenc,$(foreach uriable,$(BUILDDIR) $(PARSERS) $(TRANSFORMS) $(sourcefiles) $(sourceincludes),file://$(abspath $(uriable))))) -# (callable) Get the file u·r·is for the given parsers, transforms, or parsed files. +# (callable) Get the file u·r·is for the given parsers, transforms, parsed files, or metadata compilations. override fileuri = $(foreach file,$1,$(or $(patsubst $(file)|%,%,$(filter $(file)|%,$(fileuripairs))),$(error Unable to get file u·r·i for `$(file)´))) ifneq ($(wildcard $(BUILDDIR)/dependencies),) @@ -482,10 +480,10 @@ override destinations := $(shell $(CAT) $(BUILDDIR)/destinations) # Pair source files and their destinations. override sourcedestinationpair := $(foreach destination,$(destinations),$(call sourcefile,$(firstword $(subst |, ,$(destination))))|$(call perdec,$(subst $(space),|,$(wordlist 2,$(words $(subst |, ,$(destination))),$(subst |, ,$(destination)))))) -# (callable) Get the destination for the given source files, or return `NOTDEF´. +# (callable) Get the destination for the given source files, or return `.NOTDEF/$1´. # -# The fallback here is because destinations are used to generate targets and thus must always be non·empty, even when they haven’t been generated yet. -override destination = $(foreach file,$1,$(or $(patsubst $(file)|%,%,$(filter $(file)|%,$(sourcedestinationpair))),NOTDEF)) +# The fallback here is because destinations are used to generate targets and thus must always be non·empty and should be unique, even when they haven’t been generated yet. +override destination = $(foreach file,$1,$(or $(patsubst $(file)|%,%,$(filter $(file)|%,$(sourcedestinationpair))),.NOTDEF/$1)) # Pair each source file with its compiled location. override sourcecompiledpair := $(foreach file,$(sourcefiles),$(file)|$(BUILDDIR)/results/$(call destination,$(file))) @@ -542,7 +540,7 @@ install : $(call installed,$(recursivefiles) $(installablefiles)) ; # List all source files and includes and their computed types. list : - @$(PRINTF) '%b' $(call quote,$(foreach file,$(sort $(sourcefiles)) $(sort $(sourceincludes)),\0033[1m$(file)\0033[22m|$(call typeoffile,$(file))|[\0033[3m$(if $(filter $(file),$(xmlfiles)),xml,$(if $(filter $(file),$(plaintextfiles)),text,asset))$(if $(filter $(file),$(sourceincludes)),|include,)\0033[23m] Modified:|$(call modtime,$(file))$(if $(call dependencies,$(file))$(call recursives,$(file)), $(strip $(foreach recursive,$(call recursives,$(file)),\0033[93;41m•|Recursive|Dependency|\0033[39;49m|$(recursive)) $(foreach dependency,$(call dependencies,$(file)),\0033[2m•|Dependency|\0033[22m|$(dependency))))$(if $(filter $(file),$(sourcefiles)), →|<\0033[4m/$(call destination,$(file))\0033[24m>,) )) | $(TR) ' |' '\n ' + @$(PRINTF) '%b' $(call quote,$(foreach file,$(sort $(sourcefiles)) $(sort $(sourceincludes)),\0033[1m$(file)\0033[22m|$(call typeoffile,$(file))|[\0033[3m$(if $(filter $(file),$(xmlfiles)),xml,$(if $(filter $(file),$(plaintextfiles)),text,asset))$(if $(filter $(file),$(sourceincludes)),|include,)\0033[23m]$(if $(call dependencies,$(file))$(call recursives,$(file)), $(strip $(foreach recursive,$(call recursives,$(file)),\0033[93;41m•|Recursive|Dependency|\0033[39;49m|$(recursive)) $(foreach dependency,$(call dependencies,$(file)),\0033[2m•|Dependency|\0033[22m|$(dependency))))$(if $(filter $(file),$(sourcefiles)), →|<\0033[4m/$(call destination,$(file))\0033[24m>,) )) | $(TR) ' |' '\n ' # Lists out the destinations of all resulting files (relative to `DESTDIR´). listout : @@ -629,14 +627,14 @@ $(BUILDDIR)/parser.catalog : $(call diffprereqs,parsers,$(sort $(PARSERS))) $(foreach parser,$(PARSERS),$(silent){ $(call id,$(parser)); $(PRINTF) '%s\n' $(call quote,$(call fileuri,$(parser))) '--noout' $(call quote,$@); } | $(xargsmultiquote) | $(XARGS) -E '' $(XMLCATALOG) --add uri$(newline)) $(BUILDDIR)/parser.xslt : $(BUILDDIR)/parser.catalog $(THISDIR)/lib/catalog2parser.xslt $(call inform,$(PRINTF) '%s\n' 'Generating main parser…' >&2) - $(silent)$(XSLTPROC) --nonet --novalid -o $(call quote,$@) $(call quote,$(THISDIR)/lib/catalog2parser.xslt) $(call quote,$<) + $(silent)$(XSLTPROC) --nonet --novalid --nomkdir --nowrite $(call quote,$(THISDIR)/lib/catalog2parser.xslt) $(call quote,$<) >|$(call quote,$@) $(silent)$(TOUCH) $(call quote,$(BUILDDIR)/.update-types) # Generate R·D·F metadata for files. $(call metadata,$(sourcefiles) $(sourceincludes)) : % : $$(call datadata,$$@) $(typeupdates) $(call inform,$(PRINTF) '%s\n' $(call quote,Generating metadata for `$<´…) >&2) $(silent)$(call ensuredirectory,$(dir $@)) - $(silent){ if $(TEST) ! -f $(call quote,$(BUILDDIR)/.mtime); then $(PRINTF) '%b' '\n' >|$(call quote,$(BUILDDIR)/.mtime); fi; $(TOUCH) -r $(call quote,$<) $(call quote,$(BUILDDIR)/.mtime); TZ=UTC0 $(DIFF) -u $(call quote,$(BUILDDIR)/.mtime) /dev/null | $(SED) '1!d;s/.* \([^ ]*\) \([^ ]*\).*$$/\1T\2Z/'; $(CKSUM) $(call quote,$<) | $(SED) 's/[ ].*//'; } | $(xargsmultiquote) | $(XARGS) -E '' $(PRINTF) '$(if $(filter $(source),$(assetfiles)),,)%s' $(call quote,$(call attresc,$(call localuri,$<))) $(call quote,$(call attresc,$(call fileuri,$<))) $(call quote,$(call attresc,$(call typeoffile,$<))) $(call quote,$(call attresc,$(call fileuri,$(call parsed,$<)))) >|$(call quote,$@) + $(silent){ if $(TEST) ! -f $(call quote,$(BUILDDIR)/.mtime); then $(PRINTF) '%b' '\n' >|$(call quote,$(BUILDDIR)/.mtime); fi; $(TOUCH) -r $(call quote,$<) $(call quote,$(BUILDDIR)/.mtime); $(DIFF) -u $(call quote,$(BUILDDIR)/.mtime) /dev/null | $(SED) '1!d;s/.* \([^ ]*\) \([^ ]*\).*$$/\1T\2Z/'; $(CKSUM) $(call quote,$<) | $(SED) 's/[ ].*//'; } | $(xargsmultiquote) | $(XARGS) -E '' $(PRINTF) '$(if $(filter $<,$(assetfiles)),,)%s' $(call quote,$(call attresc,$(call localuri,$<))) $(call quote,$(call attresc,$(if $(filter $<,$(sourceincludes)),$(call includepath,$<),$(call sourcepath,$<)))) $(call quote,$(call attresc,$(call fileuri,$<))) $(call quote,$(call attresc,$(call typeoffile,$<))) >|$(call quote,$@) # Parse the files. # @@ -645,42 +643,42 @@ $(call metadata,$(sourcefiles) $(sourceincludes)) : % : $$(call datadata,$$@) $( $(call parsed,$(sourcefiles) $(sourceincludes)) : % : $$(call unparsed,$$@) $(BUILDDIR)/parser.xslt $(typeupdates) $(call inform,$(PRINTF) '%s\n' $(call quote,Processing `$<´…) >&2) $(silent)$(call ensuredirectory,$(dir $@)) - $(silent)$(if $(filter $<,$(assetfiles)),$(PRINTF) '%s\n' $(call quote,) >|$(call quote,$@),$(if $(filter $<,$(plaintextfiles)),$(call wrapplaintext,$<),$(call serializexml,$<)) | $(XSLTPROC) --nonet --novalid -o $(call quote,$@) --stringparam BUILDTIME $$($(DATE) -u '+%Y-%m-%dT%H:%M:%SZ') --stringparam IDENTIFIER $(call quote,$(call localuri,$<)) --stringparam SRCTIME '$(call modtime,$<)' --stringparam CKSUM $$($(CKSUM) $(call quote,$<) | $(SED) 's/[ ].*//')$(if $(THISREV), --stringparam THISREV $(call quote,$(THISREV)),)$(if $(SRCREV), --stringparam SRCREV $(call quote,$(SRCREV)),) $(call quote,$(BUILDDIR)/parser.xslt) -) + $(silent)$(if $(filter $<,$(assetfiles)),$(PRINTF) '%s\n' $(call quote,) >|$(call quote,$@),$(if $(filter $<,$(plaintextfiles)),$(call wrapplaintext,$<),$(call serializexml,$<)) | $(XSLTPROC) --nonet --novalid --nomkdir --nowrite --stringparam BUILDTIME $$($(DATE) -u '+%Y-%m-%dT%H:%M:%SZ') --stringparam IDENTIFIER $(call quote,$(call localuri,$<))$(if $(THISREV), --stringparam THISREV $(call quote,$(THISREV)),)$(if $(SRCREV), --stringparam SRCREV $(call quote,$(SRCREV)),) $(call quote,$(BUILDDIR)/parser.xslt) - >|$(call quote,$@)) # Collect the metadata into a single file. -$(BUILDDIR)/metadata : $(call diffprereqs,metadatas,$(call metadata,$(sort $(sourcefiles) $(sourceincludes)))) +$(BUILDDIR)/metadata : $(call diffprereqs,metadatas,$(call metadata,$(sort $(sourcefiles) $(sourceincludes)))) $(call parsed,$(filter-out $(assetfiles),$(sourcefiles) $(sourceincludes))) $(THISDIR)/lib/expandmetadata.xslt $(call inform,$(PRINTF) '%s\n' 'Compiling metadata…' >&2) - $(silent){ $(PRINTF) '%s' ''; $(foreach meta,$(call metadata,$(sort $(sourcefiles) $(sourceincludes))),$(CAT) $(call quote,$(meta)) | $(SED) 's///';) $(PRINTF) '%s\n' ''; } >|$(call quote,$@) + $(silent){ $(PRINTF) '' $(call quote,$(call attresc,$(call fileuri,$(BUILDDIR)))); { $(foreach meta,$(call metadata,$(sort $(sourcefiles) $(sourceincludes))),$(CAT) $(call quote,$(meta));) } | $(SED) 's///g'; $(PRINTF) '%s\n' ''; } | $(XSLTPROC) --nonet --novalid --nomkdir --nowrite $(call quote,$(THISDIR)/lib/expandmetadata.xslt) - | $(XMLLINT) --nonet --nsclean - >|$(call quote,$@) # Build a list of dependencies for each parsed file. -$(BUILDDIR)/dependencies : $(BUILDDIR)/metadata $(call parsed,$(filter-out $(assetfiles),$(sourcefiles) $(sourceincludes))) $(THISDIR)/lib/metadata2dependencies.xslt +$(BUILDDIR)/dependencies : $(BUILDDIR)/metadata $(THISDIR)/lib/metadata2dependencies.xslt $(call inform,$(PRINTF) '%s\n' 'Identifying dependencies…' >&2) $(silent)$(TOUCH) $(call quote,$@) - $(silent)$(XSLTPROC) --nonet --novalid -o $(call quote,$@) $(call quote,$(THISDIR)/lib/metadata2dependencies.xslt) $(call quote,$<) + $(silent)$(XSLTPROC) --nonet --novalid --nomkdir --nowrite $(call quote,$(THISDIR)/lib/metadata2dependencies.xslt) $(call quote,$<) >|$(call quote,$@) # Generate a catalog of destinations for files. # # This depends on parsing non·asset source files, but not assets or includes. # It does not require knowing the dependencies. -$(BUILDDIR)/destinations : $(BUILDDIR)/metadata $(call parsed,$(filter-out $(assetfiles),$(sourcefiles))) $(THISDIR)/lib/metadata2destinations.xslt +$(BUILDDIR)/destinations : $(BUILDDIR)/metadata $(THISDIR)/lib/metadata2destinations.xslt $(call inform,$(PRINTF) '%s\n' 'Identifying output destinations…' >&2) $(silent)$(TOUCH) $(call quote,$@) - $(silent)$(XSLTPROC) --nonet --novalid -o $(call quote,$@) $(call quote,$(THISDIR)/lib/metadata2destinations.xslt) $(call quote,$<) + $(silent)$(XSLTPROC) --nonet --novalid --nomkdir --nowrite $(call quote,$(THISDIR)/lib/metadata2destinations.xslt) $(call quote,$<) >|$(call quote,$@) # Generate the main transform. $(BUILDDIR)/transform.catalog : $(call diffprereqs,transforms,$(sort $(TRANSFORMS))) $(call inform,$(PRINTF) '%s\n' 'Generating catalog of transforms…' >&2) $(silent)$(XMLCATALOG) --create --noout $(call quote,$@) $(foreach transform,$(TRANSFORMS),$(silent){ $(call id,$(transform)); $(PRINTF) '%s\n' $(call quote,$(call fileuri,$(transform))) '--noout' $(call quote,$@); } | $(xargsmultiquote) | $(XARGS) -E '' $(XMLCATALOG) --add uri$(newline)) -$(BUILDDIR)/transform.xslt : $(BUILDDIR)/transform.catalog $(THISDIR)/lib/catalog2transform.xslt +$(BUILDDIR)/transform.xslt : $(BUILDDIR)/transform.catalog $(BUILDDIR)/metadata $(THISDIR)/lib/catalog2transform.xslt $(call inform,$(PRINTF) '%s\n' 'Generating main transform…' >&2) - $(silent)$(XSLTPROC) --nonet --novalid -o $(call quote,$@) $(call quote,$(THISDIR)/lib/catalog2transform.xslt) $(call quote,$<) + $(silent)$(XSLTPROC) --nonet --novalid --nomkdir --nowrite --stringparam METADATA $(call quote,$(call fileuri,$(BUILDDIR))/metadata) $(call quote,$(THISDIR)/lib/catalog2transform.xslt) $(call quote,$<) >|$(call quote,$@) # Compile the result files using the dependencies as necessary. $(call compiled,$(compilablefiles)) : $(BUILDDIR)/results/% : $$(call parsed,$$(call uncompiled,$$@)) $$(call parsed,$$(call dependencies,$$(call uncompiled,$$@))) $(BUILDDIR)/transform.xslt $(BUILDDIR)/metadata $(call inform,$(PRINTF) '%s\n' $(call quote,Compiling …) >&2) $(silent)$(call ensuredirectory,$(dir $@)) - $(silent)$(XSLTPROC) --nonet --novalid -o $(call quote,$@) --stringparam METADATA 'metadata' --stringparam BUILDTIME $$($(DATE) -u '+%Y-%m-%dT%H:%M:%SZ') --stringparam SRCTIME '$(call modtime,$(call uncompiled,$@))' --stringparam IDENTIFIER $(call quote,$(call localuri,$(call uncompiled,$@))) --stringparam PATH $(call quote,/$*) --stringparam CKSUM $$($(CKSUM) $(call quote,$(call uncompiled,$@)) | $(SED) 's/[ ].*//')$(if $(THISREV), --stringparam THISREV $(call quote,$(THISREV)),)$(if $(SRCREV), --stringparam SRCREV $(call quote,$(SRCREV)),) $(call quote,$(BUILDDIR)/transform.xslt) $(call quote,$<) + $(silent)$(XSLTPROC) --nonet --novalid --nomkdir --nowrite --stringparam METADATA 'metadata' --stringparam BUILDTIME $$($(DATE) -u '+%Y-%m-%dT%H:%M:%SZ') --stringparam IDENTIFIER $(call quote,$(call localuri,$(call uncompiled,$@))) --stringparam PATH $(call quote,/$*)$(if $(THISREV), --stringparam THISREV $(call quote,$(THISREV)),)$(if $(SRCREV), --stringparam SRCREV $(call quote,$(SRCREV)),) $(call quote,$(BUILDDIR)/transform.xslt) $(call quote,$<) >|$(call quote,$@) # Create the final files from the compiled results (or error in the case of recursive ones). $(call built,$(compilablefiles)) : $(BUILDDIR)/public/% : $(BUILDDIR)/results/% @@ -728,7 +726,7 @@ $(THISDIR)/GNUmakefile : $(BUILDDIR)/index # Build the extractor transform for extracting the contents of the archive source file. $(BUILDDIR)/extractor.xslt : $(SRC) $(THISDIR)/lib/archive2extractor.xslt $(silent)$(call ensuredirectory,$(dir $@)) - $(silent)$(XSLTPROC) --nonet --novalid -o $(call quote,$@) $(call quote,$(THISDIR)/lib/archive2extractor.xslt) $(call quote,$<) + $(silent)$(XSLTPROC) --nonet --novalid --nomkdir --nowrite $(call quote,$(THISDIR)/lib/archive2extractor.xslt) $(call quote,$<) >|$(call quote,$@) # Use the extractor transform to extract the archive source file out into its components. #