diff options
author | Luke Shumaker <lukeshu@sbcglobal.net> | 2016-03-03 19:20:54 -0500 |
---|---|---|
committer | Luke Shumaker <lukeshu@sbcglobal.net> | 2016-03-03 19:20:54 -0500 |
commit | aeaebc66b1e579a394268460afc6c704915b3612 (patch) | |
tree | 2c2c51209fe426a32cc1830601f5477ef77a6e27 | |
parent | 225ca4b3f8efb7c95cf204bef3ddae3d432b3ec6 (diff) | |
parent | 45d77264cab813a4465116a3ac33a0a44a1389e7 (diff) |
Merge remote-tracking branch 'automake/master'
-rw-r--r-- | automake.head.mk | 3 | ||||
-rw-r--r-- | automake.tail.mk | 11 | ||||
-rw-r--r-- | automake.txt | 93 |
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. |