aboutsummaryrefslogtreecommitdiff
path: root/doc
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2017-03-07 14:07:06 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2017-03-07 14:07:06 +0200
commitbe97c982f70fb8bb9f688a1dfa4e7afe979210b3 (patch)
tree5e805649ba1f8c603da1d305994e2c1e8d877dac /doc
parent1215355bc101a1691c468909db60a167a694ddca (diff)
Spec wildcard pattern-based name generation
Diffstat (limited to 'doc')
-rw-r--r--doc/manual.cli127
1 files changed, 127 insertions, 0 deletions
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|
\