X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ian/git?p=subdirmk.git;a=blobdiff_plain;f=subdirmk%2FREADME;h=16a33e373d937567550c611ae4184cb662b90710;hp=7cf84cf756597db3b2073c4c158172456fca59ed;hb=37ddf3c292b5dbf0ea56af4185d5a6faefac738d;hpb=3d62132e874bd2ceee3fb5960a172beb4594d6c9 diff --git a/subdirmk/README b/subdirmk/README index 7cf84cf..16a33e3 100644 --- a/subdirmk/README +++ b/subdirmk/README @@ -1,3 +1,95 @@ +subdirmk - assistance for non-recursive use of make +=================================================== + +Introduction +------------ + +Peter Miller's 1997 essay _Recursive Make Considered Harmful_ +persuasively argues that it is better to arrannge to have a single +make invocation with the project's complete dependency tree, rather +than the currently conventional `$(MAKE) -C subdirectory' approach. + +However, actually writing a project's build system in a non-recursive +style is not very ergonomic. The main difficulties are: + - constantly having to write out long file and directory names + - the lack of a per-directory make variable namespace means + long make variables (or namespace clashes) + - it is difficult to arrange that one can cd to a subdirectory + and say `make all' and have something reasonable happen + (to wit, build an appropriate subset) + +`subdirmk' is an attempt to solve these problems (and it also slightly +alleviates some of the boilerplate needed to support out-of-tree +builds well). + +Basic approach +-------------- + +The developer is expected to write a makefile fragment in each +relevant subdirectory called `Subdir.mk.in'. + +These fragments may contain ordinary make language. + +However, the sigil & is treated specially. By and large, it refers to +`the current directory'. There are a variety of convenient +constructions. + +The result is that to a large extent, the Subdir.mk.in has an easy way +to namespace its "local" make variables, and an easy way to refer to +its "local" filenames. + +The Subdir.mk.in's are filtered, fed through autoconf in the usual way +(for @..@-substitutions) and included by one autogenerated toplevel +makefile. + +So all of the input is combined and passed to one make invocation. (A +corollary is that there is no enforcement of the namespacing: +discipline is required to prefix relevant variable names with &, etc. + +Each subdirectory is also provided with an autogenerated `Makefile' +which exists purely to capture ordinary make invocations and arrange +for something suitable to happen. + +Where there are dependencies between subdirectories, each Subdir.mk.in +can simply refer to files in other subdirectories directly. + +Per-directory targets, "recursion" +---------------------------------- + +Each subdirectory has its own `all' target. For example a +subdirectory `src' has a target `src/all'. The rules for these are +automatically generated from the settings of the per-directory +&TARGETS variables. (In src/Subdir.mk.in, this of course refers to a +make variable called src_TARGETS.) + +The `all' target in a parent directory is taken to imply the `all' +targets in all of its subdirectories, recursively. And in the +autogenerated stub Makefiles, `all' is the default target. So if you +just type `make' in the toplevel, you are asking for `&all' +(/all) for every directory in the project. + +In a parallel build, the rules for all these various subdirectory +targets may be in run in parallel: there is only one `make' +invocation at a time. + +There may also be other + + + + + + + (None of this prevents + + + + + + https://web.archive.org/web/20150330111905/http://miller.emu.id.au/pmiller/books/rmch/ + + + + &CAPS => subdir_CAPS or TOP_CAPS &lc => subdir/lc or lc @@ -16,6 +108,12 @@ & ~ thing thing... & & may be omitted before EOL or before \EOL other &'s not recognised +start of line (maybe after ws): +&: .... +args are processed for & first +&:include filename filename should usually be foo.mk.in +&:-include filename + CAPS is [A-Z][0-9_A-Z]*(?!\w) lc is [a-z][-+,0-9_a-z]*(?!\w)