summaryrefslogtreecommitdiff
path: root/build-aux/Makefile.README.txt
diff options
context:
space:
mode:
Diffstat (limited to 'build-aux/Makefile.README.txt')
-rw-r--r--build-aux/Makefile.README.txt262
1 files changed, 105 insertions, 157 deletions
diff --git a/build-aux/Makefile.README.txt b/build-aux/Makefile.README.txt
index e06ba52..3be7a9d 100644
--- a/build-aux/Makefile.README.txt
+++ b/build-aux/Makefile.README.txt
@@ -1,160 +1,108 @@
-Luke's AutoMake
-===============
-
-Yo, this document is incomplete. It describes the magical
-automake.{head,tail}.mk Makefiles and how to use them, kinda.
-
-I wrote a "clone" of automake. I say clone, because it works
-differently. Yeah, I need a new name for it.
-
-High-level overview
--------------------
-
-Now, what this does for you is:
-
-It makes it _easy_ to write non-recursive Makefiles--and ones that are
-similar to plain recursive Makefiles, at that! (search for the paper
-"Recursive Make Considered Harmful") As harmful as recursive make is,
-it's historically been difficult to to write non-recursive Makefiles.
-This makes it easy.
-
-It also makes it easy to follow the GNU standards for your makefiles:
-it takes care of this entire table of .PHONY targets for you:
-
-| this | and this | are aliases for this |
-|------+------------------+--------------------------------------------------------|
-| all | build | $(outdir)/build |
-| | install | $(outdir)/install |
-| | uninstall | $(outdir)/uninstall |
-| | mostlyclean | $(outdir)/mostlyclean |
-| | clean | $(outdir)/clean |
-| | distclean | $(outdir)/distclean |
-| | maintainer-clean | $(outdir)/maintainer-clean |
-| | check | $(outdir)/check (not implemented for you) |
-| | dist | $(topoutdir)/$(PACKAGE)-$(VERSION).tar.gz (not .PHONY) |
-
-(You are still responsible for implementing the `$(outdir)/check`
-target in each of your Makefiles.)
-
-What you have to do is:
-
-In each source directory, you write a `Makefile`, very similarly to if
-you were writing for plain GNU Make, with
-
- topoutdir ?= ...
- topsrcdir ?= ...
- include $(topsrcdir)/build-aux/Makefile.head.mk
-
- # your makefile
-
- include $(topsrcdir)/build-aux/Makefile.tail.mk
-
-And in the top-level source directory, Write your own helper makefiles
-that get included:
- - `common.once.head.mk`: before parsing any of your Makefiles
- - `common.each.head.mk`: before parsing each of your Makefiles
- - `common.each.tail.mk`: after parsing each of your Makefiles
- - `common.each.tail.mk`: after parsing all of your Makefiles
-
-The `common.*.mk` makefiles are nice for including generic pattern
-rules and variables that aren't specific to a directory.
-
-You're probably thinking that this sounds too good to be true!
-Unfortunately, there are two major deviations from writing a plain
-recursive Makefile:
-
- 1. all targets and prerequisites (including .PHONY targets!) need to
- be prefixed with
- `$(srcdir)`/`$(outdir)`/`$(topsrcdir)`/`$(topoutdir)`.
- * sub-gotcha: this means that if a pattern rule has a
- prerequisite that may be in srcdir or outdir, then it must be
- specified twice, once for each case.
- 2. if a prerequisite is in a directory "owned" by another Makefile,
- you must filter the pathname through `am_path`:
- `$(call am_path,YOUR_PATH)`. Further, that path must NOT contain
- a `..` segment; if you need to refer to a sibling directory, do it
- relative to `$(topoutdir)` or `$(topsrcdir)`.
-
-Telling automake about your program
------------------------------------
-
-You tell automake what to do for you by setting some variables. They
-are all prefixed with `am_`; this prefix may be changed by editing the
-`_am` variable at the top of `automake.head.mk`.
-
-The exception to this is the `am_path` variable, which is a macro that
-is used to make a list of filenames relative to the appropriate
-directory, because unlike normal GNU (Auto)Make, `$(outdir)` isn't
-nescessarily equal to `.`. See above.
-
-There are several commands that generate files; simply record the list
-of files that each command generates as the following variable
-variables:
-
-| Variable | Create Command | Delete Command | Description | Relative to |
-|--------------+----------------+-----------------------------+-----------------------------------+-------------|
-| am_src_files | emacs | rm -rf . | Files that the developer writes | srcdir |
-| am_gen_files | ??? | make maintainer-clean | Files the developer compiles | srcdir |
-| am_cfg_files | ./configure | make distclean | Users' compile-time configuration | outdir |
-| am_out_files | make all | make mostlyclean/make clean | Files the user compiles | outdir |
-| am_sys_files | make install | make uninstall | Files the user installs | DESTDIR |
-
-In addition, there are two more variables that control not how files
-are created, but how they are deleted:
-
-| Variable | Affected command | Description | Relative to |
-|----------------+------------------+------------------------------------------------+-------------|
-| am_clean_files | make clean | A list of things to `rm` in addition to the | outdir |
-| | | files in `$(am_out_files)`. (Example: `*.o`) | |
-|----------------+------------------+------------------------------------------------+-------------|
-| am_slow_files | make mostlyclean | A list of things that (as an exception) should | outdir |
-| | | _not_ be deleted. (otherwise, `mostlyclean` | |
-| | | is the same as `clean`) | |
-
-Finally, there are two variables that express the relationships
-between directories:
-
-| Variable | Description |
-|------------+---------------------------------------------------------|
-| am_subdirs | A list of other directories (containing Makefiles) that |
-| | may be considered "children" of this |
-| | directory/Makefile; building a phony target in this |
-| | directory should also build it in the subdirectory. |
-| | They are not necesarily actually subdirectories of this |
-| | directory in the filesystem. |
-|------------+---------------------------------------------------------|
-| am_depdirs | A list of other directories (containing Makefiles) that |
-| | contain or generate files that are dependencies of |
-| | targets in this directory. They are not necesarily |
-| | actually subdirectories of this directory in the |
-| | filesystem. Except for files that are dependencies of |
-| | files in this directory, things in the dependency |
-| | directory will not be built. |
-
-Tips, notes
------------
-
-I like to have the first (non-comment) line in a Makefile be:
-
- include $(dir $(lastword $(MAKEFILE_LIST)))/../../config.mk
-
-(adjusting the number of `../` sequences as nescessary). Then, my
-(user-editable) `config.mk` is of the form:
-
- ifeq ($(topsrcdir),)
- topoutdir := $(patsubst %/,%,$(dir $(lastword $(MAKEFILE_LIST))))
- topsrcdir := $(topoutdir)
-
- # your configuration
-
- endif
-
-If the package has a `./configure` script, then I have it modifiy
-topsrcdir as necessary, as well as modifying whatever other parts of
-the configuration. All of the configuration lives in `config.mk`;
-`./configure` doesn't modify any `Makefile`s, it just generates
-`config.mk`, and copies (or (sym?)link?) every `$(srcdir)/Makefile` to
-`$(outdir)/Makefile`.
+# -*- 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"
+ <http://aegis.sourceforge.net/auug97.pdf>
----
Copyright (C) 2016 Luke Shumaker