summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--automake.head.mk3
-rw-r--r--automake.tail.mk11
-rw-r--r--automake.txt93
3 files changed, 80 insertions, 27 deletions
diff --git a/automake.head.mk b/automake.head.mk
index ad7154c..c79da83 100644
--- a/automake.head.mk
+++ b/automake.head.mk
@@ -17,13 +17,14 @@ _am = am_
_am_noslash = $(patsubst %/.,%,$(patsubst %/,%,$1))
# These are all $(call _am_func,parent,child)
-#_am_relto = $(if $2,$(shell realpath -s --relative-to='$1' $2))
+#_am_relto = $(if $2,$(shell realpath -sm --relative-to='$1' $2))
_am_is_subdir = $(filter $(abspath $1)/%,$(abspath $2)/.)
_am_relto_helper = $(if $(call _am_is_subdir,$1,$2),$(patsubst $1/%,%,$(addsuffix /.,$2)),$(addprefix ../,$(call _am_relto_helper,$(patsubst %/,%,$(dir $1)),$2)))
_am_relto = $(call _am_noslash,$(call _am_relto_helper,$(call _am_noslash,$(abspath $1)),$(call _am_noslash,$(abspath $2))))
# Note that _am_is_subdir says that a directory is a subdirectory of
# itself.
_am_path = $(call _am_relto,.,$1)
+am_path = $(foreach p,$1,$(call _am_relto,$p))
## Declare the default target
all: build
diff --git a/automake.tail.mk b/automake.tail.mk
index 5d6ad00..a24820b 100644
--- a/automake.tail.mk
+++ b/automake.tail.mk
@@ -19,8 +19,7 @@ include $(topsrcdir)/common.each.tail.mk
# Aggregate variables
# Add some more defaults to the *_files variables
-$(_am)clean_files += $($(_am)gen_files) $($(_am)out_files)
-$(_am)cfg_files += Makefile
+$(_am)clean_files += $($(_am)gen_files) $($(_am)cfg_files) $($(_am)out_files)
# Now namespace the *_files variables
define _am_save_variables
@@ -103,10 +102,10 @@ $(outdir)/build : $(_am_out_files/%(outdir))
$(outdir)/install: $(_am_sys_files/%(outdir))
# Destructive phony targets
_am_uninstall/%(outdir) = $(_am_sys_files/%(outdir))
-_am_mostlyclean/%(outdir) = $(filter-out $(_am_slow_files/%(outdir)) $(_am_cfg_files/%(outdir)) $(_am_gen_files/%(outdir)),$(_am_clean_files/%(outdir)))
-_am_clean/%(outdir) = $(filter-out $(_am_cfg_files/%(outdir)) $(_am_gen_files/%(outdir)),$(_am_clean_files/%(outdir)))
-_am_distclean/%(outdir) = $(filter-out $(_am_gen_files/%(outdir)),$(_am_clean_files/%(outdir)))
-_am_maintainer-clean/%(outdir) = $(_am_clean_files/%(outdir))
+_am_mostlyclean/%(outdir) = $(filter-out $(_am_slow_files/%(outdir)) $(_am_cfg_files/%(outdir)) $(_am_gen_files/%(outdir)) $(_am_src_files/%(outdir)),$(_am_clean_files/%(outdir)))
+_am_clean/%(outdir) = $(filter-out $(_am_cfg_files/%(outdir)) $(_am_gen_files/%(outdir)) $(_am_src_files/%(outdir)),$(_am_clean_files/%(outdir)))
+_am_distclean/%(outdir) = $(filter-out $(_am_gen_files/%(outdir)) $(_am_src_files/%(outdir)),$(_am_clean_files/%(outdir)))
+_am_maintainer-clean/%(outdir) = $(filter-out $(_am_src_files/%(outdir)),$(_am_clean_files/%(outdir)))
endef
$(foreach outdir,$(_am_outdirs),$(eval $(subst %(outdir),$(outdir),$(value _am_directory_rules))))
diff --git a/automake.txt b/automake.txt
index 22a0b84..c9834d3 100644
--- a/automake.txt
+++ b/automake.txt
@@ -10,6 +10,34 @@ 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
@@ -21,30 +49,42 @@ you were writing for plain GNU Make, with
include $(topsrcdir)/automake.tail.mk
-Write your own `common.{each,once}.{head,tail}.mk` files that get
-included:
+And in the top-level output directory, you write a `config.mk` with:
+
+ ifeq ($(topsrcdir),)
+ # have your ./configure script adjust topsrcdir if doing an
+ # out-of-tree build
+ topsrcdir := $(patsubst %/,%,$(dir $(lastword $(MAKEFILE_LIST))))
+
+ # your configuration
+
+ endif
+
+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
-Here is a table of all of the .PHONY targets that automake takes care
-of 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 responsible for implementing the `$(outdir)/check` target in
-each 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
-----------------------------------
@@ -53,6 +93,11 @@ 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:
@@ -97,9 +142,17 @@ between directories:
| | files in this directory, things in the dependency |
| | directory will not be built. |
+Tips, notes
+-----------
+
+If you have a `./configure` script, don't have it modify the
+`Makefile`s; have everything you need modified be in
+`$(topoutdir)/config.mk` and have it generate that; then have it copy
+(or (sym?)link?) every `$(srcdir)/Makefile` into `$(outdir)/Makefile`.
+
----
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 do so.
+absolutely every way that I can legally grant to you.