From: Ian Jackson Date: Wed, 13 Nov 2019 23:24:27 +0000 (+0000) Subject: Add 'subdirmk/' from commit 'f1789a0ae66174a95c8d629738eae98d40c084ac' X-Git-Tag: v0.5.1~44 X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ian/git?p=secnet.git;a=commitdiff_plain;h=e84c081039387230c524f9f34903afacaab4219b Add 'subdirmk/' from commit 'f1789a0ae66174a95c8d629738eae98d40c084ac' git-subtree-dir: subdirmk git-subtree-mainline: d212a384b4ef631a876e1ddd3e52fd09e4b1f484 git-subtree-split: f1789a0ae66174a95c8d629738eae98d40c084ac --- e84c081039387230c524f9f34903afacaab4219b diff --cc subdirmk/.gitignore index 0000000,0000000..a5b02c2 new file mode 100644 --- /dev/null +++ b/subdirmk/.gitignore @@@ -1,0 -1,0 +1,8 @@@ ++# subdirmk - subdirmk/.gitignore ++# Copyright 2019 Mark Wooding ++# Copyright 2019 Ian Jackson ++# SPDX-License-Identifier: LGPL-2.0-or-later ++ ++#----- subdirmk-generated ----- ++/regen.mk ++/usual.mk diff --cc subdirmk/DEVELOPER-CERTIFICATE index 0000000,912d22e..912d22e mode 000000,100644..100644 --- a/subdirmk/DEVELOPER-CERTIFICATE +++ b/subdirmk/DEVELOPER-CERTIFICATE diff --cc subdirmk/LGPL-2 index 0000000,5bc8fb2..5bc8fb2 mode 000000,100644..100644 --- a/subdirmk/LGPL-2 +++ b/subdirmk/LGPL-2 diff --cc subdirmk/README index 0000000,0000000..e5ef4b4 new file mode 100644 --- /dev/null +++ b/subdirmk/README @@@ -1,0 -1,0 +1,313 @@@ ++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 arrange 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.sd.mk'. ++ ++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.sd.mk has an easy way ++to namespace its "local" make variables, and an easy way to refer to ++its "local" filenames. ++ ++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.) ++ ++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.sd.mk ++can simply refer to files in other subdirectories directly. ++ ++Invocation, "recursive" per-directory targets ++--------------------------------------------- ++ ++Arrangements are made so that when you run `make foo' in a ++subdirectory, it is like running the whole toplevel makefile, from the ++toplevel, as `make subdir/foo'. If `subdir/foo' is a file that might ++be built, that builds it. ++ ++But `foo' can also be a conventional target like `all'. ++ ++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, &TARGETS 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 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 (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 ++lib will fail. If you want to make a target exist everywhere, ++mention its name in Perdir.sd.mk (see below). ++ ++Perdir.sd.mk, inclusion ++----------------------- ++ ++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. ++ ++This lets you do per-directory boilerplate. Some useful boilerplate ++is already provided in subdirmk, for you to reference like this: ++ &:include subdirmk/cdeps.sd.mk ++ &:include subdirmk/clean.sd.mk ++For example you could put that in Perdir.sd.mk. ++ ++Global definitions ++------------------ ++ ++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' ++-------------------------------------------------------------------- ++ ++There are two kinds of template files. ++ ++ Filename .sd.mk .mk.in ++ ++ Processed by &-substitution, autoconf only ++ then autoconf ++ ++ Instantiated Usu. once per subdir Once only ++ ++ Need to be mentioned No, but Subdir.sd.mk All not in subdirmk/ ++ in configure.ac? via SUBDIRMK_SUBDIRS via SUBDIRMK_MAKEFILES ++ ++ How to include `&:include foo.sd.mk' `include foo.mk' ++ in all relevant .sd.mk in only one ++ (but not needed for Subdir.sd.mk ++ Subdir and Perdir) ++ ++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. ++ ++Substitution syntax ++------------------- ++ ++In general & expands to the subdirectory name when used for a ++filename, and to the subdirectory name with / replaced with _ for ++variable names. ++ ++Note that & is processed *even in makefile comments*. The substitutor ++does not understand make syntax, or shell syntax, at all. However, ++the substitution rules are chosen to work well with constructs which ++are common in makefiles. ++ ++In the notation below, we suppose that the substitution is being in ++done in a subdirectory sub/dir of the source tree. In the RH column ++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 ++ 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 . ++&^ => $(top_srcdir)/sub/dir or $(top_srcdir) ++&~ => $(abs_top_srcdir)/sub/dir or $(abs_top_srcdir) ++ ++&& => && for convenience in shell runes ++\& => & general escaping mechanism ++ ++& 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 & preceded by lwsp, ++ or until EOL (the end of the line), or \ then EOL. ++ ++&: .... ++ recognised at start of line only (possibly after lwsp) ++ args are processed for & ++ ++&: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, ++ and is terminated by EOL or lwsp. &!STUFF and the lwsp ++ are discarded. ++ ++ After this, write STUFF instead of &, everywhere. ++ The effect is global and lasts until the next setting. ++ It takes effect on &:include'd files too, so maybe set ++ it back before using &:include. ++ ++ Notably ++ STUFFSTUFF => STUFFSTUFF ++ \STUFF => STUFF ++ STUFF!& set escape back to & ++ ++&TARGETS_things ++ Handled specially. If mentioned, declares that this ++ subdir ought to have a target `things'. The rule will be ++ &/things:: $(&TARGETS_things) ++ ++ You may extend it by adding more :: rules for the target, ++ but the preferred style is to do things like this: ++ &TARGETS_check += & test-passed.stamp ++ ++ It is important to mention &TARGETS_things at least once in ++ the context of each applicable directory, because doing so ++ arranges that the *parent* will also have a `things' target ++ which recursively implies this directory's `things'. ++ ++ Must be spelled exactly &TARGETS_things. &_TARGETS_things, ++ for example, is not magic. But mentioning &TARGETS_things in ++ a #-comment *does* work because the & filter does not care ++ about comments. ++ ++ `all' is extra special: every directory has an `all' ++ target, which corresponds to &TARGETS. ++ ++Subdirectory and variable naming ++-------------------------------- ++ ++The simple variable decoration scheme does not enforce a strict ++namespace distinction between parts of variable names which come from ++subdirectory names, and parts that mean something else. ++ ++So it is a good idea to be a bit careful with your directory naming. ++`TOP', names that contain `_', and names that are similar to parts of ++make variables (whether conventional ones, or ones used in your ++project) are best avoided. ++ ++If you name your variables in ALL CAPS and your subdirectories in ++lower case with `-' rather than `_', there will be no confusion. ++ ++Incorporating this into your project ++------------------------------------ ++ ++Use `git-subtree' to merge the subdirmk/ directory. You may find it ++useful to symlink the DEVELOPER-CERTIFICATE file (git can store ++symlinks as symlinks - just `git add' the link). And you probably ++want to mention the situation in your top-level COPYING. ++ ++Symlink autogen.sh into your project toplevel. ++ ++In your configure.ac, say ++ ++ m4_include([subdirmk/subdirmk.ac]) ++ SUBDIRMK_SUBDIRS([...list of subdirectories in relative syntax...]) ++ ++Write a Subdir.sd.mk in each directory. The toplevel one should ++probably contain: ++ ++ include subdirmk/usual.mk ++ include subdirmk/regen.mk ++ ++Write a Perdir.sd.mk in the toplevel, if you want. It should probably ++have: ++ ++ &:include subdirmk/cdeps.sd.mk ++ &:include subdirmk/clean.sd.mk ++ ++ ++Legal information ++----------------- ++ ++subdirmk is ++ Copyright 2019 Mark Wooding ++ Copyright 2019 Ian Jackson ++ ++ subdirmk and its example is free software; you can redistribute it ++ and/or modify it under the terms of the GNU Library General Public ++ License as published by the Free Software Foundation; either ++ version 2 of the License, or (at your option) any later version. ++ ++ This is distributed in the hope that it will be useful, but ++ WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Library General Public License for more details. ++ ++ You should have received a copy of the GNU Library General Public ++ License along with this library as the file LGPL-2. ++ If not, see https://www.gnu.org/. ++ ++Individual files generally contain the following tag in the copyright ++notice, instead of the full licence grant text: ++ SPDX-License-Identifier: LGPL-2.0-or-later ++As is conventional, this should be read as a licence grant. ++ ++Contributions are accepted based on the git commit Signed-off-by ++convention, by which the contributors' certify their contributions ++according to the Developer Certificate of Origin version 1.1 - see ++the file DEVELOPER-CERTIFICATE. ++ ++Where subdirmk is used by and incorporated into another project (eg ++via git subtree), the directory subdirmk/ is under GNU LGPL-2.0+, and ++the rest of the project are under that other project's licence(s). ++(The project's overall licence must be compatible with LGPL-2.0+.) diff --cc subdirmk/autogen.sh index 0000000,0000000..e28e80e new file mode 100755 --- /dev/null +++ b/subdirmk/autogen.sh @@@ -1,0 -1,0 +1,7 @@@ ++#!/bin/sh ++# subdirmk, autogen.sh (conventional autoconf invocation script) ++# Copyright 2019 Ian Jackson ++# SPDX-License-Identifier: LGPL-2.0-or-later ++set -e ++cd ${0%/*} ++autoconf diff --cc subdirmk/cdeps.sd.mk index 0000000,402e687..402e687 mode 000000,100644..100644 --- a/subdirmk/cdeps.sd.mk +++ b/subdirmk/cdeps.sd.mk diff --cc subdirmk/clean.sd.mk index 0000000,08f8dcc..08f8dcc mode 000000,100644..100644 --- a/subdirmk/clean.sd.mk +++ b/subdirmk/clean.sd.mk diff --cc subdirmk/example/.gitignore index 0000000,a97b413..a97b413 mode 000000,100644..100644 --- a/subdirmk/example/.gitignore +++ b/subdirmk/example/.gitignore diff --cc subdirmk/example/DEVELOPER-CERTIFICATE index 0000000,d56384e..d56384e mode 000000,120000..120000 --- a/subdirmk/example/DEVELOPER-CERTIFICATE +++ b/subdirmk/example/DEVELOPER-CERTIFICATE diff --cc subdirmk/example/LGPL-2 index 0000000,318395d..318395d mode 000000,120000..120000 --- a/subdirmk/example/LGPL-2 +++ b/subdirmk/example/LGPL-2 diff --cc subdirmk/example/Perdir.sd.mk index 0000000,65b8630..65b8630 mode 000000,100644..100644 --- a/subdirmk/example/Perdir.sd.mk +++ b/subdirmk/example/Perdir.sd.mk diff --cc subdirmk/example/Subdir.sd.mk index 0000000,5c2040a..5c2040a mode 000000,100644..100644 --- a/subdirmk/example/Subdir.sd.mk +++ b/subdirmk/example/Subdir.sd.mk diff --cc subdirmk/example/autogen.sh index 0000000,589d835..589d835 mode 000000,120000..120000 --- a/subdirmk/example/autogen.sh +++ b/subdirmk/example/autogen.sh diff --cc subdirmk/example/configure.ac index 0000000,b7c07e7..b7c07e7 mode 000000,100644..100644 --- a/subdirmk/example/configure.ac +++ b/subdirmk/example/configure.ac diff --cc subdirmk/example/lib/Subdir.sd.mk index 0000000,c2939c5..c2939c5 mode 000000,100644..100644 --- a/subdirmk/example/lib/Subdir.sd.mk +++ b/subdirmk/example/lib/Subdir.sd.mk diff --cc subdirmk/example/lib/t/Subdir.sd.mk index 0000000,ae11cd0..ae11cd0 mode 000000,100644..100644 --- a/subdirmk/example/lib/t/Subdir.sd.mk +++ b/subdirmk/example/lib/t/Subdir.sd.mk diff --cc subdirmk/example/lib/t/toytest.c index 0000000,aa03e1e..aa03e1e mode 000000,100644..100644 --- a/subdirmk/example/lib/t/toytest.c +++ b/subdirmk/example/lib/t/toytest.c diff --cc subdirmk/example/lib/toylib.c index 0000000,6e73f76..6e73f76 mode 000000,100644..100644 --- a/subdirmk/example/lib/toylib.c +++ b/subdirmk/example/lib/toylib.c diff --cc subdirmk/example/lib/toylib.h index 0000000,04848d5..04848d5 mode 000000,100644..100644 --- a/subdirmk/example/lib/toylib.h +++ b/subdirmk/example/lib/toylib.h diff --cc subdirmk/example/src/Subdir.sd.mk index 0000000,402116e..402116e mode 000000,100644..100644 --- a/subdirmk/example/src/Subdir.sd.mk +++ b/subdirmk/example/src/Subdir.sd.mk diff --cc subdirmk/example/src/toy.c index 0000000,a70f861..a70f861 mode 000000,100644..100644 --- a/subdirmk/example/src/toy.c +++ b/subdirmk/example/src/toy.c diff --cc subdirmk/example/subdirmk index 0000000,a96aa0e..a96aa0e mode 000000,120000..120000 --- a/subdirmk/example/subdirmk +++ b/subdirmk/example/subdirmk diff --cc subdirmk/generate index 0000000,486bdc5..486bdc5 mode 000000,100755..100755 --- a/subdirmk/generate +++ b/subdirmk/generate diff --cc subdirmk/regen.mk.in index 0000000,83952c9..83952c9 mode 000000,100644..100644 --- a/subdirmk/regen.mk.in +++ b/subdirmk/regen.mk.in diff --cc subdirmk/subdirmk.ac index 0000000,bacd1cf..bacd1cf mode 000000,100644..100644 --- a/subdirmk/subdirmk.ac +++ b/subdirmk/subdirmk.ac diff --cc subdirmk/tests/check index 0000000,f0914dd..f0914dd mode 000000,100755..100755 --- a/subdirmk/tests/check +++ b/subdirmk/tests/check diff --cc subdirmk/usual.mk.in index 0000000,66c71eb..66c71eb mode 000000,100644..100644 --- a/subdirmk/usual.mk.in +++ b/subdirmk/usual.mk.in