From be97c982f70fb8bb9f688a1dfa4e7afe979210b3 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Tue, 7 Mar 2017 14:07:06 +0200 Subject: Spec wildcard pattern-based name generation --- doc/manual.cli | 127 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 127 insertions(+) diff --git a/doc/manual.cli b/doc/manual.cli index 2fa666e..02d1638 100644 --- a/doc/manual.cli +++ b/doc/manual.cli @@ -16,6 +16,133 @@ This is the preface. +\h1#name-pattern|Name Pattern| + +For convenience, in certain contexts, names can be generated with shell-like +wildcard patterns. A name is a \i{name pattern} if its value contains one or +more unquoted wildcard characters or character sequences. For example: + +\ +./: */ # All (immediate) subdirectories +exe{hello}: {hxx cxx}{**} # All C++ header/source files. +pattern = '*.txt' # Literal '*.txt'. +\ + +Pattern-based name generation is only performed in certain contexts. +Specifically, it is performed in prerequisite names and variable assignments +but not in target names (where it may be interpreted as a pattern at a high +level), for example (@@ TODO: clarify after implemented): + +\ +s = *.txt # Variable assignment. +./: cxx{*} # Prerequisite names. +cxx{*}: dist = false # Target pattern. +\ + +The following characters are wildcards: + +\ +* - match any number of characters (including zero) +? - match any single character +\ + +If a pattern ends with a directory separator, then it only matches +directories. Otherwise, it only matches files. Matches that start with a dot +(\c{.}) are automatically ignored unless the pattern itself also starts with +this character. + +In addition to the above wildcard characters, \c{**} and \c{***} are +recognized as wildcard character sequences. If a pattern contains \c{**}, then +it is matched just like \c{*} but in all the subdirectories, recursively. The +\c{***} wildcard behaves like \c{**} but also matches the start directory +itself. For example: + +\ +exe{hello}: cxx{**} # All C++ source files, including in subdirectories. +\ + +A \c{{\}}-enclosed pattern value may be following by inclusion/exclusion +patterns/matches. A subsequent value is treated as an inclusion if it starts +with a plus sign (\c{+}) and as an exclusion if it starts with a minus +(\c{-}). A subsequent value that does not start with either of these signs is +illegal. For example: + +\ +exe{hello}: cxx{f* -foo} # Exclude foo if present. +exe{hello}: cxx{f* +foo} # Include foo if not present. +exe{hello}: cxx{f* -fo?} # Exclude foo and fox if present. +exe{hello}: cxx{f* +b* -foo -bar} # Exclude foo and bar if present. +\ + +One common situation that calls for exclusions is auto-generated source +code. Let's say we have auto-generated command line parser in \c{options.hxx} +and \c{options.cxx}. Because of the in-tree builds, our name pattern may or +may not find these files. Note, however, that we cannot just include them as +non-pattern prerequisites. We also have to exclude them from the pattern match +since otherwise we may end up with duplicate prerequisites. As a result, this +is how we have to handle this case provided we want to continue using patterns +to find other, non-generated source files: + +\ +exe{hello}: {hxx cxx}{* -options} {hxx cxx}{options} +\ + +Pattern matching as well as inclusion/exclusion logic is target +type-specific. If the name pattern does not contain a type, then the +\c{dir{\}} type is assumed if the pattern ends with a directory separator and +\c{file{\}} otherwise. + +For the \c{dir{\}} target type the trailing directory separator is added to +the pattern and all the inclusion/exclusion patterns/matches that do not +already end with one. Then the filesystem search is performed for matching +directories. For example: + +\ +./: dir{* -build} # Search for */, exclude build/. +\ + +For the \c{file{\}} and \c{file{\}}-based target types the default extension +(if any) is added to the pattern and all the inclusion/exclusion +patterns/matches that do not already contain an extension. Then the filesystem +search is performed for matching files. + +For example, the \c{cxx{\}} target type obtains the default extension from the +\c{extension} variable. Assuming we have the following line in our +\c{root.build}: + +\ +cxx{*}: extension = cxx +\ + +And the following in our \c{buildfile}: + +\ +exe{hello}: {cxx}{* -foo -bar.cpp} +\ + +The pattern match will first search for all the files matching the \c{*.cxx} +pattern in \c{src_base} and then exclude \c{foo.cxx} and \c{bar.cpp} from the +result. + +If the name pattern includes an absolute directory, then the pattern match is +performed in that directory and the generated names include absolute +directories as well. Otherwise, the pattern match is performed in the +\i{pattern base} directory. In buildfiles this is \c{src_base} while on the +command line \- the current working directory (@@ TODO: spec for testscript, +other contexts). In this case the generated names are relative to the base +directory. For example, assuming we have the \c{foo.cxx} and \c{b/bar.cxx} +source files: + +\ +exe{hello}: $src_base/cxx{**} # $src_base/cxx{foo} $src_base/b/cxx{bar} +exe{hello}: cxx{**} # cxx{foo} b/cxx{bar} +\ + +If the name generation cannot be performed because the base directory is +unknown, target type is unknown, or the target type is not directory or +file-based, then the name pattern is returned as is (that is, as an ordinary +name). + \h1#grammar|Grammar| \ -- cgit v1.1