aboutsummaryrefslogtreecommitdiffstats
path: root/mk
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--mk/README49
-rw-r--r--mk/all.mk27
-rw-r--r--mk/clean.mk36
-rw-r--r--mk/copy.mk78
-rw-r--r--mk/dist.mk156
-rw-r--r--mk/empty.mk86
-rw-r--r--mk/i18n.mk106
-rw-r--r--mk/lang-c.mk177
-rw-r--r--mk/man.mk109
-rw-r--r--mk/path.mk156
-rw-r--r--mk/tags.mk25
-rw-r--r--mk/texinfo.mk256
-rw-r--r--mk/tools.mk97
13 files changed, 1358 insertions, 0 deletions
diff --git a/mk/README b/mk/README
new file mode 100644
index 0000000..fd27fd0
--- /dev/null
+++ b/mk/README
@@ -0,0 +1,49 @@
+This is a collection of generic enough makefiles.
+Please feel free to use them in your project.
+
+Usage:
+ Include all.mk from your makefile.
+
+ It is a good idea to include path.mk before you define
+ path variables.
+
+ Read the top of each file for details.
+
+ Define the variables:
+
+ _VERSION
+ This version of the package.
+
+ _PROJECT
+ The name of the project. Must only include [a-z0-9_-].
+
+ _PROJECT_FULL
+ The name of the project. May include any character.
+
+ _SRC
+ All source code files. This list is used when
+ generating the translation template file.
+
+ _COPYRIGHT_HOLDER
+ The copyright holder's full name and e-mail address.
+
+ COMMAND
+ The name of the command. Must not be declared if
+ the package does not include exactly one runnable
+ command.
+
+ PKGNAME
+ The name of the package.
+
+ Variables beginning with __ are used internally by
+ the files where they appear, or in rare cases,
+ internally between these files.
+
+ Variables beginning with _ but not __ are set in the
+ makefile to specify for these files how they should
+ behave. They should not be changed by a user of the
+ package.
+
+ Variables that do not begin with _ are configurable
+ by the user of the package.
+
diff --git a/mk/all.mk b/mk/all.mk
new file mode 100644
index 0000000..7b00995
--- /dev/null
+++ b/mk/all.mk
@@ -0,0 +1,27 @@
+# Copyright (C) 2015 Mattias Andrée <maandree@member.fsf.org>
+#
+# Copying and distribution of this file, with or without modification,
+# are permitted in any medium without royalty provided the copyright
+# notice and this notice are preserved. This file is offered as-is,
+# without any warranty.
+
+
+#=== This file includes all the other files in appropriate order. ===#
+
+ifndef Q
+A = \e[35m
+Z = 
+endif
+
+include mk/path.mk
+include mk/empty.mk
+include mk/tools.mk
+include mk/copy.mk
+include mk/lang-c.mk
+include mk/texinfo.mk
+include mk/man.mk
+include mk/i18n.mk
+include mk/clean.mk
+include mk/dist.mk
+include mk/tags.mk
+
diff --git a/mk/clean.mk b/mk/clean.mk
new file mode 100644
index 0000000..4d6d1a4
--- /dev/null
+++ b/mk/clean.mk
@@ -0,0 +1,36 @@
+# Copyright (C) 2015 Mattias Andrée <maandree@member.fsf.org>
+#
+# Copying and distribution of this file, with or without modification,
+# are permitted in any medium without royalty provided the copyright
+# notice and this notice are preserved. This file is offered as-is,
+# without any warranty.
+
+
+#=== These rules are used for cleaning the repository of generated files. ===#
+
+
+# Delete all files are normally created during a build.
+.PHONY: clean
+clean:
+ @$(PRINTF_INFO) '\e[00;01;31mCLEANING\e[34m\e[00m\n'
+ -$(Q)$(RM) -r bin obj $(PKGNAME)-*.tar* $(PKGNAME)-*.checksums*
+ @$(ECHO)
+
+# Delete all files that are created during configuration.
+# Note, this, for some reason, should not imply `make clean`.
+.PHONY: distclean
+distclean:
+
+# Like `make clean` but do not remove massive binaries
+# that are seldom recompiled.
+.PHONY: mostlyclean
+mostlyclean: clean
+
+# Delete everything except ./configure
+.PHONY: maintainer-clean
+maintainer-clean: clean distclean
+ @$(ECHO)
+ @$(ECHO) 'This command is intended for maintainers to use; it'
+ @$(ECHO) 'deletes files that may need special tools to rebuild.'
+ @$(ECHO)
+
diff --git a/mk/copy.mk b/mk/copy.mk
new file mode 100644
index 0000000..c27604f
--- /dev/null
+++ b/mk/copy.mk
@@ -0,0 +1,78 @@
+# Copyright (C) 2015 Mattias Andrée <maandree@member.fsf.org>
+#
+# Copying and distribution of this file, with or without modification,
+# are permitted in any medium without royalty provided the copyright
+# notice and this notice are preserved. This file is offered as-is,
+# without any warranty.
+
+
+#=== These rules are used for legal files. ===#
+
+
+# Enables the rules:
+# install-copyright Install all files in _COPYING and _LICENSE
+# install-copying Install all files in _COPYING
+# install-license Install all files in _LICENSE
+
+
+# WHEN TO BUILD, INSTALL, AND UNINSTALL:
+
+install-base: install-copyright
+uninstall: uninstall-copyright
+
+
+# INSTALL RULES:
+
+.PHONY: install-copyright
+install-copyright:
+
+ifdef _COPYING
+.PHONY: install-copyright
+install-copyright: install-copying
+
+.PHONY: install-copying
+install-copying: $(_COPYING)
+ @$(PRINTF_INFO) '\e[00;01;31mINSTALL\e[34m %s\e[00m\n' "$@"
+ $(Q)$(INSTALL_DIR) -- "$(DESTDIR)$(LICENSEDIR)/$(PKGNAME)"
+ $(Q)$(INSTALL_DATA) $^ -- "$(DESTDIR)$(LICENSEDIR)/$(PKGNAME)"
+ @$(ECHO_EMPTY)
+endif
+
+ifdef _COPYING
+.PHONY: install-copyright
+install-copyright: install-license
+
+.PHONY: install-license
+install-license: $(_LICENSE)
+ @$(PRINTF_INFO) '\e[00;01;31mINSTALL\e[34m %s\e[00m\n' "$@"
+ $(Q)$(INSTALL_DIR) -- "$(DESTDIR)$(LICENSEDIR)/$(PKGNAME)"
+ $(Q)$(INSTALL_DATA) $^ -- "$(DESTDIR)$(LICENSEDIR)/$(PKGNAME)"
+ @$(ECHO_EMPTY)
+endif
+
+
+# UNINSTALL RULES:
+
+.PHONY: uninstall-copyright
+uninstall-copyright:
+
+ifdef _COPYING
+.PHONY: uninstall-copyright
+uninstall-copyright: uninstall-copying
+
+.PHONY: uninstall-copying
+uninstall-copying:
+ -$(Q)$(RM) -- $(foreach F,$(_COPYING),"$(DESTDIR)$(LICENSEDIR)/$(PKGNAME)/$(F)")
+ -$(Q)$(RMDIR) -- "$(DESTDIR)$(LICENSEDIR)/$(PKGNAME)"
+endif
+
+ifdef _COPYING
+.PHONY: uninstall-copyright
+uninstall-copyright: uninstall-license
+
+.PHONY: uninstall-license
+uninstall-license:
+ -$(Q)$(RM) -- $(foreach F,$(_LICENSE),"$(DESTDIR)$(LICENSEDIR)/$(PKGNAME)/$(F)")
+ -$(Q)$(RMDIR) -- "$(DESTDIR)$(LICENSEDIR)/$(PKGNAME)"
+endif
+
diff --git a/mk/dist.mk b/mk/dist.mk
new file mode 100644
index 0000000..8b98cce
--- /dev/null
+++ b/mk/dist.mk
@@ -0,0 +1,156 @@
+# Copyright (C) 2015 Mattias Andrée <maandree@member.fsf.org>
+#
+# Copying and distribution of this file, with or without modification,
+# are permitted in any medium without royalty provided the copyright
+# notice and this notice are preserved. This file is offered as-is,
+# without any warranty.
+
+
+#=== These rules are used for making releases. ===#
+
+
+# CONFIGURATIONS:
+
+# Formats for packages to generate.
+DIST_FORMATS = tar tar.xz tar.bz2 tar.gz
+
+# Define DO_NOT_SIGN if you do not want sign the release.
+
+# You can select checksums to generate:
+# Declaring NO_BSD_SUM will omit `sum -r`.
+# Declaring NO_SYSV_SUM will omit `sum -s`.
+# List all checksum programs, that do not require any flags, in DIST_CHECKSUMS.
+
+# Any missing flags for GnuPG?
+GPG_FLAGS =
+
+# What key should be used for signing?
+GPG_KEY ?=
+
+
+
+# HELP VARIALES:
+
+# The packages and there detached signatures (if any.)
+ifndef DO_NOT_SIGN
+__DIST_FILES = $(foreach F,$(DIST_FORMATS),$(_PROJECT)-$(_VERSION).$(F) $(_PROJECT)-$(_VERSION).$(F).sig)
+else
+__DIST_FILES = $(foreach F,$(DIST_FORMATS),$(_PROJECT)-$(_VERSION).$(F))
+endif
+
+# All known checksum programs that are unambiguous.
+__DIST_CHECKSUMS_ALL = cksum md2sum md4sum md5sum md6sum sha0sum sha1sum sha224sum \
+ sha256sum sha384sum sha512sum sha512-224sum sha512-256sum \
+ sha3-224sum sha3-256sum sha3-384sum sha3-512sum shake256sum \
+ shake512sum rawshake256sum rawshake512sum keccak-224sum \
+ keccak-256sum keccak-384sum keccak-512sum keccaksum
+
+# All installed checksum programs that are unambiguous.
+DIST_CHECKSUMS = $(foreach C,$(__DIST_CHECKSUMS_ALL),$(shell if command -v $(C) >/dev/null; then $(ECHO) $(C); fi))
+
+
+
+# MAKE RULES:
+
+# Generate release files. (Tarballs, compressed and uncompressed; signatures; checksums.)
+.PHONY: dist
+dist: dist-balls dist-checksums
+
+
+
+# HELP MAKE RULES:
+
+# Generate tarballs, compressed and uncompressed,
+.PHONY: dist-balls
+dist-balls: $(__DIST_FILES)
+
+ifndef DO_NOT_SIGN
+# Generate checksums and signature of checksums.
+.PHONY: dist-checksums
+dist-checksums: $(_PROJECT)-$(_VERSION).checksums $(_PROJECT)-$(_VERSION).checksums.sig
+
+# Generate uncompressed tarball and signature of it.
+.PHONY: dist-tar
+dist-tar: $(_PROJECT)-$(_VERSION).tar $(_PROJECT)-$(_VERSION).tar.sig
+
+# Generate xz-copressed tarball and signature of it.
+.PHONY: dist-xz
+dist-xz: $(_PROJECT)-$(_VERSION).tar.xz $(_PROJECT)-$(_VERSION).tar.xz.sig
+
+# Generate bz2-copressed tarball and signature of it.
+.PHONY: dist-bzip2
+dist-bz2: $(_PROJECT)-$(_VERSION).tar.bz2 $(_PROJECT)-$(_VERSION).tar.bz2.sig
+
+# Generate gzip-copressed tarball and signature of it.
+.PHONY: dist-gz
+dist-gz: $(_PROJECT)-$(_VERSION).tar.gz $(_PROJECT)-$(_VERSION).tar.sig
+else
+# Generate checksums, but no signature.
+.PHONY: dist-checksums
+dist-checksums: $(_PROJECT)-$(_VERSION).checksums
+
+# Generate uncompressed tarball, but no signature.
+.PHONY: dist-tar
+dist-tar: $(_PROJECT)-$(_VERSION).tar
+
+# Generate xz-compressed tarball, but no signature.
+.PHONY: dist-xz
+dist-xz: $(_PROJECT)-$(_VERSION).tar.xz
+
+# Generate bzip2-compressed tarball, but no signature.
+.PHONY: dist-bz2
+dist-bz2: $(_PROJECT)-$(_VERSION).tar.bz2
+
+# Generate gzip-compressed tarball, but no signature.
+.PHONY: dist-gz
+dist-gz: $(_PROJECT)-$(_VERSION).tar.gz
+endif
+
+# Generate the tarball for the release.
+$(_PROJECT)-$(_VERSION).tar:
+ @$(PRINTF_INFO) '\e[00;01;31mARCHIVE\e[34m %s\e[00m$A\n' "$@"
+ @if $(TEST) -f $@; then $(RM) $@; fi
+ $(Q)git archive --prefix=$(_PROJECT)-$(_VERSION)/ --format=tar $(_VERSION) -o $@ #$Z
+ @$(ECHO_EMPTY)
+
+# Compression rule for xz-compression. Used on the tarball.
+%.xz: %
+ @$(PRINTF_INFO) '\e[00;01;31mXZ\e[34m %s\e[00m$A\n' "$@"
+ @if $(TEST) -f $@; then $(RM) $@; fi
+ $(Q)$(XZ_COMPRESS) $< #$Z
+ @$(ECHO_EMPTY)
+
+# Compression rule for bzip2-compression. Used on the tarball.
+%.bz2: %
+ @$(PRINTF_INFO) '\e[00;01;31mBZIP2\e[34m %s\e[00m$A\n' "$@"
+ @if $(TEST) -f $@; then $(RM) $@; fi
+ $(Q)$(BZIP2_COMPRESS) $< #$Z
+ @$(ECHO_EMPTY)
+
+# Compression rule for gzip-compression. Used on the tarball.
+%.gz: %
+ @$(PRINTF_INFO) '\e[00;01;31mGZIP\e[34m %s\e[00m$A\n' "$@"
+ @if $(TEST) -f $@; then $(RM) $@; fi
+ $(Q)$(GZIP_COMPRESS) $< #$Z
+ @$(ECHO_EMPTY)
+
+# Generate checksums of tarballs, compressed and uncompressed, and of their detached signatures.
+$(_PROJECT)-$(_VERSION).checksums: $(__DIST_FILES)
+ @$(PRINTF_INFO) '\e[00;01;31mCHECKSUM\e[34m %s\e[00m\n' "$@"
+ @$(PRINTF) '' > $@
+ifndef NO_BSD_SUM
+ @if ! ($(ECHO) ':: sum -r ::' && sum -r $^ && $(ECHO)) >> $@ ; then $(PRINTF) '' > $@; fi
+endif
+ifndef NO_SYSV_SUM
+ @if ! ($(ECHO) ':: sum -s ::' && sum -s $^ && $(ECHO)) >> $@ ; then $(PRINTF) '' > $@; fi
+endif
+ @$(foreach C,$(DIST_CHECKSUMS),$(ECHO) ':: $(C) ::' >> $@ && $(C) $^ | $(GREP) -v '^--' >> $@ && $(ECHO) >> $@ &&) $(TRUE)
+ @$(ECHO_EMPTY)
+
+# Signing rule. Used on the tarballs, compressed and uncompressed, and on the checksum file.
+%.sig: %
+ @$(PRINTF_INFO) '\e[00;01;31mSIG\e[34m %s\e[00m$A\n' "$@"
+ @if $(TEST) -f $@; then $(RM) $@; fi
+ $(Q)$(GPG) $(GPG_FLAGS) --local-user $(GPG_KEY) --detach-sign --armor --output $@ < $< #$Z
+ @$(ECHO_EMPTY)
+
diff --git a/mk/empty.mk b/mk/empty.mk
new file mode 100644
index 0000000..6e95a1e
--- /dev/null
+++ b/mk/empty.mk
@@ -0,0 +1,86 @@
+# Copyright (C) 2015 Mattias Andrée <maandree@member.fsf.org>
+#
+# Copying and distribution of this file, with or without modification,
+# are permitted in any medium without royalty provided the copyright
+# notice and this notice are preserved. This file is offered as-is,
+# without any warranty.
+
+
+#=== This file includes empty rules that are filled by other files. ===#
+
+
+.PHONY: all
+all:
+
+.PHONY: everything
+everything:
+
+.PHONY: base
+base:
+
+.PHONY: cmd
+cmd:
+
+.PHONY: doc
+doc:
+
+
+.PHONY: install
+install:
+
+.PHONY: install-everything
+install-everything:
+
+.PHONY: install-base
+install-base:
+
+.PHONY: install-cmd
+install-cmd:
+
+.PHONY: install-doc
+install-doc:
+
+
+.PHONY: uninstall
+uninstall:
+
+
+
+.PHONY: all
+all: base
+
+.PHONY: everything
+everything: base
+
+.PHONY: base
+base: cmd
+
+
+.PHONY: install
+install: install-base
+
+.PHONY: install-everything
+install-everything: install-base
+
+.PHONY: install-base
+install-base: install-cmd
+
+
+
+.PHONY: install-strip
+install-strip: __STRIP = -s
+install-strip: install
+
+.PHONY: install-everything-strip
+install-everything-strip: __STRIP = -s
+install-everything-strip: install-everything
+
+.PHONY: install-base-strip
+install-base-strip: __STRIP = -s
+install-base-strip: install-base
+
+.PHONY: install-cmd-strip
+install-cmd-strip: __STRIP = -s
+install-cmd-strip: install-cmd
+
+
diff --git a/mk/i18n.mk b/mk/i18n.mk
new file mode 100644
index 0000000..526bc1f
--- /dev/null
+++ b/mk/i18n.mk
@@ -0,0 +1,106 @@
+# Copyright (C) 2015 Mattias Andrée <maandree@member.fsf.org>
+#
+# Copying and distribution of this file, with or without modification,
+# are permitted in any medium without royalty provided the copyright
+# notice and this notice are preserved. This file is offered as-is,
+# without any warranty.
+
+
+#=== These rules are used for internationalisation. ===#
+
+
+# Enables the rules:
+# locale Build all translations.
+# update-po Update all .po files for further translation.
+# install-locale Install all locales.
+#
+# "All locales" are those listed in LOCALES.
+# If LOCALES is not defined, this file is ignored.
+#
+# If WITHOUT_GETTEXT is defined, `locale` and
+# `install-locale` will not do anything.
+
+
+ifdef LOCALES
+
+
+# WHEN TO BUILD, INSTALL, AND UNINSTALL:
+
+all: locale
+everything: locale
+install: install-locale
+install-everything: install-locale
+uninstall: uninstall-locale
+
+
+# BUILD RULES:
+
+# Build all translations.
+ifdef WITHOUT_GETTEXT
+.PHONY: locale
+locale:
+else
+.PHONY: locale
+locale: $(foreach L,$(LOCALES),bin/mo/$(L)/messages.mo)
+endif
+
+# Update all translation files for further translation.
+.PHONY: update-po
+update-po: $(foreach L,$(LOCALES),po/$(L).po)
+
+# Generate template for translations.
+obj/$(_PROJECT).pot: $(foreach S,$(_SRC),src/$(S).c)
+ @$(PRINTF_INFO) '\e[00;01;31mPOT\e[34m %s\e[00m$A\n' "$@"
+ @$(MKDIR) -p obj
+ $(Q)$(CPP) -DUSE_GETTEXT=1 $^ | \
+ $(XGETTEXT) -o "$@" -Lc --from-code utf-8 --package-name "$(_PROJECT_FULL)" \
+ --package-version $(_VERSION) --no-wrap --force-po \
+ --copyright-holder '$(_COPYRIGHT_HOLDER)' - #$Z
+ @$(ECHO_EMPTY)
+
+# Create or update a translation file.
+po/%.po: obj/$(_PROJECT).pot
+ @$(PRINTF_INFO) '\e[00;01;31mPO\e[34m %s\e[00m$A\n' "$@"
+ @$(MKDIR) -p po
+ $(Q)if ! $(TEST) -e $@; then \
+ $(MSGINIT) --no-translator --no-wrap -i $< -o $@ -l $*; \
+ else \
+ $(MSGMERGE) --no-wrap -U $@ $<; \
+ fi #$Z
+ @$(TOUCH) $@
+ @$(ECHO_EMPTY)
+
+# Compile a translation file.
+bin/mo/%/messages.mo: po/%.po
+ @$(PRINTF_INFO) '\e[00;01;31mMO\e[34m %s\e[00m$A\n' "$@"
+ @$(MKDIR) -p bin/mo/$*
+ $(Q)cd bin/mo/$* && $(MSGFMT) ../../../$< #$Z
+ @$(ECHO_EMPTY)
+
+
+# INSTALL RULES:
+
+# Install all locales.
+ifdef WITHOUT_GETTEXT
+.PHONY: install-locale
+install-locale:
+else
+.PHONY: install-locale
+install-locale: $(foreach L,$(LOCALES),bin/mo/$(L)/messages.mo)
+ @$(PRINTF_INFO) '\e[00;01;31mINSTALL\e[34m %s\e[00m\n' "$@"
+ $(Q)$(INSTALL) -dm755 -- $(foreach L,$(LOCALES),"$(DESTDIR)$(LOCALEDIR)/$(L)/LC_MESSAGES")
+ $(Q)$(foreach L,$(LOCALES),$(INSTALL_DATA) bin/mo/$(L)/messages.mo -- "$(DESTDIR)$(LOCALEDIR)/$(L)/LC_MESSAGES/$(PKGNAME).mo" &&) $(TRUE)
+ @$(ECHO_EMPTY)
+endif
+
+
+# UNINSTALL RULES:
+
+# Uninstall all locales.
+.PHONY: uninstall-locale
+uninstall-locale:
+ -$(Q)$(RM) -- $(foreach L,$(LOCALES),"$(DESTDIR)$(LOCALEDIR)/$(L)/LC_MESSAGES/$(PKGNAME).mo")
+
+
+endif
+
diff --git a/mk/lang-c.mk b/mk/lang-c.mk
new file mode 100644
index 0000000..a76a4c3
--- /dev/null
+++ b/mk/lang-c.mk
@@ -0,0 +1,177 @@
+# Copyright (C) 2015 Mattias Andrée <maandree@member.fsf.org>
+#
+# Copying and distribution of this file, with or without modification,
+# are permitted in any medium without royalty provided the copyright
+# notice and this notice are preserved. This file is offered as-is,
+# without any warranty.
+
+
+#=== This file includes rules for C programs. ===#
+
+
+# This file is ignored unless _C_STD is defined.
+# _C_STD should be set the the version of C that
+# is used.
+#
+# If you want to compile with -pedantic, define
+# the variable _PEDANTIC.
+#
+# Define _CPPFLAGS with any additional CPP
+# flags to use, _CFLAGS with any additional CC
+# flags to use, and _LDFLAGS with any additional
+# LD flags to use.
+#
+# Defined in path.mk, you can change _ALL_DIRS
+# if you do not want CPP definitions for all
+# directories.
+#
+# Define _HEADER_DIRLEVELS to specify the directory
+# nesting level in src. It is assumed that all
+# directories contain header files. Set to '0' if
+# there are no header files.
+#
+# _BIN shall list all commands to build. These
+# should be the basenames. For each command
+# you should be the variable _OBJ_$(COMMAND)
+# that lists all objects files (without the
+# suffix and without the obj/ prefix) that
+# are required to build the command.
+
+
+ifdef _C_STD
+
+
+
+# WHEN TO BUILD, INSTALL, AND UNINSTALL:
+
+cmd: cmd-c
+install-cmd: install-cmd-c
+uninstall: uninstall-cmd-c
+
+
+# HELP VARIABLES:
+
+# Figure out whether the GCC is being used.
+ifeq ($(shell $(PRINTF) '%s\n' ${CC} | $(HEAD) -n 1),gcc)
+__USING_GCC = 1
+endif
+
+
+# BUILD VARIABLES:
+
+# Optimisation settings for C code compilation.
+ifdef DEBUG
+OPTIMISE = -Og -g
+else
+ifndef OPTIMISE
+OPTIMISE = -O2
+endif
+endif
+
+# Warning settings for C code compilation.
+ifdef _PEDANTIC
+_PEDANTIC = -pedantic
+endif
+ifdef __USING_GCC
+WARN = -Wall -Wextra $(_PEDANTIC) -Wdouble-promotion -Wformat=2 -Winit-self -Wmissing-include-dirs \
+ -Wtrampolines -Wmissing-prototypes -Wmissing-declarations -Wnested-externs \
+ -Wno-variadic-macros -Wsync-nand -Wunsafe-loop-optimizations -Wcast-align \
+ -Wdeclaration-after-statement -Wundef -Wbad-function-cast -Wwrite-strings -Wlogical-op \
+ -Wstrict-prototypes -Wold-style-definition -Wpacked -Wvector-operation-performance \
+ -Wunsuffixed-float-constants -Wsuggest-attribute=const -Wsuggest-attribute=noreturn \
+ -Wsuggest-attribute=format -Wnormalized=nfkc -fstrict-aliasing -fipa-pure-const -ftree-vrp \
+ -fstack-usage -funsafe-loop-optimizations -Wshadow -Wredundant-decls -Winline -Wcast-qual \
+ -Wsign-conversion -Wstrict-overflow=5 -Wconversion -Wsuggest-attribute=pure -Wswitch-default \
+ -Wstrict-aliasing=1 -fstrict-overflow -Wfloat-equal -Wpadded -Waggregate-return \
+ -Wtraditional-conversion
+else
+WARN = -Wall -Wextra $(_PEDANTIC)
+endif
+
+# Support for internationalisation?
+ifndef WITHOUT_GETTEXT
+_CPPFLAGS += -D'USE_GETTEXT=1'
+endif
+
+# Add CPP definitions for all directories.
+_CPPFLAGS += $(foreach D,$(_ALL_DIRS),-D'$(D)="$($(D))"')
+
+
+# MORE HELP VARIABLES:
+
+# Compilation and linking flags, and command.
+__CC = $(CC) -std=$(_C_STD) $(OPTIMISE) $(WARN) $(_CPPFLAGS) $(_CFLAGS) -c
+__LD = $(CC) -std=$(_C_STD) $(OPTIMISE) $(WARN) $(_LDFLAGS)
+__CC_POST = $(CPPFLAGS) $(CFLAGS)
+__LD_POST = $(LDFLAGS)
+
+# Header files.
+__H =
+ifdef _HEADER_DIRLEVELS
+ifeq ($(_HEADER_DIRLEVELS),1)
+__H += src/*.h
+else
+ifeq ($(_HEADER_DIRLEVELS),2)
+__H += src/*.h
+__H += src/*/*.h
+else
+ifneq ($(_HEADER_DIRLEVELS),0)
+__H += $(foreach W,$(shell $(SEQ) $(_HEADER_DIRLEVELS) | while read n; do $(ECHO) $$($(SEQ) $$n)" " | $(SED) 's/[^ ]* /\/\*/g'; done | $(XARGS) $(ECHO)),src$(W).h)
+endif
+endif
+endif
+endif
+
+
+# BUILD RULES:
+
+.PHONY: cmd-c
+cmd-c: $(foreach B,$(_BIN),bin/$(B))
+
+# Compile a C file into an object file.
+obj/%.o: src/%.c $(__H)
+ @$(PRINTF_INFO) '\e[00;01;31mCC\e[34m %s\e[00m$A\n' "$@"
+ @$(MKDIR) -p $(shell dirname $@)
+ $(Q)$(__CC) -o $@ $< $(__CC_POST) #$Z
+ @$(ECHO_EMPTY)
+
+# Link object files into a command.
+# Dependencies are declared below..
+bin/%:
+ @$(PRINTF_INFO) '\e[00;01;31mLD\e[34m %s\e[00;32m$A\n' "$@"
+ @$(MKDIR) -p bin
+ $(Q)$(__LD) -o $@ $^ $(__LD_POST) #$Z
+ @$(ECHO_EMPTY)
+
+# Dependencies for the rule above.
+$(foreach B,$(_BIN),$(foreach O,$(_OBJ_$(B)),bin/$(B): obj/$(O).o\
+))
+
+
+# INSTALL RULES:
+
+.PHONY: install-cmd-c
+install-cmd-c: $(foreach B,$(_BIN),bin/$(B))
+ @$(PRINTF_INFO) '\e[00;01;31mINSTALL\e[34m %s\e[00m\n' "$@"
+ $(Q)$(INSTALL_DIR) -- "$(DESTDIR)$(BINDIR)"
+ifdef COMMAND
+ $(Q)$(INSTALL_PROGRAM) $(__STRIP) $^ -- "$(DESTDIR)$(BINDIR)"
+else
+ $(Q)$(INSTALL_PROGRAM) $(__STRIP) $^ -- "$(DESTDIR)$(BINDIR)/$(COMMAND)"
+endif
+ @$(ECHO_EMPTY)
+
+
+# UNINSTALL RULES:
+
+.PHONY: uninstall-cmd-c
+uninstall-cmd-c:
+ifdef COMMAND
+ -$(Q)$(RM) -- "$(DESTDIR)$(BINDIR)/$(COMMAND)"
+else
+ -$(Q)$(RM) -- $(foreach B,$(_BIN),"$(DESTDIR)$(BINDIR)/$(B)")
+endif
+
+
+endif
+
diff --git a/mk/man.mk b/mk/man.mk
new file mode 100644
index 0000000..fa85de6
--- /dev/null
+++ b/mk/man.mk
@@ -0,0 +1,109 @@
+# Copyright (C) 2015 Mattias Andrée <maandree@member.fsf.org>
+#
+# Copying and distribution of this file, with or without modification,
+# are permitted in any medium without royalty provided the copyright
+# notice and this notice are preserved. This file is offered as-is,
+# without any warranty.
+
+
+#=== These rules are used for man pages. ===#
+
+
+# Enables the rules:
+# install-man Install all man page
+# install-man-untranslated Install untranslated man page
+# install-man-locale Install translated man page
+#
+# This file is ignored unless _MAN_PAGE_SECTIONS
+# is defined. _MAN_PAGE_SECTIONS should list all
+# used man page sections. For all used sections
+# there should also be a variable named
+# _MAN_$(SECTION) that lists the suffixless
+# basename of all man pages in that section.
+#
+# The pathname of a man page should look
+# like this: doc/man/$(DOCUMENT).$(SECTION)
+# Translations looks like this:
+# doc/man/$(DOCUMENT).$(LANGUAGE).$(SECTION)
+#
+# For each language and section, there should
+# be a variable _MAN_$(LANGUAGE)_$(SECTION)
+# that lists all translated documents in that
+# section and for that lanuage. These should
+# be suffixless basenames. The lanuage counts
+# as a suffix.
+#
+# The translations of the man pages to
+# install should be specified, by language,
+# in the variable MAN_LOCALES.
+
+
+ifdef _MAN_PAGE_SECTIONS
+
+
+# WHEN TO BUILD, INSTALL, AND UNINSTALL:
+
+install: install-man
+install-everything: install-man
+install-doc: install-man
+uninstall: uninstall-man
+
+
+# HELP VARIABLES
+
+# Customisable man page filename.
+ifdef COMMAND
+ifeq ($(shell $(PRINTF) '%s\n' $(COMMAND) | $(WC) -l),1)
+ifeq ($(shell $(PRINTF) '%s\n' $(_MAN_PAGE_SECTIONS) | $(WC) -l),1)
+ifeq ($(shell $(PRINTF) '%s\n' $(_MAN_$(_MAN_PAGE_SECTIONS)) | $(WC) -l),1)
+__MAN_COMMAND = $(COMMAND).$(MAN$(_MAN_PAGE_SECTIONS)EXT)
+endif
+endif
+endif
+endif
+
+
+# INSTALL RULES:
+
+.PHONY: install-man
+install-man: install-man-untranslated install-man-locale
+
+.PHONY: install-man-untranslated
+install-man-untranslated:
+ @$(PRINTF_INFO) '\e[00;01;31mINSTALL\e[34m %s\e[00m\n' "$@"
+ $(Q)$(INSTALL_DIR) -- $(foreach S,$(_MAN_PAGE_SECTIONS),"$(DESTDIR)$(MANDIR)$(MAN$(S))")
+ifndef __MAN_COMMAND
+ $(Q)$(foreach S,$(_MAN_PAGE_SECTIONS),$(foreach P,$(_MAN_$(S)),$(INSTALL_DATA) doc/man/$(P).$(S) -- "$(DESTDIR)$(MANDIR)$(MAN$(S))/$(P).$(MAN$(S)EXT)" &&)) $(TRUE)
+else
+ $(Q)$(foreach S,$(_MAN_PAGE_SECTIONS),$(foreach P,$(_MAN_$(S)),$(INSTALL_DATA) doc/man/$(P).$(S) -- "$(DESTDIR)$(MANDIR)$(MAN$(S))/$(__MAN_COMMAND)" &&)) $(TRUE)
+endif
+ @$(ECHO_EMPTY)
+
+.PHONY: install-man-locale
+install-man-locale:
+ @$(PRINTF_INFO) '\e[00;01;31mINSTALL\e[34m %s\e[00m\n' "$@"
+ $(Q)$(foreach L,$(MAN_LOCALES),$(INSTALL_DIR) -- $(foreach S,$(_MAN_PAGE_SECTIONS),"$(DESTDIR)$(MANDIR)/$(L)$(MAN$(S))") &&) $(TRUE)
+ifndef __MAN_COMMAND
+ $(Q)$(foreach L,$(MAN_LOCALES),$(foreach S,$(_MAN_PAGE_SECTIONS),$(foreach P,$(_MAN_$(L)_$(S)),$(INSTALL_DATA) doc/man/$(P).$(L).$(S) -- "$(DESTDIR)$(MANDIR)/$(L)$(MAN$(S))/$(P).$(MAN$(S)EXT)" &&))) $(TRUE)
+else
+ $(Q)$(foreach L,$(MAN_LOCALES),$(foreach S,$(_MAN_PAGE_SECTIONS),$(foreach P,$(_MAN_$(L)_$(S)),$(INSTALL_DATA) doc/man/$(P).$(L).$(S) -- "$(DESTDIR)$(MANDIR)/$(L)$(MAN$(S))/$(__MAN_COMMAND)" &&))) $(TRUE)
+endif
+ @$(ECHO_EMPTY)
+
+
+
+# UNINSTALL RULES:
+
+.PHONY: uninstall-man
+uninstall-man:
+ifndef __MAN_COMMAND
+ -$(Q)$(RM) -- $(foreach S,$(_MAN_PAGE_SECTIONS),$(foreach P,$(_MAN_$(S)),"$(DESTDIR)$(MANDIR)$(MAN$(S))/$(P).$(MAN$(S)EXT)"))
+ -$(Q)$(RM) -- $(foreach L,$(MAN_LOCALES),$(foreach S,$(_MAN_PAGE_SECTIONS),$(foreach P,$(_MAN_$(L)_$(S)),"$(DESTDIR)$(MANDIR)/$(L)$(MAN$(S))/$(P).$(MAN$(S)EXT)")))
+else
+ -$(Q)$(RM) -- "$(DESTDIR)$(MANDIR)$(MAN$(_MAN_PAGE_SECTIONS))/$(__MAN_COMMAND)"
+ -$(Q)$(RM) -- $(foreach L,$(MAN_LOCALES),$(foreach S,$(_MAN_PAGE_SECTIONS),$(foreach P,$(_MAN_$(L)_$(S)),"$(DESTDIR)$(MANDIR)/$(L)$(MAN$(S))/$(__MAN_COMMAND)")))
+endif
+
+
+endif
+
diff --git a/mk/path.mk b/mk/path.mk
new file mode 100644
index 0000000..060a1c0
--- /dev/null
+++ b/mk/path.mk
@@ -0,0 +1,156 @@
+# Copyright (C) 2015 Mattias Andrée <maandree@member.fsf.org>
+#
+# Copying and distribution of this file, with or without modification,
+# are permitted in any medium without royalty provided the copyright
+# notice and this notice are preserved. This file is offered as-is,
+# without any warranty.
+
+
+#=== This file define path variables. ===#
+
+
+ifndef __PATH_MK_INCLUDED
+__PATH_MK_INCLUDED = 1
+
+
+# DIRECTORIES:
+
+# The package path prefix, if you want to install to another root, set DESTDIR to that root.
+PREFIX = /usr
+# The command path excluding prefix.
+BIN = /bin
+# The administration command path excluding prefix.
+SBIN = /sbin
+# The library path excluding prefix.
+LIB = /lib
+# The executable library path excluding prefix.
+LIBEXEC = /libexec
+# The header-file path excluding prefix.
+INCLUDE = /include
+# The resource path excluding prefix.
+DATA = /share
+# The man page sections path excluding prefix.
+MAN0 = /man0
+MAN1 = /man1
+MAN2 = /man2
+MAN3 = /man3
+MAN4 = /man4
+MAN5 = /man5
+MAN6 = /man6
+MAN7 = /man7
+MAN8 = /man8
+MAN9 = /man9
+
+# The command path including prefix.
+BINDIR = $(PREFIX)$(BIN)
+# The administration command path including prefix.
+SBINDIR = $(PREFIX)$(SBIN)
+# The library path including prefix.
+LIBDIR = $(PREFIX)$(LIB)
+# The executable library path including prefix.
+LIBEXECDIR = $(PREFIX)$(LIBEXEC)
+# The header-file path including prefix.
+INCLUDEDIR = $(PREFIX)$(INCLUDE)
+# The resource path including prefix.
+DATADIR = $(PREFIX)$(DATA)
+# The architecture-dependent resource path including prefix.
+SYSDEPDATA = $(DATADIR)
+# The generic documentation path including prefix.
+DOCDIR = $(DATADIR)/doc
+# The info manual documentation path including prefix.
+INFODIR = $(DATADIR)/info
+# The DVI documentation path including prefix.
+DVIDIR = $(DOCDIR)
+# The PDF documentation path including prefix.
+PDFDIR = $(DOCDIR)
+# The PostScript documentation path including prefix.
+PSDIR = $(DOCDIR)
+# The HTML documentation path including prefix.
+HTMLDIR = $(DOCDIR)
+# The man page documentation path including prefix.
+MANDIR = $(DATADIR)/man
+# The locale path including prefix.
+LOCALEDIR = $(DATADIR)/locale
+# The license base path including prefix.
+LICENSEDIR = $(DATADIR)/licenses
+# The persistent variable data directory.
+VARDIR = /var
+# The persistent directory for temporary files.
+VARTMPDIR = $(VARDIR)/tmp
+# The network-common persistent variable data directory.
+COMDIR = /com
+# The network-common persistent directory for temporary files.
+COMTMPDIR = $(COMDIR)/tmp
+# The transient directory for temporary files.
+TMPDIR = /tmp
+# The transient directory for runtime files.
+RUNDIR = /run
+# The directory for site-specific configurations.
+SYSCONFDIR = /etc
+# The directory for pseudo-devices.
+DEVDIR = /dev
+# The /sys directory.
+SYSDIR = /sys
+# The /proc directory
+PROCDIR = /proc
+# The /proc/self directory
+SELFPROCDIR = $(PROCDIR)/self
+# The cache directory.
+CACHEDIR = $(VARDIR)/cache
+# The spool directory.
+SPOOLDIR = $(VARDIR)/spool
+# The empty directory.
+EMPTYDIR = $(VARDIR)/empty
+# The logfile directory.
+LOGDIR = $(VARDIR)/log
+# The state directory.
+STATEDIR = $(VARDIR)/lib
+# The highscore directory.
+GAMEDIR = $(VARDIR)/games
+# The lockfile directory.
+LOCKDIR = $(RUNDIR)/lock
+# The user skeleton directory.
+SKELDIR = $(SYSCONFDIR)/skel
+# The network-common cache directory.
+COMCACHEDIR = $(COMDIR)/cache
+# The network-common spool directory.
+COMSPOOLDIR = $(COMDIR)/spool
+# The network-common empty directory.
+COMEMPTYDIR = $(COMDIR)/empty
+# The network-common logfile directory.
+COMLOGDIR = $(COMDIR)/log
+# The network-common state directory.
+COMSTATEDIR = $(COMDIR)/lib
+# The network-common highscore directory.
+COMGAMEDIR = $(COMDIR)/games
+
+
+# FILENAME SUFFIXES:
+
+# Filename suffixes for man pages by section.
+MAN0EXT = 0
+MAN1EXT = 1
+MAN2EXT = 2
+MAN3EXT = 3
+MAN4EXT = 4
+MAN5EXT = 5
+MAN6EXT = 6
+MAN7EXT = 7
+MAN8EXT = 8
+MAN9EXT = 9
+
+
+# HELP VARIABLES:
+
+# All path variables that includes the prefix,
+# or are unaffected by the prefix.
+_ALL_DIRS = BINDIR SBINDIR LIBDIR LIBEXECDIR INCLUDEDIR DATADIR SYSDEPDATA DOCDIR \
+ INFODIR DVIDIR PDFDIR PSDIR HTMLDIR MANDIR LOCALEDIR LICENSEDIR VARDIR \
+ VARTMPDIR COMDIR COMTMPDIR TMPDIR RUNDIR SYSCONFDIR DEVDIR SYSDIR \
+ PROCDIR SELFPROCDIR CACHEDIR SPOOLDIR EMPTYDIR LOGDIR STATEDIR GAMEDIR \
+ LOCKDIR SKELDIR COMCACHEDIR COMSPOOLDIR COMEMPTYDIR COMLOGDIR COMSTATEDIR \
+ COMGAMEDIR
+
+
+endif
+
diff --git a/mk/tags.mk b/mk/tags.mk
new file mode 100644
index 0000000..a7c695b
--- /dev/null
+++ b/mk/tags.mk
@@ -0,0 +1,25 @@
+# Copyright (C) 2015 Mattias Andrée <maandree@member.fsf.org>
+#
+# Copying and distribution of this file, with or without modification,
+# are permitted in any medium without royalty provided the copyright
+# notice and this notice are preserved. This file is offered as-is,
+# without any warranty.
+
+
+#=== These rules are used for generate etags- and ctags-tablse. ===#
+
+
+# Generate etags-table.
+.PHONY: TAGS
+TAGS:
+ @$(ECHO)
+ @$(ECHO) "TAGS is not implemented. Did not see the need. Feel free to implement if you want."
+ @$(ECHO)
+
+# Generate ctags-table
+.PHONY: tags
+tags:
+ @$(ECHO)
+ @$(ECHO) "tags is not implemented. Did not see the need. Feel free to implement if you want."
+ @$(ECHO)
+
diff --git a/mk/texinfo.mk b/mk/texinfo.mk
new file mode 100644
index 0000000..163b6e6
--- /dev/null
+++ b/mk/texinfo.mk
@@ -0,0 +1,256 @@
+# Copyright (C) 2015 Mattias Andrée <maandree@member.fsf.org>
+#
+# Copying and distribution of this file, with or without modification,
+# are permitted in any medium without royalty provided the copyright
+# notice and this notice are preserved. This file is offered as-is,
+# without any warranty.
+
+
+#=== These rules are used for Texinfo manuals. ===#
+
+
+# Enables the rules:
+# info Build info manual
+# dvi Build DVI manual
+# pdf Build PDF manual
+# ps Build PostScript manual
+# html Build HTML manual
+# install-info Install info manual
+# install-dvi Install DVI manual
+# install-pdf Install PDF manual
+# install-ps Install PostScript manual
+# install-html Install HTML manual
+#
+# This file is ignored unless
+# _HAVE_TEXINFO_MANUAL is defined.
+#
+# This file can only build output for
+# one Texinfo manual. This manual must
+# be named doc/info/$(_PROJECT).texinfo.
+# Additional sourced are set by specifing
+# how man directories deep doc/info nests
+# in the variable _TEXINFO_DIRLEVELS.
+#
+# If the info manual splits, specify the
+# split-number, of the file with the highest
+# split-number, in the variable _INFOPARTS.
+#
+# If the project has a logo, _LOGO should
+# name the suffixless basename of the SVG
+# files that contains the logo. This file
+# must be located in doc/.
+#
+# _HTML_FILES should the basename (with
+# suffix) of all files generated by `html`.
+
+
+ifdef _HAVE_TEXINFO_MANUAL
+
+
+# WHEN TO BUILD, INSTALL, AND UNINSTALL:
+
+all: info
+everything: info dvi pdf ps html
+doc: info dvi pdf ps html
+install: install-info
+install-everything: install-info install-dvi install-pdf install-ps install-html
+install-doc: install-info install-dvi install-pdf install-ps install-html
+uninstall: uninstall-info uninstall-dvi uninstall-pdf uninstall-ps uninstall-html
+
+
+# HELP VARIABLES:
+
+# Files from which the Texinfo manuals are built.
+__TEXI_SRC =
+ifdef _TEXINFO_DIRLEVELS
+ifeq ($(_TEXINFO_DIRLEVELS),1)
+__TEXI_SRC += doc/info/*.texinfo
+else
+ifeq ($(_TEXINFO_DIRLEVELS),2)
+__TEXI_SRC += doc/info/*.texinfo
+__TEXI_SRC += doc/info/*/*.texinfo
+else
+__TEXI_SRC += $(foreach W,$(shell $(SEQ) $(_TEXINFO_DIRLEVELS) | while read n; do $(ECHO) $$($(SEQ) $$n)" " | $(SED) 's/[^ ]* /\/\*/g'; done | $(XARGS) $(ECHO)),doc/info$(W).texinfo)
+endif
+endif
+endif
+
+# Split parts of the info manual.
+ifdef _INFOPARTS
+ifneq ($(_INFOPARTS),0)
+__INFOPARTS = $(shell $(SEQ))
+endif
+endif
+
+# Flags for TeX processed output.
+__TEXINFO_FLAGS = $(TEXINFO_FLAGS)
+ifdef _LOGO
+__TEXINFO_FLAGS += '--texinfo="@set LOGO $(_LOGO)"'
+endif
+
+
+# BUILD RULES:
+
+ifdef _LOGO
+# Prepare conversion of logo.
+obj/$(_LOGO).svg: doc/$(_LOGO).svg
+ @$(PRINTF_INFO) '\e[00;01;31mCP\e[34m %s\e[00m$A\n' "$@"
+ @$(MKDIR) -p obj
+ $(Q)$(CP) $< $@ #$Z
+ @$(ECHO_EMPTY)
+
+# Intermediate format for the logo for DVI and PostScript manuals.
+obj/$(_LOGO).ps: doc/$(_LOGO).svg
+ @$(PRINTF_INFO) '\e[00;01;31mPS\e[34m %s\e[00m$A\n' "$@"
+ @$(MKDIR) -p obj
+ $(Q)$(SVG2PS) $< > $@ #$Z
+ @$(ECHO_EMPTY)
+
+# Logo for DVI and PostScript manuals.
+obj/$(_LOGO).eps: obj/$(_LOGO).ps
+ @$(PRINTF_INFO) '\e[00;01;31mEPS\e[34m %s\e[00m$A\n' "$@"
+ $(Q)$(PS2EPS) $< #$Z
+ @$(ECHO_EMPTY)
+
+# Logo for PDF manual.
+obj/$(_LOGO).pdf: doc/$(_LOGO).svg
+ @$(PRINTF_INFO) '\e[00;01;31mPDF\e[34m %s\e[00m$A\n' "$@"
+ @$(MKDIR) -p obj
+ $(Q)$(SVG2PDF) $< > $@ #$Z
+ @$(ECHO_EMPTY)
+endif
+
+# Build info manual.
+.PHONY: info
+info: bin/$(_PROJECT).info
+bin/%.info $(foreach P,$(__INFOPARTS),bin/%.info-$(P)): doc/info/%.texinfo $(__TEXI_SRC)
+ @$(PRINTF_INFO) '\e[00;01;31mTEXI\e[34m %s\e[00m$A\n' "$@"
+ @$(MKDIR) -p bin
+ $(Q)$(MAKEINFO) $< #$Z
+ @$(PRINTF_INFO) '$A'
+ $(Q)$(MV) $*.info $@ #$Z
+ @$(ECHO_EMPTY)
+
+# Build DVI manual.
+.PHONY: dvi
+dvi: bin/$(_PROJECT).dvi
+bin/%.dvi: doc/info/%.texinfo $(__TEXI_SRC) $(foreach L,$(_LOGO),obj/$(L).eps)
+ @$(PRINTF_INFO) '\e[00;01;31mTEXI\e[34m %s\e[00m$A\n' "$@"
+ @! $(TEST) -d obj/dvi/$* || $(RM) -rf obj/dvi/$*
+ @$(MKDIR) -p obj/dvi/$* bin
+ $(Q)cd obj/dvi/$* && $(TEXI2DVI) ../../../$< $(__TEXINFO_FLAGS) < /dev/null #$Z
+ @$(PRINTF_INFO) '$A'
+ $(Q)$(MV) obj/dvi/$*/$*.dvi $@ #$Z
+ @$(ECHO_EMPTY)
+
+# Build PDF manual.
+.PHONY: pdf
+pdf: bin/$(_PROJECT).pdf
+bin/%.pdf: doc/info/%.texinfo $(__TEXI_SRC) $(foreach L,$(_LOGO),obj/$(L).pdf)
+ @$(PRINTF_INFO) '\e[00;01;31mTEXI\e[34m %s\e[00m$A\n' "$@"
+ @! $(TEST) -d obj/pdf/$* || $(RM) -rf obj/pdf/$*
+ @$(MKDIR) -p obj/pdf/$* bin
+ $(Q)cd obj/pdf/$* && $(TEXI2PDF) ../../../$< $(__TEXINFO_FLAGS) < /dev/null #$Z
+ @$(PRINTF_INFO) '$A'
+ $(Q)$(MV) obj/pdf/$*/$*.pdf $@ #$Z
+ @$(ECHO_EMPTY)
+
+# Build PostScript manual.
+.PHONY: ps
+ps: bin/$(_PROJECT).ps
+bin/%.ps: doc/info/%.texinfo $(__TEXI_SRC) $(foreach L,$(_LOGO),obj/$(L).eps)
+ @$(PRINTF_INFO) '\e[00;01;31mTEXI\e[34m %s\e[00m$A\n' "$@"
+ @! $(TEST) -d obj/ps/$* || $(RM) -rf obj/ps/$*
+ @$(MKDIR) -p obj/ps/$* bin
+ $(Q)cd obj/ps/$* && $(TEXI2PS) ../../../$< $(__TEXINFO_FLAGS) < /dev/null #$Z
+ @$(PRINTF_INFO) '$A'
+ $(Q)$(MV) obj/ps/$*/$*.ps $@ #$Z
+ @$(ECHO_EMPTY)
+
+# Build HTML manual.
+.PHONY: html
+html: bin/html/$(_PROJECT)/index.html
+bin/html/%/index.html: doc/info/%.texinfo $(__TEXI_SRC)
+ @$(PRINTF_INFO) '\e[00;01;31mTEXI\e[34m %s\e[00m$A\n' "$@"
+ @! $(TEST) -d bin/html/$* || $(RM) -rf bin/html/$*
+ @$(MKDIR) -p bin/html
+ $(Q)cd bin/html && $(MAKEINFO_HTML) ../../$< < /dev/null #$Z
+ @$(ECHO_EMPTY)
+
+
+# INSTALL RULES:
+
+# Install info manual.
+.PHONY: install-info
+install-info: bin/$(_PROJECT).info $(foreach P,$(__INFOPARTS),bin/%.info-$(P))
+ @$(PRINTF_INFO) '\e[00;01;31mINSTALL\e[34m %s\e[00m\n' "$@"
+ $(Q)$(INSTALL_DIR) -- "$(DESTDIR)$(INFODIR)"
+ $(Q)$(INSTALL_DATA) $< -- "$(DESTDIR)$(INFODIR)/$(PKGNAME).info"
+ $(Q)$(forearch P,$(__INFOPARTS),$(INSTALL_DATA) bin/$*.info-$(P) -- "$(DESTDIR)$(INFODIR)/$(PKGNAME).info-$(P)" &&) $(TRUE)
+ @$(ECHO_EMPTY)
+
+# Install DVI manual.
+.PHONY: install-dvi
+install-dvi: bin/$(_PROJECT).dvi
+ @$(PRINTF_INFO) '\e[00;01;31mINSTALL\e[34m %s\e[00m\n' "$@"
+ $(Q)$(INSTALL_DIR) -- "$(DESTDIR)$(DVIDIR)"
+ $(Q)$(INSTALL_DATA) $< -- "$(DESTDIR)$(DVIDIR)/$(PKGNAME).dvi"
+ @$(ECHO_EMPTY)
+
+# Install PDF manual.
+.PHONY: install-pdf
+install-pdf: bin/$(_PROJECT).pdf
+ @$(PRINTF_INFO) '\e[00;01;31mINSTALL\e[34m %s\e[00m\n' "$@"
+ $(Q)$(INSTALL_DIR) -- "$(DESTDIR)$(PDFDIR)"
+ $(Q)$(INSTALL_DATA) $< -- "$(DESTDIR)$(PDFDIR)/$(PKGNAME).pdf"
+ @$(ECHO_EMPTY)
+
+# Install PostScript manual.
+.PHONY: install-ps
+install-ps: bin/$(_PROJECT).ps
+ @$(PRINTF_INFO) '\e[00;01;31mINSTALL\e[34m %s\e[00m\n' "$@"
+ $(Q)$(INSTALL_DIR) -- "$(DESTDIR)$(PSDIR)"
+ $(Q)$(INSTALL_DATA) $< -- "$(DESTDIR)$(PSDIR)/$(PKGNAME).ps"
+ @$(ECHO_EMPTY)
+
+# Install HTML manual.
+.PHONY: install-html
+install-html: $(foreach F,$(_HTML_FILES),bin/html/$(_PROJECT)/$(F))
+ @$(PRINTF_INFO) '\e[00;01;31mINSTALL\e[34m %s\e[00m\n' "$@"
+ $(Q)$(INSTALL_DIR) -- "$(DESTDIR)$(HTMLDIR)/$(PKGNAME)/html"
+ $(Q)$(INSTALL_DATA) $^ -- "$(DESTDIR)$(HTMLDIR)/$(PKGNAME)/html/"
+ @$(ECHO_EMPTY)
+
+
+# UNINSTALL RULES:
+
+# Uninstall info manual.
+.PHONY: uninstall-info
+uninstall-info:
+ -$(Q)$(RM) -- "$(DESTDIR)$(INFODIR)/$(PKGNAME).info" $(forearch P,$(__INFOPARTS),"$(DESTDIR)$(INFODIR)/$(PKGNAME).info-$(P)")
+
+# Uninstall DVI manual.
+.PHONY: uninstall-dvi
+uninstall-dvi:
+ -$(Q)$(RM) -- "$(DESTDIR)$(DVIDIR)/$(PKGNAME).dvi"
+
+# Uninstall PDF manual.
+.PHONY: uninstall-pdf
+uninstall-pdf:
+ -$(Q)$(RM) -- "$(DESTDIR)$(PDFDIR)/$(PKGNAME).pdf"
+
+# Uninstall PostScript manual.
+.PHONY: uninstall-ps
+uninstall-ps:
+ -$(Q)$(RM) -- "$(DESTDIR)$(PSDIR)/$(PKGNAME).ps"
+
+# Uninstall HTML manual.
+.PHONY: uninstall-html
+uninstall-html:
+ -$(Q)$(RM) -- $(foreach F,$(_HTML_FILES),"$(DESTDIR)$(HTMLDIR)/$(PKGNAME)/html/$(F)")
+ -$(Q)$(RM) -- "$(DESTDIR)$(HTMLDIR)/$(PKGNAME)/html"
+ -$(Q)$(RM) -- "$(DESTDIR)$(HTMLDIR)/$(PKGNAME)"
+
+
+endif
+
diff --git a/mk/tools.mk b/mk/tools.mk
new file mode 100644
index 0000000..6793840
--- /dev/null
+++ b/mk/tools.mk
@@ -0,0 +1,97 @@
+# Copyright (C) 2015 Mattias Andrée <maandree@member.fsf.org>
+#
+# Copying and distribution of this file, with or without modification,
+# are permitted in any medium without royalty provided the copyright
+# notice and this notice are preserved. This file is offered as-is,
+# without any warranty.
+
+
+#=== This file defines variables for all used commands. ===#
+
+
+# Part of GNU Coreutils:
+MKDIR ?= mkdir
+CP ?= cp
+MV ?= mv
+RM ?= rm
+RMDIR ?= rmdir
+TRUE ?= true
+TEST ?= test
+TOUCH ?= touch
+ECHO ?= echo
+CUT ?= cut
+TAC ?= tac
+TAIL ?= tail
+HEAD ?= head
+SORT ?= sort
+UNIQ ?= uniq
+PRINTF ?= printf
+WC ?= wc
+INSTALL ?= install
+INSTALL_PROGRAM ?= $(INSTALL) -m755
+INSTALL_DATA ?= $(INSTALL) -m644
+INSTALL_DIR ?= $(INSTALL) -dm755
+
+# Part of GNU Findutils:
+FIND ?= find
+XARGS ?= xargs
+
+# Part of GNU Grep:
+GREP ?= grep
+
+# Part of GNU Sed:
+SED ?= sed
+
+# Part of GNU Privacy Guard:
+GPG ?= gpg
+
+# Part of Texinfo:
+MAKEINFO ?= makeinfo
+MAKEINFO_HTML ?= $(MAKEINFO) --html
+
+# Part of Texlive-plainextra:
+TEXI2PDF ?= texi2pdf
+TEXI2DVI ?= texi2dvi
+TEXI2PS ?= texi2pdf --ps
+
+# Part of Texlive-core:
+PS2EPS ?= ps2eps
+
+# Part of librsvg:
+RSVG_CONVERT ?= rsvg-convert
+SVG2PS ?= $(RSVG_CONVERT) --format=ps
+SVG2PDF ?= $(RSVG_CONVERT) --format=pdf
+
+# Part of GCC:
+CC ?= cc
+CPP ?= cpp
+
+# Part of GNU Gettext:
+XGETTEXT ?= xgettext
+MSGFMT ?= msgfmt
+MSGMERGE ?= msgmerge
+MSGINIT ?= msginit
+
+# Part of gzip:
+GZIP ?= gzip
+GZIP_COMPRESS ?= $(GZIP) -k9
+
+# Part of bzip2:
+BZIP2 ?= bzip2
+BZIP2_COMPRESS ?= $(BZIP2) -k9
+
+# Part of xz:
+XZ ?= xz
+XZ_COMPRESS ?= $(XZ) -ke9
+
+
+# Change to $(TRUE) to suppress the bold red and blue output.
+ifndef PRINTF_INFO
+PRINTF_INFO = $(PRINTF)
+endif
+
+# Change to $(TRUE) to suppress empty lines
+ifndef ECHO_EMPTY
+ECHO_EMPTY = $(ECHO)
+endif
+