X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ian/git?a=blobdiff_plain;f=subdirmk%2FREADME;h=fcf8c000f89a6ea61f92deca0a1aabaa420fce96;hb=24eb6b672f1095d5b362b6615f22c17f1136274a;hp=95cdd69024b8ea194ab2d32d10d31c5857bf3a85;hpb=1c1948504ec808f30a0fd631d6cbc11ebd7ab371;p=secnet.git diff --git a/subdirmk/README b/subdirmk/README index 95cdd69..fcf8c00 100644 --- a/subdirmk/README +++ b/subdirmk/README @@ -5,7 +5,7 @@ Introduction ------------ Peter Miller's 1997 essay _Recursive Make Considered Harmful_ -persuasively argues that it is better to arrannge to have a single +persuasively argues that it is better to arrange to have a single make invocation with the project's complete dependency tree, rather than the currently conventional `$(MAKE) -C subdirectory' approach. @@ -14,7 +14,7 @@ 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 + - 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) @@ -28,23 +28,25 @@ Basic approach The developer is expected to write a makefile fragment, in each relevant subdirectory, called `Subdir.sd.mk'. -These fragments may contain ordinary make language. +These fragments may contain ordinary make language. Unqualified +filenames are relative to the build toplevel, and all commands all run +there. However, the sigil & is treated specially. By and large, it refers to -`the current directory'. There are a variety of convenient -constructions. +`the build directory corresponding to this .sd.mk file', etc. +There are a variety of convenient constructions. The result is that to a large extent, the Subdir.sd.mk has an easy way to namespace its "local" make variables, and an easy way to refer to -its "local" filenames. +its "local" filenames (and filenames in general). The Subdir.sd.mk'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. +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 @@ -67,7 +69,7 @@ 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. &TARGETS is magic in this way. (In -src/Subdir.sd.mk, &TARGES of course refers to a make variable called +src/Subdir.sd.mk, &TARGETS of course refers to a make variable called src_TARGETS.) The `all' target in a parent directory is taken to imply the `all' @@ -77,12 +79,13 @@ 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. +targets may be in run in parallel: there is only one `make' invocation +at a time. There is no sequencing between subdirectories, only been +individual targets (as specified according to their dependencies). You can define other per-directory recursive targets too: simply mention (usually, by setting) the variable &TARGETS_zonk, or whatever. -This will create a src/zonk target. +This will create a src/zonk target (for appropriate value of src/). Unlike `all', these other targets only exist in areas of the project where at least something mentions them. So for example, if &TARGETS_zonk is mentioned in src but not lib, `make zonk' in @@ -92,7 +95,7 @@ mention its name in Perdir.sd.mk (see below). Perdir.sd.mk, inclusion ----------------------- -The file Perdir.sd.mk in the toplevel of fthe source is automatically +The file Perdir.sd.mk in the toplevel of the source is automatically processed after each individual directory's Subdir.sd.mk, and the &-substituted contents therefore appear once for each subdirectory. @@ -102,6 +105,19 @@ is already provided in subdirmk, for you to reference like this: &:include subdirmk/clean.sd.mk For example you could put that in Perdir.sd.mk. +The top-level Subdir.sd.mk is the first makefile included after the +autogenerated `main.mk' which merely has some basic settings and +includes. So if you want to get in early and set global variables, +put them near the top of Subdir.sd.mk. + +subdirmk's filter script itself sets (only) these variables: + top_srcdir + abs_top_srcdir + SUBDIRMK_MAKEFILES + MAKEFILE_TEMPLATES +You are likely to want to define $(PWD), and shorter names for +top_srdir and abs_top_srcdir (we suggest $(src) and $(abs_src)). + Global definitions ------------------ @@ -109,6 +125,10 @@ If want to set global variables, such as CC, that should only be done once. You can put them in your top-level Subdir.sd.mk, or a separate file you `include' and declare using SUBDIRMK_MAKEFILES. +If you need different settings of variables like CC for different +subdirectories, you should probably do that with target-specific +variable settings. See the info node `(make) Target-specific'. + Subdirectory templates `.sd.mk' vs plain autoconf templates `.mk.in' -------------------------------------------------------------------- @@ -133,6 +153,47 @@ If you `include subdirmk/regen.mk', dependency management and automatic regeneration for all of this template substitution, and for config.status etc. is done for you. +Tables of file reference syntaxes +--------------------------------- + +In a nonrecursive makefile supporting out of tree builds there are +three separate important distinctions between different file +locations: + + (i) In the build tree, or in the source tree ? + + (ii) In (or relative to) the subdirectory to which this Subdir.sd.mk + relates, or relative to the project's top level ? + + (iii) Absolute or relative pathname ? Usually relative pathnames + suffice. Where an absolute pathname is needed, it can be built + out of &/ and an appropriate make variable such as $(PWD). + +Path construction &-expansions are built from the following: + + Relative paths in... + build source + + This directory & &^ + Top level . &~ + +In more detail, with all the various options laid out: + + Recommended Relative paths in... Absolute paths in... + for build source build source + + This lc &file &^file $(PWD)/&file $(abs_src)/&file + directory any &/file &^/file $(PWD)/&file $(abs_src)/&/file + several & f g h &^ f g h $(addprefix...) + + Top lc file &~file + level any file &~/file $(PWD)/file $(abs_src)/file + .mk.in file $(src)/file $(PWD)/file $(abs_src)/file + several f g h &~ f g h $(addprefix...) + +(This assumes you have appropriate make variables src, PWD and +abs_src.) + Substitution syntax ------------------- @@ -151,30 +212,45 @@ we describe the expansion at the top level, which is often a special case (in general in variable names we call that TOP rather than the empty string). -&CAPS => sub_dir_CAPS or TOP_CAPS -&lc => sub/dir/lc or lc +&CAPS => sub_dir_CAPS or TOP_CAPS +&lc => sub/dir/lc or lc Here CAPS is any ASCII letter A-Z and lc is a-z. The assumption is that filenames are usually lowercase and variables usually uppercase. Otherwise, use another syntax: &_ => sub_dir_ or TOP_ -&/ => sub/dir/ or nothing &=_ => sub_dir or TOP + +&/ => sub/dir/ or nothing &=/ => sub/dir or . -&^ => $(top_srcdir)/sub/dir or $(top_srcdir) -&~ => $(abs_top_srcdir)/sub/dir or $(abs_top_srcdir) + +&^lc => $(top_srcdir)/sub/dir/lc +&^/ => $(top_srcdir)/sub/dir/ + +&~lc => $(top_srcdir)/lc +&~/ => $(top_srcdir)/ + +In general: + = return subdir without delimiter (not allowed with `^' `~') + ^ pathname of this subdirectory in source tree + ~ pathname of top level of source tree + / terminates the escape (needed if next is not lwsp or space) + lwsp starts multi-word processing (see below) + +So pathname syntax is a subset of: + '&' [ '^' | '~' ] [ lc | '/' ] && => && for convenience in shell runes \& => & general escaping mechanism & thing thing... & -& ^ thing thing... & -& ~ thing thing... & +&^ thing thing... & +&~ thing thing... & Convenience syntax for prefixing multiple filenames. - Introduced by & followed by lwsp (space or tab). - Each lwsp-separated non-ws word is prefixed by &/ &^/ &~/ - respectively. No other & escapes are recognised. - This processing continues until a & preceded by lwsp, + Introduced by & followed by lwsp where lc could go. + Each lwsp-separated non-ws word is prefixed by &/ etc. + etc. respectively. No other & escapes are recognised. + This processing continues until & preceded by lwsp, or until EOL (the end of the line), or \ then EOL. &: .... @@ -183,9 +259,13 @@ empty string). &:include filename filename should usually be foo.sd.mk &:-include filename tolerate nonexistent file + filenames are relative to $(top_srcdir) &! disables & until EOL (and then disappears) +&# delete everything to end of line + (useful if the RHS contains unrecognised & constructions) + &!STUFF changes the escape sequence from & to literally STUFF STUFF may be any series of of non-whitespace characters, @@ -266,6 +346,38 @@ have: &:include subdirmk/cdeps.sd.mk &:include subdirmk/clean.sd.mk +Hints +----- + +You can convert your project incrementally. Start with the top-level +Makefile.in and rename it to Subdir.sd.mk, and add the appropriate +stuff to configure.ac, and fix everything up. Leave the existing +$(MAKE) -C for your existing subdirectories alone. Then you can +convert individual subdirectories, or classes of subdirectories, at +your leisure. (You must be /sure/ that each subdirectory will be +entered only once at a time, but your existing recursive make descent +system should already do that or you already have concurrency bugs.) + +Aside from this, be very wary of any invocation of $(MAKE) anywhere. +This is a frequent source of concurrency bugs in recursive make build +systems. When combined with nonrecursive make it's all in the same +directory and there is nothing stopping the different invocations +ending up trying to make the same targets at the same time. That +causes hideous racy lossage. There are ways to get this to work +reliably but it is advanced stuff. + +If you make syntax errors, or certain kinds of other errors, in your +makefiles, you may find that just `make' is broken now and cannot get +far enough to regenerate a working set of makefiles. If this happens +just rerun ./config.status by hand. + +If you go back and forth between different versions of your code you +can sometimes find that `make' complains that one of your Subdir.sd.mk +files is missing: typically, if iot was used and therefore a +dependency in some other version of your code. If you run `make +clean' (or `make realclean') these dependencies are suppressed, which +will clear up the problem. + Legal information -----------------