X-Git-Url: https://git.ladys.computer/Shushe/blobdiff_plain/a9dfb3cd8b5a2a8a3c6b8ce90212638166a15fd3..90810b4c234960e725e770f331b13c4687f407c8:/GNUmakefile diff --git a/GNUmakefile b/GNUmakefile index 0b644c2..e09da91 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -146,12 +146,9 @@ MAGICDIR := $(patsubst ./%,%,$(THISDIR)/magic) # Configuration of `find´. # -# By default, `find´ will not follow symlinks and will use extended -# regular expressions, ignoring hidden files and those which begin with -# a period. -FINDOPTS := -PE -FINDRULES := -flags -nohidden -and -not -name '.*' -FINDINCLUDEOPTS := $(FINDOPTS) +# By default, `find´ will ignore hidden files, those which begin with a +# period, and those which are likely to cause problems for `make´. +FINDRULES := -flags -nohidden -and ! '(' '(' -name '[.-]*' -or -name '*[:|$$%]*' ')' -and -prune ')' FINDINCLUDERULES := $(FINDRULES) # The list of parsers for plaintext file types. @@ -210,7 +207,7 @@ override silent := $(if $(VERBOSE),,@) override sedesc = $(subst /,[/],$(subst $$,\$$,$(subst *,\*,$(subst .,\.,$(subst [,\[,$(subst ^,\^,$(subst \,\\,$1))))))) # (callable) Percent‐decode the given strings. -override perdec = $(foreach encoded,$1,$(shell $(PRINTF) '%s\n' $(call quote,$(encoded)) | $(SED) 's/`/`%60`/g;s/[\]/`%5C`/g;s/%[0-9A-Fa-f]\{2\}/`&`/g' | $(TR) '`' '\n' | $(SED) '/^%[0-9A-Fa-f]\{2\}$$/!s/%/`%25`/' | $(TR) '`' '\n' | $(AWK) '$$0!~/%/{printf("%s",$$0)}/%/{sub("%","0x");printf("\\%04o",$$0)}' | $(XARGS) -0 $(PRINTF) '%b')) +override perdec = $(foreach encoded,$1,$(shell $(PRINTF) '%s\n' $(call quote,$(encoded)) | $(SED) 's/|/%7C/g;s/[\]/%5C/g;s/%[0-9A-Fa-f]\{2\}/|&|/g' | $(TR) '|' '\n' | $(SED) '/^%[0-9A-Fa-f]\{2\}$$/!s/%/|%25|/' | $(TR) '|' '\n' | $(AWK) '$$0!~/%/{printf("%s",$$0)}/%/{sub("%","0x");printf("\\%04o",$$0)}' | $(XARGS) -0 $(PRINTF) '%b')) # (callable) Percent‐encode the given strings. # @@ -234,17 +231,17 @@ sourcefiles := $(filter-out $(sourceincludes),$(shell $(FIND) $(FINDOPTS) $(SRCD # Figure out the file type of each source file and source include. ifneq ($(wildcard $(BUILDDIR)/magic.mgc),) -override types := $(shell $(SED) 's/^ *//;s/ *$$//;s/ {2,}/ /g' <<< $(call quote,$(sourcefiles) $(sourceincludes)) | $(TR) ' ' '\n' | $(FILE) -m $(call quote,$(BUILDDIR)/magic.mgc) --mime-type --separator ':' --files-from - | $(SED) 's/: */:/g') +override types := $(shell $(SED) 's/^ *//;s/ *$$//;s/ {2,}/ /g' <<< $(call quote,$(sourcefiles) $(sourceincludes)) | $(TR) ' ' '\n' | $(FILE) -m $(call quote,$(BUILDDIR)/magic.mgc) --mime-type --separator '|' --files-from - | $(SED) 's/| */|/g') endif # Get the list of supported plaintext file types from the parser. ifneq ($(wildcard $(BUILDDIR)/parser.xslt),) -override plaintexttypes := $(filter-out $(XMLTYPES),$(shell $(XSLTPROC) $(call quote,$(THISDIR)/lib/parser2types.xslt) $(call quote,$(BUILDDIR)/parser.xslt))) +override plaintexttypes := $(filter-out $(XMLTYPES),$(shell $(XMLLINT) --xpath '/*/*[@name="书社:parsers"]//*[namespace-uri()="http://www.w3.org/1999/xhtml" and local-name()="dd"]/text()' $(call quote,$(BUILDDIR)/parser.xslt))) endif # (callable) Get all of the files (source and includes) which have the # given types. -override filesoftype = $(foreach type,$1,$(patsubst %:$(type),%,$(filter %:$(type),$(types)))) +override filesoftype = $(foreach type,$1,$(patsubst %|$(type),%,$(filter %|$(type),$(types)))) # Build up collections of various file types. override xmlfiles := $(call filesoftype,$(XMLTYPES)) @@ -252,7 +249,7 @@ override plaintextfiles := $(filter-out $(xmlfiles),$(call filesoftype,$(plainte override assetfiles := $(filter-out $(xmlfiles) $(plaintextfiles),$(sourcefiles) $(sourceincludes)) # (callable) Get the types of the given files. -override typeoffile = $(patsubst $(foreach file,$1,$(file):%),%,$(filter $(foreach file,$1,$(file):%),$(types))) +override typeoffile = $(patsubst $(foreach file,$1,$(file)|%),%,$(filter $(foreach file,$1,$(file)|%),$(types))) # (callable) Get the identifier for the given transform. override id = $(or $(shell $(XMLLINT) --xpath '/*/*[local-name()="id" and namespace-uri()="urn:fdc:ladys.computer:20231231:Shu1She4"]/text()[1]' $1),example:$(call pathenc,$(basename $(notdir $1)))) @@ -267,13 +264,13 @@ override includepath = $(firstword $(foreach directory,$(INCLUDEDIR),$(if $(filt override datauri = $(foreach file,$1,data:$(call typeoffile,$(file));base64,$(shell $(UUENCODE) -m -r $(call quote,$(file)) _ | tr -d ' \n')) # Pair each source file and include with its local u·r·i. -override sourcelocalpair = $(foreach file,$(sourcefiles) $(sourceincludes),$(if $(filter $(file),$(sourceincludes)),$(file):about:shushe?include=$(call pathenc,$(call includepath,$(file))),$(file):about:shushe?source=$(call pathenc,$(call sourcepath,$(file))))) +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))))) # (callable) Get local uris for the given files. -override localuri = $(foreach file,$1,$(patsubst $(file):%,%,$(filter $(file):%,$(sourcelocalpair)))) +override localuri = $(foreach file,$1,$(patsubst $(file)|%,%,$(filter $(file)|%,$(sourcelocalpair)))) # (callable) Get the source files for the given local uris. -override sourcefile = $(foreach local,$1,$(patsubst %:$(local),%,$(filter %:$(local),$(sourcelocalpair)))) +override sourcefile = $(foreach local,$1,$(patsubst %|$(local),%,$(filter %|$(local),$(sourcelocalpair)))) # Adds a requirement on `$(BUILDDIR)/.update-types´ if the file is # present. @@ -283,25 +280,25 @@ override sourcefile = $(foreach local,$1,$(patsubst %:$(local),%,$(filter %:$(lo # up‐to‐date immediately after the reload. override typeupdates := $(wildcard $(BUILDDIR)/.update-types) +# 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)))) + # (callable) Get the location of the transformed X·M·L files for the # given source files. -override parsed = $(foreach file,$1,$(if $(filter $(file),$(sourceincludes)),$(BUILDDIR)/includes/$(call includepath,$(file)),$(BUILDDIR)/sources/$(call sourcepath,$(file)))) - -# Pair each source file and include with its parsed location. -override sourceparsedpair = $(foreach file,$(sourcefiles) $(sourceincludes),$(file):$(call parsed,$(file))) +override parsed = $(foreach file,$1,$(patsubst $(file)|%,%,$(filter $(file)|%,$(sourceparsedpair)))) # (callable) Get the source files for the given parsed file. -override unparsed = $(foreach file,$1,$(patsubst %:$(file),%,$(filter %:$(file),$(sourceparsedpair)))) +override unparsed = $(foreach file,$1,$(patsubst %|$(file),%,$(filter %|$(file),$(sourceparsedpair)))) ifneq ($(wildcard $(BUILDDIR)/dependencies),) # Pair each file with a list of dependencies for it. -override dependenciesforfile := $(foreach file,$(sourcefiles),$(file):$(subst $(space),:,$(shell $(CAT) $(call quote,$(BUILDDIR)/dependencies) | $(SED) $(call quote,/^$(call sedesc,$(call localuri,$(file)))$$/$(comma)/^[^ ]/!d;/^ /!d;s/^ //)))) +override dependenciesforfile := $(foreach file,$(sourcefiles),$(file)|$(subst $(space),|,$(shell $(CAT) $(call quote,$(BUILDDIR)/dependencies) | $(SED) $(call quote,/^$(call sedesc,$(call localuri,$(file)))$$/$(comma)/^[^ ]/!d;/^ /!d;s/^ //)))) # (callable) Get the list of dependency leiris for the given source # files. # # Recursive dependencies are marked with a leading `-´. -override dependencyuris = $(foreach file,$1,$(subst :, ,$(patsubst $(file):%,%,$(filter $(file):%,$(dependenciesforfile))))) +override dependencyuris = $(foreach file,$1,$(subst |, ,$(patsubst $(file)|%,%,$(filter $(file)|%,$(dependenciesforfile))))) # (callable) Get the list of recursive dependencies for the given # source files. @@ -320,17 +317,29 @@ override recursivefiles := $(foreach file,$(filter-out $(assetfiles),$(sourcefil # This is all of the non·asset, nonrecursive files. override compilablefiles := $(filter-out $(assetfiles) $(recursivefiles),$(sourcefiles)) -# (callable) Get the compiled locations for the given source files. -override compiled = $(foreach file,$1,$(BUILDDIR)/public/$(call sourcepath,$(file))) +ifneq ($(wildcard $(BUILDDIR)/destinations),) +# Get the output of the destination transform. +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. +override destination = $(foreach file,$1,$(patsubst $(file)|%,%,$(filter $(file)|%,$(sourcedestinationpair)))) # Pair each source file and include with its compiled location. -override sourcecompiledpair = $(foreach file,$(sourcefiles) $(sourceincludes),$(file):$(call compiled,$(file))) +override sourcecompiledpair := $(foreach file,$(sourcefiles) $(sourceincludes),$(file)|$(BUILDDIR)/public/$(call destination,$(file))) + +# (callable) Get the location of the transformed X·M·L files for the +# given source files. +override compiled = $(foreach file,$1,$(patsubst $(file)|%,%,$(filter $(file)|%,$(sourcecompiledpair)))) # (callable) Get the source files for the given compiled file. -override uncompiled = $(foreach file,$1,$(patsubst %:$(file),%,$(filter %:$(file),$(sourcecompiledpair)))) +override uncompiled = $(foreach file,$1,$(patsubst %|$(file),%,$(filter %|$(file),$(sourcecompiledpair)))) # (callable) Get the installed locations for the given source files. -override installed = $(foreach file,$1,$(DESTDIR)/$(call sourcepath,$(file))) +override installed = $(foreach file,$1,$(DESTDIR)/$(call destination,$(file))) +endif # ─ ¶ Recipe Variable Definitions ───────────────────────────────────── @@ -364,12 +373,12 @@ install: $(call installed,$(recursivefiles) $(compilablefiles) $(filter $(source # List all source files and includes and their computed types. list: - $(silent)$(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)))) )) | $(TR) ' :' '\n ' + $(silent)$(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 ' # Raise an error when attempting to build any files with recursive # dependencies. -$(call compiled,$(recursivefiles)): $(BUILDDIR)/public/%: - @$(PRINTF) '%b\n' $(call quote,\0033[93;41mError:\0033[39;49m `$*´ has recursive dependencies:\n$(subst :, ,$(subst $(space),$(newline),$(foreach recursive,$(call recursives,$(SRCDIR)/$*),•:$(patsubst $(SRCDIR)/%,%,$(recursive)))))) && false +$(call compiled,$(recursivefiles)): + @$(PRINTF) '%b\n' $(call quote,\0033[93;41mError:\0033[39;49m `$(call uncompiled,$@)´ has recursive dependencies:\n$(subst |, ,$(subst $(space),$(newline),$(foreach recursive,$(call recursives,$(call uncompiled,$@)),•|$(recursive))))) && false # ─ ¶ Special Targets ───────────────────────────────────────────────── @@ -392,10 +401,10 @@ ifneq ($(wildcard $(BUILDDIR)/.update-types)$(wildcard $(BUILDDIR)/dependencies) # # This recipe only exists after types have been updated or when the # dependency graph already exists. -$(THISDIR)/GNUmakefile:: $(BUILDDIR)/dependencies +$(THISDIR)/GNUmakefile:: $(BUILDDIR)/dependencies $(BUILDDIR)/destinations $(silent)$(TOUCH) $(THISDIR)/GNUmakefile $(silent)$(RM) -f $(BUILDDIR)/.update-types - @$(PRINTF) '%b\n' '\0033[1mDependency graph updated. Restarting…\0033[22m' + @$(PRINTF) '%b\n' '\0033[1mDependency graph and output destinations updated. Restarting…\0033[22m' endif ifeq ($(wildcard $(BUILDDIR)/.update-types),) @@ -407,7 +416,7 @@ ifeq ($(wildcard $(BUILDDIR)/.update-types),) # # This recipe sleeps for one second to ensure that files built after # the restart have a more current time·stamp. -$(THISDIR)/GNUmakefile:: $(BUILDDIR)/magic.mgc $(BUILDDIR)/parser.xslt $(THISDIR)/lib/parser2types.xslt +$(THISDIR)/GNUmakefile:: $(BUILDDIR)/magic.mgc $(BUILDDIR)/parser.xslt $(silent)$(TOUCH) $(THISDIR)/GNUmakefile $(silent)$(RM) -f $(call quote,$(BUILDDIR)/dependencies) @$(PRINTF) '%b\n' '\0033[1mMagic file or parsers have updated. Restarting…\0033[22m' @@ -458,6 +467,13 @@ $(BUILDDIR)/dependencies: $(BUILDDIR)/catalog $(call parsed,$(plaintextfiles) $( @$(ECHO) "Identifying dependencies…" $(silent)$(XSLTPROC) -o $(call quote,$@) $(call quote,$(THISDIR)/lib/catalog2dependencies.xslt) $(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)/catalog $(call parsed,$(filter-out $(assetfiles),$(sourcefiles))) $(THISDIR)/lib/catalog2destinations.xslt + @$(ECHO) "Identifying output destinations…" + $(silent)$(XSLTPROC) -o $(call quote,$@) $(call quote,$(THISDIR)/lib/catalog2destinations.xslt) $(call quote,$<) + # Generate the main transform. $(BUILDDIR)/transform.catalog: $(TRANSFORMS) @$(ECHO) "Generating catalog of transforms…"