SHELL = /bin/sh # ━ § BASIC INFORMATION ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ override define makefileinfo ╭────────────────────────────╮ ╔╡ ⁌ ⛩️📰 书社 ∷ GNUmakefile ╞════════════════════════════════╗ ║╰────────────────────────────╯ ║ ╟┬ ¶ Prerequisites ───────────────────────────────────────────┬╢ ║│ │║ ║│ Requires G·N·U Make, at least version 3.81, a version of │║ ║│ uuencode with base64 support, and the various programs │║ ║│ offered by libxml2 and libxslt. Beyond this, only programs │║ ║│ required by Posix are used, altho there is a chance of │║ ║│ version incompatibilities. The full list of program │║ ║│ requirements is as follows :— │║ ║│ │║ ║│ • cat │║ ║│ • cp │║ ║│ • date │║ ║│ • echo │║ ║│ • file │║ ║│ • find │║ ║│ • mkdir (requires support for `-p´) │║ ║│ • mv │║ ║│ • printf │║ ║│ • rm │║ ║│ • sed │║ ║│ • sleep │║ ║│ • stat │║ ║│ • test │║ ║│ • touch │║ ║│ • tr (requires support for `-d´) │║ ║│ • uuencode (requires support for `-m´ and `-r´) │║ ║│ • xmlcatalog (provided by libxml2) │║ ║│ • xmllint (provided by libxml2) │║ ║│ • xsltproc (provided by libxslt) │║ ║│ │║ ║│ In all cases, you can supply your own version of any │║ ║│ program `program´ by overriding the corresponding variable │║ ║│ `PROGRAM´ when calling Make. │║ ║╰────────────────────────────────────────────────────────────╯║ ╟┬ ¶ Usage ───────────────────────────────────────────────────┬╢ ║│ │║ ║│ • `make all´: Compile, but do not install, all files. │║ ║│ │║ ║│ • `make clean´: Remove `BUILDDIR´. │║ ║│ │║ ║│ • `make gone´: Remove installed files. │║ ║│ │║ ║│ • `make help´ (default): Print this message. │║ ║│ │║ ║│ • `make install´: Compile all files and install in │║ ║│ `DESTDIR´. │║ ║│ │║ ║│ • `make list´: List all recognized source files and their │║ ║│ classification (including media type and dependencies). │║ ║│ │║ ║│ Set `VERBOSE=1´ to see the text of commands as they are │║ ║│ executed. │║ ║│ │║ ║│ See `README.markdown´ for a more involved description of │║ ║│ the capabilities and configuration of this program. │║ ║╰────────────────────────────────────────────────────────────╯║ ╟┬ ¶ Copyright & License ─────────────────────────────────────┬╢ ║│ │║ ║│ Copyright © 2023–2024 Lady [@ Lady’s 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 │║ ║│ not distributed with this file, You can obtain one at │║ ║│ . │║ ║╰────────────────────────────────────────────────────────────╯║ ╚══════════════════════════════════════════════════════════════╝ endef # ━ § MAKE·FILE SETUP ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ # Programs needed to run this make·file. # # If these are not installed on your computer, or you need to use a # different implementation, you can override the appropriate variable. CAT := cat CP := cp DATE := date ECHO := echo FILE := file FIND := find MKDIR := mkdir MV := mv PRINTF := printf RM := rm SED := sed SLEEP := sleep STAT := stat TEST := test TOUCH := touch TR := tr UUENCODE := uuencode XMLCATALOG := xmlcatalog XMLLINT := xmllint XSLTPROC := xsltproc # The directory which contains the source files. SRCDIR := sources # The directory which contains “includes”: Files which may be included # in other files but for which no final output will be generated. # # This can be inside of `SOURCES_DIRECTORY´ if desired. INCLUDEDIR := sources/includes # The directory in which to generate temporary buildfiles. BUILDDIR := build # The directory into which to output files on `make install´. DESTDIR := public # The location of this Makefile (and related ⛩️📰 书社 files), # relative to the current working directory. # # By default, this is inferred from the variable `MAKEFILE_LIST´. THISDIR := $(patsubst %/,%,$(dir $(lastword $(MAKEFILE_LIST)))) # The location of the magic files to use when determining media types. # # One is provided as part of this repository, but you can override it # if you need different media type detection. # # Your computer probably has a more comprehensive one installed at # `/usr/share/file/magic´, but it is not recommended that you use this # directly. Instead, link or copy just the files you expect to need for # your project. MAGICDIR := $(patsubst ./%,%,$(THISDIR)/magic) # Configuration of `find´. # # By default, `find´ will follow symlinks and use extended regular # expressions, ignoring hidden files and those which begin with a # period. FINDOPTS := -LE FINDRULES := -flags -nohidden -and -not -name '.*' # The list of parsers for plaintext file types. # # Which parsers are provided will influence which kinds of files are # recognized as plaintext. # # Each parser ⁜must⁜ have a template which matches ⁜only⁜ X·H·T·M·L # `')" # ─ ¶ Phony Targets ─────────────────────────────────────────────────── # Provide help. help: $(silent)$(PRINTF) '%b' '$(subst $(newline),\n,$(makefileinfo))' # Compile all files, or error if any are recursive. all: $(call compiled,$(recursivefiles) $(compilablefiles) $(filter $(sourcefiles),$(assetfiles))) ; # Destroy buildfiles. clean: $(silent)$(RM) -rf $(BUILDDIR)/ # Destroy buildfiles and the install directory. gone: $(silent)$(RM) -rf $(BUILDDIR)/ $(call compiled,$(recursivefiles) $(compilablefiles)) # Install the compiled files into `DESTDIR´. install: $(call installed,$(recursivefiles) $(compilablefiles) $(filter $(sourcefiles),$(assetfiles))) ; # 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 ' # 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 # ─ ¶ Special Targets ───────────────────────────────────────────────── # Perform secondary expansion; this enables pattern rules to determine # their prerequisites based on the matched pattern. .SECONDEXPANSION: ; # Don’t use any implicit rules. .SUFFIXES: ; # Phony rules; always consider these out‐of‐date. .PHONY: all default clean gone info install list $(call compiled,$(recursivefiles)); ifneq ($(wildcard $(BUILDDIR)/.update-types)$(wildcard $(BUILDDIR)/dependencies),) # Reload this make·file if the dependency graph has changed. # # This graph is a dependency for some of the variables that this # make·file uses, so it’s important to ensure that they are actually # up‐to‐date prior to executing any later rules. # # This recipe only exists after types have been updated or when the # dependency graph already exists. $(THISDIR)/GNUmakefile:: $(BUILDDIR)/dependencies $(silent)$(TOUCH) $(THISDIR)/GNUmakefile $(silent)$(RM) -f $(BUILDDIR)/.update-types @$(PRINTF) '%b\n' '\0033[1mDependency graph updated. Restarting…\0033[22m' endif ifeq ($(wildcard $(BUILDDIR)/.update-types),) # Reload this make·file if any of the magic files or parsers have # changed. # # These are used to classify source files, so if they have changed then # the make·file must be reloaded. # # 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 $(silent)$(TOUCH) $(THISDIR)/GNUmakefile $(silent)$(RM) -f $(call quote,$(BUILDDIR)/dependencies) @$(PRINTF) '%b\n' '\0033[1mMagic file or parsers have updated. Restarting…\0033[22m' $(silent)$(SLEEP) 1 $(silent)$(TOUCH) $(call quote,$(BUILDDIR)/.update-types) endif # ─ ¶ Build Targets ─────────────────────────────────────────────────── # Generate the compiled magic file from its sources. # # It must be updated if any of the files in the magic directory change. # It ⁜also⁜ should be updated if any of the files in the magic # directory are deleted, but this isn’t tracked presently. $(BUILDDIR)/magic.mgc: $(wildcard $(MAGICDIR)/*) @$(ECHO) "Compiling new magic…" $(silent)$(call ensuredirectory,$(dir $@)) $(silent)cd $(call quote,$(BUILDDIR)) && $(FILE) -C -m $(call quote,$(realpath $(MAGICDIR))) # Generate the main parser. $(BUILDDIR)/parser.catalog: $(PARSERS) @$(ECHO) "Generating catalog of parsers…" $(silent)$(XMLCATALOG) --create --noout $(call quote,$@) $(foreach parser,$(PARSERS),$(silent)$(XMLCATALOG) --add uri $(call quote,$(call id,$(parser))) $(call quote,../$(parser)) --noout $(call quote,$@)$(newline)) $(BUILDDIR)/parser.xslt: $(BUILDDIR)/parser.catalog $(THISDIR)/lib/catalog2parser.xslt @$(ECHO) "Generating main parser…" $(silent)$(XSLTPROC) -o $(call quote,$@) $(call quote,$(THISDIR)/lib/catalog2parser.xslt) $(call quote,$<) # Parse the files. # # Even plain X·M·L files are parsed, because they may contain X·H·T·M·L # `