# -*- Mode: markdown -*- Autothing 3: The smart way to write GNU Makefiles ================================================= Autothing is a thing that does things automatically. Ok, more helpfully: Autothing is a pair of .mk Makefile fragments that you can `include` from your Makefiles to make them easier to write; specifically, it makes it _easy_ to write non-recursive Makefiles--and ones that are similar to plain recursive Makefiles, at that! Synopsis -------- Write your makefiles of the form: topsrcdir ?= ... topoutdir ?= ... at.Makefile ?= Makefile # Optional include $(topsrcdir)/build-aux/Makefile.head.mk $(outdir)/%.o: $(srcdir)/%.c: $(CC) -c -o $@ $< $(outdir)/hello: $(outdir)/hello.o at.subdirs = ... at.targets = ... include $(topsrcdir)/build-aux/Makefile.tail.mk This is similar to, but not quite, the comfortable way that you probably already write your Makefiles. Details ------- There are two fundamental things that Autothing provides: 1. Variable namespacing 2. Tools for dealing with paths The first is important because globals are bad for composability. The second is important because GNU Make is too dumb to know that `foo/bar/../baz` == `foo/baz`. Then, there's something that maybe doesn't belong, but I didn't have the heart to cut it out: 3. A module (plugin) system. The module system is "important" because there are very often common bits that you want to be included in every Makefile, and this gives some structure to that. Requirements: - A version of GNU Make that supports `undefine`. (TODO: check which version of GNU Make introduced this feature) Inputs: - In each `Makefile`: - Before `Makefile.head.mk`: - Variable (mandatory) : `topoutdir` - Variable (mandatory) : `topsrcdir` (must not be a subdirectory of `$(topoutdir)`) - Variable (optional) : `at.Makefile` (Default: `Makefile`) - Between `Makefile.head.mk` and `Makefile.tail.mk`: - Variable: `at.targets` (Default: empty) - Variable: `at.subdirs` (Default: empty) - Files: - `${topsrcdir}/build-aux/Makefile.{each,once}.{head,tail}/*.mk` Outputs: - Global: - Variable (function): `$(call at.is_subdir, parent, child)` - Variable (function): `$(call at.is_strict_subdir, parent, child)` - Variable (function): `$(call at.relbase, parent, children...)` - Variable (function): `$(call at.relto, parent, children...)` - Variable (function): `$(call at.path, paths...)` - Variable (function): `$(call at.out2src, paths...)` - Variable (function): `$(call at.addprefix, prefix, paths...)` - Per-directory: - Variable: `$(outdir)` - Variable: `$(srcdir)` TODO: actually explain things. Motivation/Exposition --------------------- This section needs rewritten. Or really just written. Other projects like GNU Automake were created to plaster over differences between make(1) implementations; however, this isn't all that Automake provides, it also makes it easy to do complex things that users want, or the GNU Coding Standards require. That's silly. Autothing does depend on GNU Make; other make(1) implementations will not work. However, if you are open to adding GNU Make as a dependency, then Autothing should obviate the need for GNU Automake, while also making your Makefiles better. Peter Miller (1997) "Recursive Make Considered Harmful" ---- Copyright (C) 2016 Luke Shumaker This documentation file is placed into the public domain. If that is not possible in your legal system, I grant you permission to use it in absolutely every way that I can legally grant to you.