X-Git-Url: https://git.ladys.computer/Shushe/blobdiff_plain/5a363a0a9e519b88fed12252328acd4bfa7689e5..53a87e096837ce277a5b90303884796627760e2a:/GNUmakefile?ds=sidebyside
diff --git a/GNUmakefile b/GNUmakefile
index ca6bfcd..8f62e46 100644
--- a/GNUmakefile
+++ b/GNUmakefile
@@ -83,7 +83,7 @@ override define makefileinfo
║╰────────────────────────────────────────────────────────────╯║
╟┬ ¶ Copyright & License ─────────────────────────────────────┬╢
║│ │║
-║│ Copyright © 2023–2024 Lady [@ Ladys Computer]. │║
+║│ Copyright © 2023–2025 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 │║
@@ -188,6 +188,11 @@ EXTRAFINDINCLUDERULES :=
FINDRULES := '!' '(' '(' -name '[.-]*' -a '!' -name '.' -o -name '*[][*?:|$$%\#\\; ]*' -o -name '*[)]' ')' -a -prune ')'$(if $(EXTRAFINDRULES), -a '(' $(EXTRAFINDRULES) ')',)
FINDINCLUDERULES := $(FINDRULES)$(if $(EXTRAFINDINCLUDERULES), -a '(' $(EXTRAFINDINCLUDERULES) ')',)
+# Options to use when calling Make for the first build of a two‐stage build.
+#
+# This can be used to override variables which are only applicable to the second build.
+DATAOPTS :=
+
# File extensions which indicate files in `SRCDIR´ which should be built as part of the first, rather than second, stage of the two‐stage `MODE´.
DATAEXT := rdf
@@ -197,6 +202,46 @@ DATAEXT := rdf
EXTRAFINDDATARULES :=
FINDDATARULES := -name '.' $(foreach ext,$(DATAEXT), -o -name '$(subst ','"'"',[!.]*.$(ext))')$(if $(EXTRAFINDDATARULES), -a '(' $(EXTRAFINDDATARULES) ')',)
+# A semicolon‐separated list of regular expressions which paths should be required to match when finding files.
+FINDFILTERONLY :=
+
+# A semicolon‐separated list of regular expressions for paths which should be filtered out when finding files.
+FINDFILTEROUT :=
+
+# A semicolon‐separated list of regular expressions for paths which paths should be required to match when finding includes.
+#
+# This is generally only useful when `SRCDIR´ and `INCLUDEDIR´ point to the same location.
+# In that situation, this variable can be used to select certain files as includes, leaving the others to be recognized as sources instead.
+#
+# Otherwise, appropriately constructing `FINDFILTERONLY´ to look at the base directory of the files it finds should be sufficient.
+FINDINCLUDEFILTERONLY :=
+
+# A semicolon‐separated list of regular expressions for paths which should be filtered out in addition to those in `FINDFILTEROUT´ when finding includes.
+#
+# This is generally only useful when `SRCDIR´ and `INCLUDEDIR´ point to the same location.
+# In that situation, this variable can be used to exclude certain files from being recognized as includes, which will make them recognized as sources instead.
+#
+# Otherwise, appropriately constructing `FINDFILTEROUT´ to look at the base directory of the files it finds should be sufficient.
+FINDINCLUDEFILTEROUT :=
+
+# If not empty, the regular expression provided by `FINDFILTERONLY´ is an extended regular expression.
+FINDFILTERONLYEXTENDED :=
+
+# If not empty, the regular expression provided by `FINDFILTEROUT´ is an extended regular expression.
+#
+# By default, this matches `FINDFILTERONLYEXTENDED´
+FINDFILTEROUTEXTENDED := $(FINDFILTERONLYEXTENDED)
+
+# If not empty, the regular expression provided by `FINDFILTEROUT´ is an extended regular expression.
+#
+# By default, this matches `FINDFILTERONLYEXTENDED´
+FINDINCLUDEFILTERONLYEXTENDED := $(FINDFILTERONLYEXTENDED)
+
+# If not empty, the regular expression provided by `FINDINCLUDEFILTEROUT´ is an extended regular expression.
+#
+# By default, this matches `FINDFILTEROUTEXTENDED´
+FINDINCLUDEFILTEROUTEXTENDED := $(and $(FINDFILTERONLYEXTENDED),$(FINDFILTEROUTEXTENDED),1)
+
# The list of magic files to use when determining media types.
#
# Some are provided as part of this repository, but you can add more if you need different media type detection.
@@ -311,6 +356,9 @@ override not = $(if $1,,1)
# (callable) Quote the given string for use within shell calls.
override quote = '$(subst ','"'"',$1)'
+# (callable) Quote the given string for use defining a variable to send to a submake.
+override varquote = $(subst $$,$$$$,$(call quote,$1))
+
# The command to use for percent‐decoding.
override perdeccmd := $(SED) 's/|/%7C/g;s/[\]/%5C/g;s/%[0123456789ABCDEFabcdef]\{2\}/|&|/g' | $(TR) '|' '\n' | $(SED) '/^%[0123456789ABCDEFabcdef]\{2\}$$/!s/%/|%25|/' | $(TR) '|' '\n' | $(AWK) '$$0!~/%/{printf "%s",$$0}/%/{d="0123456789ABCDEF";v=substr(toupper($$0),2,2);printf "\\%04o",(index(d,substr(v,1,1))-1)*16+index(d,substr(v,2,1))-1}' | $(SED) $(call quote,s/'/'"'"'/g;s/^/'/;s/$$/'/;$$!s/$$/\\/) | $(XARGS) -E '' $(PRINTF) '%b'
@@ -385,7 +433,7 @@ override id = $(XMLLINT) --noent --nonet --xpath '/*/*[local-name()="id" and nam
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 $(makefile) 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
+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 $(makefile) NAME=$(call varquote,$3) SRC=$(call varquote,$1) BUILDDIR=$(call varquote,$(BUILDDIR)/archive/$3) DESTDIR=$(call varquote,$(patsubst %/,%,$(dir $2))) MODE='urn:fdc:ladys.computer:20231231:Shu1She4:mode:archive' $(call varquote,$2); else $(FINALIZE) $(call quote,$1) >|$(call quote,$2); fi
# ━ § BEGIN DEFAULT MAKE·FILE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
@@ -403,10 +451,10 @@ override attresc = $(subst ",",$(call xmlesc,$1))
override sedesc = $(subst /,[/],$(subst $$,\$$,$(subst *,\*,$(subst .,\.,$(subst [,\[,$(subst ^,\^,$(subst \,\\,$1)))))))
# (overridable) Collect all of the applicable includes from the includes directory.
-sourceincludes := $(if $(and $(INCLUDEDIR),$(wildcard $(INCLUDEDIR))),$(patsubst ./%,%,$(shell $(FIND) $(foreach dir,$(INCLUDEDIR),$(call quote,$(dir))) '(' $(FINDINCLUDERULES) ')' -a -type f -a -print)),)
+sourceincludes := $(foreach dir,$(INCLUDEDIR),$(and $(dir),$(wildcard $(dir)),$(patsubst ./%,%,$(shell $(FIND) $(call quote,$(dir)) '(' $(FINDINCLUDERULES) ')' -a -type f -a -print$(and $(FINDFILTERONLY),$(space)| $(GREP)$(and $(FINDFILTERONLYEXTENDED),$(space)-E) $(foreach filter,$(shell $(PRINTF) '%s\n' $(call quote,$(FINDFILTERONLY)) | $(TR) ' ;' '; '),-e $(call quote,$(subst ;, ,$(filter)))))$(and $(FINDINCLUDEFILTERONLY),$(space)| $(GREP)$(and $(FINDINCLUDEFILTERONLYEXTENDED),$(space)-E) $(foreach filter,$(shell $(PRINTF) '%s\n' $(call quote,$(FINDINCLUDEFILTERONLY)) | $(TR) ' ;' '; '),-e $(call quote,$(subst ;, ,$(filter)))))$(and $(FINDFILTEROUT),$(space)| $(GREP)$(and $(FINDFILTEROUTEXTENDED),$(space)-E) -v $(foreach filter,$(shell $(PRINTF) '%s\n' $(call quote,$(FINDFILTEROUT)) | $(TR) ' ;' '; '),-e $(call quote,$(subst ;, ,$(filter)))))$(and $(FINDINCLUDEFILTEROUT),$(space)| $(GREP)$(and $(FINDINCLUDEFILTEROUTEXTENDED),$(space)-E) -v $(foreach filter,$(shell $(PRINTF) '%s\n' $(call quote,$(FINDINCLUDEFILTEROUT)) | $(TR) ' ;' '; '),-e $(call quote,$(subst ;, ,$(filter)))))))))
# (overridable) Collect all of the applicable source files from the source directory, removing any which are also includes.
-sourcefiles := $(if $(and $(SRCDIR),$(wildcard $(SRCDIR))),$(filter-out $(sourceincludes),$(patsubst ./%,%,$(shell $(FIND) $(foreach dir,$(SRCDIR),$(call quote,$(dir))) '(' $(FINDRULES) ')' -a -type f -a -print))))
+sourcefiles := $(filter-out $(sourceincludes),$(foreach dir,$(SRCDIR),$(and $(dir),$(wildcard $(dir)),$(patsubst ./%,%,$(shell $(FIND) $(call quote,$(dir)) '(' $(FINDRULES) ')' -a -type f -a -print$(and $(FINDFILTERONLY),$(space)| $(GREP)$(and $(FINDFILTERONLYEXTENDED),$(space)-E) $(foreach filter,$(shell $(PRINTF) '%s\n' $(call quote,$(FINDFILTERONLY)) | $(TR) ' ;' '; '),-e $(call quote,$(subst ;, ,$(filter)))))$(and $(FINDFILTEROUT),$(space)| $(GREP)$(and $(FINDFILTEROUTEXTENDED),$(space)-E) -v $(foreach filter,$(shell $(PRINTF) '%s\n' $(call quote,$(FINDFILTEROUT)) | $(TR) ' ;' '; '),-e $(call quote,$(subst ;, ,$(filter))))))))))
# Figure out the file type of each source file and source include.
ifneq ($(wildcard $(BUILDDIR)/magic.mgc),)
@@ -440,7 +488,7 @@ override includepath = $(or $(firstword $(foreach directory,$(INCLUDEDIR),$(if $
# (callable) Get base64 data u·r·i’s for the given files.
#
# ☡ This variable creates a subshell every time it is computed.
-override datauri = $(foreach file,$1,data:$(call typeoffile,$(file));base64,$(shell $(UUENCODE) -m $(call quote,$(file)) _ | $(SED) '2,$$!d;$$d' | $(TR) -d ' \n'))
+override datauri = $(foreach file,$1,data:$(call typeoffile,$(file));base64,$(shell $(UUENCODE) -m $(call quote,$(abspath $(file))) _ | $(SED) '2,$$!d;$$d' | $(TR) -d ' \n'))
# Pair each source file and include with its local u·r·i.
override sourcelocalpair := $(foreach file,$(sourcefiles) $(sourceincludes),$(file)|about:shushe?$(if $(filter $(file),$(sourceincludes)),include=$(call pathenc,$(call includepath,$(file))),source=$(call pathenc,$(call sourcepath,$(file)))))
@@ -460,23 +508,32 @@ override typeupdates := $(and $(wildcard $(BUILDDIR)/.update-types),FORCE)
# Pair each source file and include with its metadata location.
override sourcemetadatapair := $(foreach file,$(sourcefiles) $(sourceincludes),$(file)|$(BUILDDIR)/$(if $(filter $(file),$(sourceincludes)),includes.metadata/$(call includepath,$(file)),sources.metadata/$(call sourcepath,$(file))))
-# (callable) Get the location of the transformed X·M·L files for the given source files.
+# (callable) Get the location of the metadata files for the given source files.
override metadata = $(foreach file,$1,$(patsubst $(file)|%,%,$(filter $(file)|%,$(sourcemetadatapair))))
-# (callable) Get the source files for the given parsed file.
+# (callable) Get the source files for the given metadata files.
override datadata = $(foreach file,$1,$(patsubst %|$(file),%,$(filter %|$(file),$(sourcemetadatapair))))
# Pair each source file and include with its parsed location.
-override sourceparsedpair := $(foreach file,$(sourcefiles) $(sourceincludes),$(file)|$(BUILDDIR)/$(if $(filter $(file),$(sourceincludes)),includes/$(call includepath,$(file)),sources/$(call sourcepath,$(file))))
+override sourceparsedpair := $(foreach file,$(sourcefiles) $(sourceincludes),$(file)|$(BUILDDIR)/$(if $(filter $(file),$(sourceincludes)),includes.parsed/$(call includepath,$(file)),sources.parsed/$(call sourcepath,$(file))))
# (callable) Get the location of the transformed X·M·L files for the given source files.
override parsed = $(foreach file,$1,$(patsubst $(file)|%,%,$(filter $(file)|%,$(sourceparsedpair))))
-# (callable) Get the source files for the given parsed file.
+# (callable) Get the source files for the given parsed files.
override unparsed = $(foreach file,$1,$(patsubst %|$(file),%,$(filter %|$(file),$(sourceparsedpair))))
-# Pair each build directory, transform, source file, or parsed file with its file u·r·i.
-override fileuripairs := $(join $(patsubst %,%|,$(BUILDDIR) $(TRANSFORMS) $(sourcefiles) $(sourceincludes) $(call parsed,$(sourcefiles) $(sourceincludes))),$(call pathenc,$(foreach uriable,$(BUILDDIR) $(TRANSFORMS) $(sourcefiles) $(sourceincludes) $(call parsed,$(sourcefiles) $(sourceincludes)),file://$(abspath $(uriable)))))
+# Pair each source file and include with its parsed result location.
+override parsepair := $(foreach file,$(sourcefiles) $(sourceincludes),$(file)|$(BUILDDIR)/$(if $(filter $(file),$(sourceincludes)),includes/$(call includepath,$(file)),sources/$(call sourcepath,$(file))))
+
+# (callable) Get the location of the parsed results for the given source files.
+override parseresult = $(foreach file,$1,$(patsubst $(file)|%,%,$(filter $(file)|%,$(parsepair))))
+
+# (callable) Get the source files for the given parsed results.
+override parsesource = $(foreach file,$1,$(patsubst %|$(file),%,$(filter %|$(file),$(parsepair))))
+
+# Pair each build directory, transform, source file, or parsed file, parse result file with its file u·r·i.
+override fileuripairs := $(join $(patsubst %,%|,$(BUILDDIR) $(TRANSFORMS) $(sourcefiles) $(sourceincludes) $(call parsed,$(sourcefiles) $(sourceincludes)) $(call parseresult,$(sourcefiles) $(sourceincludes))),$(call pathenc,$(foreach uriable,$(BUILDDIR) $(TRANSFORMS) $(sourcefiles) $(sourceincludes) $(call parsed,$(sourcefiles) $(sourceincludes)) $(call parseresult,$(sourcefiles) $(sourceincludes)),file://$(abspath $(uriable)))))
# (callable) Get the file u·r·is for the given transforms, source file or parsed files.
override fileuri = $(foreach file,$1,$(or $(patsubst $(file)|%,%,$(filter $(file)|%,$(fileuripairs))),$(error Unable to get file u·r·i for `$(file)´)))
@@ -548,14 +605,14 @@ override installed = $(foreach file,$1,$(DESTDIR)/$(call destination,$(file)))
# ─ ¶ Recipe Variable Definitions ─────────────────────────────────────
# (callable) Sanitize and wrap the provided plaintext file in X·M·L, printing to `stdout´.
-override wrapplaintext = { $(PRINTF) '%s\n%s' '' ''; }
+override wrapplaintext = { $(PRINTF) '%s\n%s' '' ''; }
# (callable) Check if the provided X·M·L file is X·M·L 1.1, and if so, coerce to X·M·L 1.0 as best as possible, printing the result (or the original file contents) to `stdout´.
#
# The X·M·L declaration will be dropped and character escapes for C0 control codes will be replaced with a literal `U+0091 PRIVATE USE ONE´, which is invalid in X·M·L 1.1, but valid X·M·L 1.0 (making the replacement obvious).
#
# This isn’t a perfect substitution (it makes some assumptions about the format of the underlying X·M·L), but it should be workable for most sensible, welformed files.
-override serializexml = $(SED) "$$($(PRINTF) '%b' '/]*?>//\n s/&\0043x0*[12345678BCEFbcef];/\0302\0221/g\n s/&\0043x0*1[0123456789ABCDEFabcdef];/\0302\0221/g\n s/&\00430*[12345678];/\0302\0221/g\n s/&\00430*1[12456789];/\0302\0221/g\n s/&\00430*2[0123456789];/\0302\0221/g\n s/&\00430*3[01];/\0302\0221/g\n}')" <$(call quote,$1) | $(SED) "$$($(PRINTF) '%b' ':a\n/^\\n*$$/{ $$d\n N\n ba\n}')"
+override serializexml = $(SED) "$$($(PRINTF) '%b' '/]*?>//\n s/&\0043x0*[12345678BCEFbcef];/\0302\0221/g\n s/&\0043x0*1[0123456789ABCDEFabcdef];/\0302\0221/g\n s/&\00430*[12345678];/\0302\0221/g\n s/&\00430*1[12456789];/\0302\0221/g\n s/&\00430*2[0123456789];/\0302\0221/g\n s/&\00430*3[01];/\0302\0221/g\n}')" <$(call quote,$(abspath $1)) | $(SED) "$$($(PRINTF) '%b' ':a\n/^\\n*$$/{ $$d\n N\n ba\n}')"
# ─ ¶ Phony Targets ───────────────────────────────────────────────────
@@ -608,12 +665,6 @@ $(THISDIR)/GNUmakefile : $(BUILDDIR)/transform.xslt
# ─ ¶ Build Targets ───────────────────────────────────────────────────
-# Generate R·D·F metadata for files.
-$(call metadata,$(sourcefiles) $(sourceincludes)) : % : $$(call datadata,$$@) $(THISDIR)/.metadata-format-changed-since $(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); $(DIFF) -u $(call quote,$(BUILDDIR)/.mtime) /dev/null | $(SED) '1!d;s/.* \([^ ]*\) \([^ ]*\).*$$/\1T\2Z/'; $(CKSUM) $(call quote,$<) | $(SED) 's/[ ].*//'; } | $(xargsmultiquote) | $(XARGS) -E '' $(PRINTF) '<书社vocab:$(if $(filter $<,$(sourceincludes)),IncludeFile,SourceFile) xmlns:nie="http://www.semanticdesktop.org/ontologies/2007/01/19/nie#" xmlns:nfo="http://www.semanticdesktop.org/ontologies/2007/03/22/nfo#" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:书社vocab="urn:fdc:ladys.computer:20231231:Shu1She4:vocab:" rdf:about="%s" 书社vocab:path="%s" nfo:fileUrl="%s">$(if $(filter $<,$(assetfiles)),,)<书社vocab:hasParsedFile nfo:fileUrl="%s"/>%s书社vocab:$(if $(filter $<,$(sourceincludes)),IncludeFile,SourceFile)>' $(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,$(call attresc,$(call fileuri,$(call parsed,$<)))) >|$(call quote,$@)
-
# Parse the files.
#
# Even plain X·M·L files are parsed, because they may contain X·H·T·M·L `