aboutsummaryrefslogtreecommitdiff
path: root/doc/manual.cli
diff options
context:
space:
mode:
Diffstat (limited to 'doc/manual.cli')
-rw-r--r--doc/manual.cli1124
1 files changed, 1057 insertions, 67 deletions
diff --git a/doc/manual.cli b/doc/manual.cli
index 6767f22..64275ce 100644
--- a/doc/manual.cli
+++ b/doc/manual.cli
@@ -1040,6 +1040,9 @@ a full package manifest they can be interleaved with non-header values.
\
name: <name>
version: <version>
+[upstream-version]: <string>
+[type]: <type>
+[language]: <lang>
[project]: <name>
[priority]: <priority> [; <comment>]
summary: <text>
@@ -1052,8 +1055,12 @@ license: <licenses> [; <comment>]
[description]: <text>
[description-file]: <path> [; <comment>]
[description-type]: <text-type>
+[package-description]: <text>
+[package-description-file]: <path> [; <comment>]
+[package-description-type]: <text-type>
[changes]: <text>
[changes-file]: <path> [; <comment>]
+[changes-type]: <text-type>
[url]: <url> [; <comment>]
[doc-url]: <url> [; <comment>]
@@ -1076,6 +1083,22 @@ license: <licenses> [; <comment>]
[builds]: <class-expr> [; <comment>]
[build-include]: <config>[/<target>] [; <comment>]
[build-exclude]: <config>[/<target>] [; <comment>]
+[build-auxiliary]: <config> [; <comment>]
+[build-auxiliary-<name>]: <config> [; <comment>]
+[build-bot]: <pub-key>
+
+[*-build-config]: <args> [; <comment>]
+
+[*-builds]: <class-expr> [; <comment>]
+[*-build-include]: <config>[/<target>] [; <comment>]
+[*-build-exclude]: <config>[/<target>] [; <comment>]
+[*-build-auxiliary]: <config> [; <comment>]
+[*-build-auxiliary-<name>]: <config> [; <comment>]
+[*-build-bot]: <pub-key>
+
+[*-build-email]: <email> [; <comment>]
+[*-build-warning-email]: <email> [; <comment>]
+[*-build-error-email]: <email> [; <comment>]
[build-file]: <path>
@@ -1086,6 +1109,10 @@ license: <licenses> [; <comment>]
[bootstrap-build2]: <text>
[root-build2]: <text>
[*-build2]: <text>
+
+[*-name]: <name> [<name>...]
+[*-version]: <string>
+[*-to-downstream-version]: <regex>
\
\h2#manifest-package-name|\c{name}|
@@ -1118,6 +1145,53 @@ and use the \c{upstream-version} value to preserve the original version for
information.
+\h2#manifest-package-type-language|\c{type}, \c{language}|
+
+\
+[type]: <type>
+[language]: <lang>
+
+<type> = <name>[,<sub-options>]
+<lang> = <name>[=impl]
+\
+
+The package type and programming language(s).
+
+The currently recognized package types are \c{exe}, \c{lib}, and \c{other}. If
+the type is not specified, then if the package name starts with \c{lib}, then
+it is assumed to be \c{lib} and \c{exe} otherwise (see \l{#package-name
+Package Name} for details). Other package types may be added in the future and
+code that does not recognize a certain package type should treat it as
+\c{other}. The type name can be followed by a comma-separated list of
+sub-options. Currently, the only recognized sub-option is \c{binless} which
+applies to the \c{lib} type indicating a header-only (or equivalent) library.
+For example:
+
+\
+type: lib,binless
+\
+
+The package language must be in the lower case, for example, \c{c}, \c{c++},
+\c{rust}, \c{bash}. If the language is not specified, then if the package name
+has an extension (as in, for example, \c{libbutl.bash}; see \l{#package-name
+Package Name} for details) the extension is assumed to name the package
+language. Otherwise, \c{cc} (unspecified \c{c}-common language) is assumed. If
+a package uses multiple languages, then multiple \c{language} values must be
+specified. The languages which are only used in a library's implementation (as
+opposed to also in its interface) should be marked as such. For example, for a
+C library with C++ implementation:
+
+\
+type: lib
+language: c
+language: c++=impl
+\
+
+\N|If the use of a language, such as C++, also always implies the use of
+another language, such as C, then such an implied language need not be
+explicitly specified.|
+
+
\h2#manifest-package-project|\c{project}|
\
@@ -1325,23 +1399,30 @@ as well as words from its summary are already considered to be keywords and
need not be repeated in this value.
-\h2#manifest-package-description|\c{description}|
+\h2#manifest-package-description|\c{description}, \c{package-description}|
\
[description]: <text>
[description-file]: <path> [; <comment>]
[description-type]: <text-type>
+[package-description]: <text>
+[package-description-file]: <path> [; <comment>]
+[package-description-type]: <text-type>
\
-The detailed description of the package. It can be provided either inline as a
-text fragment or by referring to a file within a package (e.g., \c{README}),
-but not both.
+The detailed description of the project (\c{description}) and package
+(\c{package-description}). If the package description is not specified, it is
+assumed to be the same as the project description. It only makes sense to
+specify the \c{package-description} value if the project and package are
+maintained separately. A description can be provided either inline as a text
+fragment or by referring to a file within a package (for example, \c{README}),
+but not both. For \c{package-description-file} the recommended file name is
+\c{PACKAGE-README} or \c{README-PACKAGE}.
In the web interface (\c{brep}) the description is displayed according to its
type. Currently, pre-formatted plain text, \l{https://github.github.com/gfm
GitHub-Flavored Markdown}, and \l{https://spec.commonmark.org/current
-CommonMark} are supported with the following \c{description-type} values,
-respectively:
+CommonMark} are supported with the following \c{*-type} values, respectively:
\
text/plain
@@ -1352,13 +1433,13 @@ text/markdown;variant=CommonMark
If just \c{text/markdown} is specified, then the GitHub-Flavored Markdown
(which is a superset of CommonMark) is assumed.
-If the description type is not explicitly specified and the description is
-specified as \c{description-file}, then an attempt to derive the type from the
-file extension is made. Specifically, the \cb{.md} and \cb{.markdown}
-extensions are mapped to \c{text/markdown}, the \cb{.txt} and no extension are
-mapped to \c{text/plain}, and all other extensions are treated as an unknown
-type, similar to unknown \c{description-type} values. And if the description
-is not specified as a file, \c{text/plain} is assumed.
+If a description type is not explicitly specified and the description is
+specified as \c{*-file}, then an attempt to derive the type from the file
+extension is made. Specifically, the \cb{.md} and \cb{.markdown} extensions
+are mapped to \c{text/markdown}, the \cb{.txt} and no extension are mapped to
+\c{text/plain}, and all other extensions are treated as an unknown type,
+similar to unknown \c{*-type} values. And if a description is not specified as
+a file, \c{text/plain} is assumed.
\h2#manifest-package-changes|\c{changes}|
@@ -1366,6 +1447,7 @@ is not specified as a file, \c{text/plain} is assumed.
\
[changes]: <text>
[changes-file]: <path> [; <comment>]
+[changes-type]: <text-type>
\
The description of changes in the release.
@@ -1399,8 +1481,11 @@ changes:
changes-file: NEWS
\
-In the web interface (\c{brep}) the changes are displayed as pre-formatted
-plain text, similar to the package description.
+In the web interface (\c{brep}) the changes are displayed according to their
+type, similar to the package description (see the
+\l{#manifest-package-description \c{description}} value for details). If
+the changes type is not explicitly specified, then the types deduced for
+individual \c{changes} values must all be the same.
\h2#manifest-package-url|\c{url}|
@@ -2057,15 +2142,19 @@ The \c{bootstrap} value should be used to mark build system modules that
require bootstrapping. The \c{host} value should be used to mark packages,
such source code generators, that are normally specified as build-time
dependencies by other packages and therefore should be built in a host
-configuration. See the \c{bbot} documentation for details.
+configuration. See the \l{bbot \c{bbot} documentation} for details.
-\h2#manifest-package-tests-examples-benchmarks|\c{tests, examples, benchmarks}|
+\h2#manifest-package-tests-examples-benchmarks|\c{tests}, \c{examples}, \c{benchmarks}|
\
-[tests]: [*] <name> [<version-constraint>]
-[examples]: [*] <name> [<version-constraint>]
-[benchmarks]: [*] <name> [<version-constraint>]
+[tests]: [*] <package> ['?' <enable-cond>] [<reflect-var>]
+[examples]: [*] <package> ['?' <enable-cond>] [<reflect-var>]
+[benchmarks]: [*] <package> ['?' <enable-cond>] [<reflect-var>]
+
+<package> = <name> [<version-constraint>]
+<enable-cond> = '(' <buildfile-eval-expr> ')'
+<reflect-var> = <config-var> '=' <value>
\
Separate tests, examples, and benchmarks packages. If the value starts with
@@ -2075,8 +2164,8 @@ specified package. Otherwise it is \i{run-time}. See the
dependencies.
These packages are built and tested by automated build bots together with the
-primary package (see the \c{bbot} documentation for details). This, in
-particular, implies that these packages must be available from the primary
+primary package (see the \l{bbot \c{bbot} documentation} for details). This,
+in particular, implies that these packages must be available from the primary
package's repository or its complement repositories, recursively. The
recommended naming convention for these packages is the primary package name
followed by \c{-tests}, \c{-examples}, or \c{-benchmarks}, respectively. For
@@ -2084,7 +2173,7 @@ example:
\
name: hello
-tests : hello-tests
+tests: hello-tests
examples: hello-examples
\
@@ -2097,18 +2186,57 @@ it can also be specified in terms of the primary package's version (see the
tests: hello-tests ~$
\
-Note that normally the tests, etc., packages themselves do not have an
-explicit dependency on the primary package (in a sense, the primary package
-has a special dependency on them). They are also not built by automated build
-bots separately from their primary package but may have their own build
-constraints, for example, to be excluded from building on some platforms where
-the primary package is still built, for example:
+Note that normally the tests, etc., packages themselves (we'll call them all
+test packages for short) do not have an explicit dependency on the primary
+package (in a sense, the primary package has a special test dependency on
+them). They are also not built by automated build bots separately from their
+primary package but may have their own build constraints, for example, to be
+excluded from building on some platforms where the primary package is still
+built, for example:
\
name: hello-tests
builds: -windows
\
+Also note that a test package may potentially be used as a test dependency for
+multiple primary packages. In this case a primary package normally needs to
+reflect to the test package the fact that it is the one being tested. This can
+be achieved by setting the test package's configuration variable (see the
+\l{#manifest-package-depends \c{depends}} value for details on
+reflection). For example:
+
+\
+name: hello-foo
+tests: hello-tests config.hello_tests.test=hello-foo
+
+name: hello-bar
+tests: hello-tests config.hello_tests.test=hello-bar
+\
+
+If it is plausible that the test package may also be built explicitly, for
+example, to achieve a more complicated setup (test multiple main packages
+simultaneously, etc), then the test dependencies need to be made conditional
+in the primary packages so that the explicit configuration is preferred over
+the reflections (see the \l{#manifest-package-depends \c{depends}} value for
+details on conditional dependencies). For example:
+
+\
+name: hello-foo
+tests: hello-tests \
+? (!$defined(config.hello_tests.test)) config.hello_tests.test=hello-foo
+
+name: hello-bar
+tests: hello-tests \
+? (!$defined(config.hello_tests.test)) config.hello_tests.test=hello-bar
+\
+
+Note that in contrast to the \l{#manifest-package-depends \c{depends}} value,
+both the reflection and condition refer to the variables defined not by the
+package which specifies the test dependency (primary package), but the package
+such a dependency refers to (test package).
+
+
\h2#manifest-package-builds|\c{builds}|
\
@@ -2119,58 +2247,60 @@ builds: -windows
<class-term> = ('+'|'-'|'&')['!'](<class-name> | '(' <class-expr> ')')
\
-The package build configurations. They specify the build configuration classes
-the package should or should not be built for by automated build bots. For
-example:
+The common package build target configurations. They specify the target
+configuration classes the package should or should not be built for by
+automated build bots, unless overridden by a package configuration-specific
+value (see \l{#manifest-package-build-config \c{*-build-config}} for details).
+For example:
\
builds: -windows
\
-Build configurations can belong to multiple classes with their names and
-semantics varying between different build bot deployments. However, the
+Build target configurations can belong to multiple classes with their names
+and semantics varying between different build bot deployments. However, the
pre-defined \c{none}, \c{default}, \c{all}, \c{host}, and \c{build2} classes
are always provided. If no \c{builds} value is specified in the package
manifest, then the \c{default} class is assumed.
-\N|A build configuration class can also derive from another class in which
+\N|A target configuration class can also derive from another class in which
case configurations that belong to the derived class are treated as also
belonging to the base class (or classes, recursively). See the Build
Configurations page of the build bot deployment for the list of available
-build configurations and their classes.|
+target configurations and their classes.|
The \c{builds} value consists of an optional underlying class set
(\c{<class-uset>}) followed by a class set expression (\c{<class-expr>}). The
underlying set is a space-separated list of class names that define the set of
-build configurations to consider. If not specified, then all the
+build target configurations to consider. If not specified, then all the
configurations belonging to the \c{default} class are assumed. The class set
expression can then be used to exclude certain configurations from this
initial set.
The class expression is a space-separated list of terms that are evaluated
from left to right. The first character of each term determines whether the
-build configuration that belong to its set are added to (\c{+}), subtracted
-from (\c{-}), or intersected with (\c{&}) the current set. If the second
-character in the term is \c{!}, then its set of configuration is inverted
-against the underlying set. The term itself can be either the class name or a
-parenthesized expression. Some examples (based on the
+build target configuration that belong to its set are added to (\c{+}),
+subtracted from (\c{-}), or intersected with (\c{&}) the current set. If the
+second character in the term is \c{!}, then its set of configuration is
+inverted against the underlying set. The term itself can be either the class
+name or a parenthesized expression. Some examples (based on the
\l{https://ci.cppget.org/?build-configs cppget.org} deployment):
\
-builds: none ; None.
-builds: all ; All (suitable for libraries).
-builds: host ; All host (suitable for tools).
-builds: default ; All default.
-builds: host : &default ; Host default.
-builds: default legacy ; All default and legacy.
-builds: host: &( +default +legacy ) ; Host default and legacy.
-builds: -windows ; Default except Windows.
-builds: all : -windows ; All except Windows.
-builds: all : -mobile ; All except mobile.
-builds: all : &gcc ; All with GCC only.
-builds: all : &gcc-8+ ; All with GCC 8 and up only.
-builds: gcc : -optimized ; GCC without optimization.
-builds: gcc : &( +linux +macos ) ; GCC on Linux and Mac OS.
+builds: none ; None.
+builds: all ; All (suitable for libraries).
+builds: all : &host ; All host (suitable for tools).
+builds: default ; All default.
+builds: default : &host ; Default host.
+builds: default legacy ; All default and legacy.
+builds: default legacy : &host ; Default and legacy host.
+builds: -windows ; Default except Windows.
+builds: all : -windows ; All except Windows.
+builds: all : -mobile ; All except mobile.
+builds: all : &gcc ; All with GCC only.
+builds: all : &gcc-8+ ; All with GCC 8 and up only.
+builds: all : &gcc -optimized ; All GCC without optimization.
+builds: all : &gcc &( +linux +macos ) ; All GCC on Linux and Mac OS.
\
Notice that the colon and parentheses must be separated with spaces from both
@@ -2194,7 +2324,7 @@ builds: -( +macos &gcc) ; Homebrew GCC is not supported.
\
\N|The \c{builds} value comments are used by the web interface (\c{brep}) to
-display the reason for the build configuration exclusion.|
+display the reason for the build target configuration exclusion.|
After evaluating all the \c{builds} values, the final configuration set can be
further fine-tuned using the \l{#manifest-package-include-exclude
@@ -2208,20 +2338,20 @@ further fine-tuned using the \l{#manifest-package-include-exclude
[build-exclude]: <config>[/<target>] [; <comment>]
\
-The package build inclusions and exclusions. The \c{build-include} and
+The common package build inclusions and exclusions. The \c{build-include} and
\c{build-exclude} values further reduce the configuration set produced by
evaluating the \l{#manifest-package-builds \c{builds}} values. The \i{config}
and \i{target} values are filesystem wildcard patterns which are matched
-against the build configuration names and target names (see the \c{bbot}
-documentation for details). In particular, the \c{*} wildcard matches zero or
-more characters within the name component while the \c{**} sequence matches
-across the components. Plus, wildcard-only pattern components match absent
-name components. For example:
+against the build target configuration names and target names (see the \l{bbot
+\c{bbot} documentation} for details). In particular, the \c{*} wildcard
+matches zero or more characters within the name component while the \c{**}
+sequence matches across the components. Plus, wildcard-only pattern components
+match absent name components. For example:
\
-build-exclude: windows** # matches windows_10-msvc_15
-build-exclude: macos*-gcc** # matches macos_10.13-gcc_8.1-O3
-build-exclude: linux-gcc*-* # matches linux-gcc_8.1 and linux-gcc_8.1-O3
+build-exclude: windows** # matches windows_10-msvc_15
+build-exclude: macos*-gcc** # matches macos_10.13-gcc_8.1-O3
+build-exclude: linux-gcc*-* # matches linux-gcc_8.1 and linux-gcc_8.1-O3
\
The exclusion and inclusion patterns are applied in the order specified with
@@ -2245,7 +2375,315 @@ build-exclude: ** ; Only supported on Linux.
\
Note that the comment of the matching exclusion is used by the web interface
-(\c{brep}) to display the reason for the build configuration exclusion.
+(\c{brep}) to display the reason for the build target configuration exclusion.
+
+
+\h2#manifest-package-build-auxiliary|\c{build-auxiliary}|
+
+\
+[build-auxiliary]: <config> [; <comment>]
+[build-auxiliary-<name>]: <config> [; <comment>]
+\
+
+The common package build auxiliary configurations. The \c{build-auxiliary}
+values can be used to specify auxiliary configurations that provide additional
+components which are required for building or testing a package and that are
+impossible or impractical to provide as part of the build configuration
+itself. For example, a package may need access to a suitably configured
+database, such as PostgreSQL, in order to run its tests. Currently no more
+than \c{9} auxiliary configurations can be specified.
+
+The \i{config} value is a filesystem wildcard patterns which is matched
+against the auxiliary configuration names (which are in turn derived from
+auxiliary machine names; see the \l{bbot \c{bbot} documentation} for
+details). In particular, the \c{*} wildcard matches zero or more characters
+within the name component while the \c{**} sequence matches across the
+components. Plus, wildcard-only pattern components match absent name
+components. For example:
+
+\
+build-auxiliary: linux_debian_12-postgresql_16
+build-auxiliary: linux_*-postgresql_*
+build-auxiliary: *-postgresql**
+\
+
+\N|If multiple auxiliary configurations match the specified pattern, then
+one is picked at random for every build.|
+
+If multiple auxiliary configurations are required, then they must be given
+distinct names with the \i{name} component. For example:
+
+\
+build-auxiliary-pgsql: *-postgresql_*
+build-auxiliary-mysql: *-mysql_*
+\
+
+Another example:
+
+\
+build-auxiliary-primary: *-postgresql_*
+build-auxiliary-secondary: *-postgresql_*
+\
+
+Auxiliary machines communicate information about their setup to the build
+machine using environment variables (see
+\l{bbot#arch-task-auxiliary-environment \c{auxiliary-environment}} for
+details). For example, an auxiliary machine that provides a test PostgreSQL
+database may need to communicate the host IP address and port on which it can
+be accessed as well as the user to login as and the database name to use. For
+example:
+
+\
+DATABASE_HOST=192.168.0.1
+DATABASE_PORT=5432
+DATABASE_USER=test
+DATABASE_NAME=test
+\
+
+If the auxiliary configuration is specified as \c{build-auxiliary-<name>},
+then capitalized and sanitized \i{name}_ is used as a prefix in the
+environment variables corresponding to the machine. For example, for the
+auxiliary configurations specified as:
+
+\
+build-auxiliary-pg-sql: *-postgresql_*
+build-auxiliary-my-sql: *-mysql_*
+\
+
+The environment variables could be:
+
+\
+PG_SQL_DATABASE_HOST=192.168.0.1
+PG_SQL_DATABASE_PORT=5432
+...
+
+MY_SQL_DATABASE_HOST=192.168.0.2
+MY_SQL_DATABASE_PORT=3306
+...
+\
+
+The auxiliary environment variables are in effect for the entire build. The
+recommended place to propagate them to the package configuration is the
+\c{*-build-config} value. For example:
+
+\
+build-auxiliary: *-postgresql_*
+default-build-config:
+\\
+config.hello.pgsql_host=$getenv(DATABASE_HOST)
+config.hello.pgsql_port=$getenv(DATABASE_PORT)
+...
+\\
+\
+
+\h2#manifest-package-build-bot|\c{build-bot}|
+
+\
+[build-bot]: <pub-key>
+\
+
+The common package build custom bot public key (see \l{bbot \c{build2} build
+bot manual} for background). Multiple \c{build-bot} values can be specified to
+list several custom build bots. If specified, then such custom bots will be
+used instead of (note: not in addition to) the default bots to build this
+package. Custom bots can be used, for example, to accommodate packages that
+have special requirements, such as proprietary dependencies, and which cannot
+be fulfilled using the default bots. The public key should be in the PEM
+format. For example:
+
+\
+build-bot:
+\\
+-----BEGIN PUBLIC KEY-----
+MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAw5liP5pyU9ebC/nD3djZ
+1H2dlKmUyiX0Z8POvKhLREd0B3rM59bPcnbRB4HMIhj0J0hUBvS8xb4u5udCPToa
+x0A/LMWZ6claiivNtJ3CdLV98eklWdNUg5WXOuqq9QDKXw2ZpGbwDwCOh6aHSWVq
+98N9AQx0ZMmMWz3qhRyxPfh+GeJ05uj2ohU9FeUJxeqUcgJT/UcMZ3+7KYbwr+Uq
+/HCoX1BmN6nvzhQGHvJIZ2IcjvOQ0AUrPmpSZN01Zr3ZEpkHM3hJWNLu3ntJLGBQ
+0aT5kG3iqFyr9q3M3c4J8c0AWrnDjvj0qnCyjNwqW+qIpatmCNT43DmgYr9fQLW0
+UHusburz53AbXs12zu3gZzkb0irlShatkMqqQaqaU0/+zw1LnoZ+rvmn2XV97UuK
+LFKMKXCnyi2ZG65IZHGkjBVAPuvsX6RgLNyner/QtkDJTbfhktInbG08dCPqv1EF
+1OtcYKMTn8I5P2VmMO6SXXDLMSdU8b5DA5EY6Ca6JBB8g06S9sqGqXgQFysAnZs1
+VFgMopf8WZqj23x+DX+9KKT2pVnjbwRvBAntuCDoO75gWoETDnCQXEei/PbyamPq
+9+NjNsTDn67iJTGncZbII+eciY2YiFHm6GMzBPsUYlQcxiuO4X36jW6m2rwuw37K
+oFDbGI3uY4LnhwmDFLbjtk8CAwEAAQ==
+-----END PUBLIC KEY-----
+\\
+\
+
+Note that such custom build bots must offer the same set of machines (or a
+subset thereof) as the default bots. In other words, you cannot invent new
+build configuration names (and the corresponding machines) with custom build
+bots \- for that you would need to run your own \c{brep} deployment. Note also
+that the list of machines offered by custom bots should be consistent with the
+build configurations enabled by the package (see \l{#manifest-package-builds
+\c{builds}} for details). For example, if the package enables a configuration
+that is not offered by any of the custom bots listed, then this configuration
+will remain unbuilt forever.
+
+\N|Note that custom build bot public keys are publicly known and nothing
+prevents someone else from specifying your bot's public key in their own
+package and thus triggering a build on your bot of a potentially rogue
+package. As a result, carefully consider the information that you make
+available in your custom machines (which will be easy to exfiltrate) as well
+as the environment in which you run your custom bots (which can potentially be
+compromised). In the future, \c{bbot} may offer mechanisms to restrict the
+names and locations of packages that it is allowed to build.|
+
+
+\h2#manifest-package-build-config|\c{*-build-config}|
+
+\
+[*-build-config]: <args> [; <comment>]
+
+<args> = [[[+|-]<prefix>:](<option>|<config-var>)]* \\
+ [(+|-)<prefix>:]* \\
+ [<dependency-spec>]* \\
+ [<package-specific-vars>]*
+
+<dependency-spec> = [{ <config-var> [<config-var>]* }+] <dependency>
+<dependency> = (?[sys:]|sys:)<name>[<version-spec>]
+<version-spec> = /<version> | <version-constraint>
+<package-specific-vars> = { <config-var> [<config-var>]* }+ <name>
+
+[*-builds]: <class-expr> [; <comment>]
+[*-build-include]: <config>[/<target>] [; <comment>]
+[*-build-exclude]: <config>[/<target>] [; <comment>]
+[*-build-auxiliary]: <config> [; <comment>]
+[*-build-auxiliary-<name>]: <config> [; <comment>]
+[*-build-bot]: <pub-key>
+
+[*-build-email]: <email> [; <comment>]
+[*-build-warning-email]: <email> [; <comment>]
+[*-build-error-email]: <email> [; <comment>]
+\
+
+The package build configurations where the substring matched by \c{*} in
+\c{*-build-config} denotes the configuration name. If specified, then the
+package is built in these configurations by automated build bots in addition
+to the default configuration (which is called \c{default}).
+
+The \c{*-build-config} values contain whitespace separated lists of
+potentially double/single-quoted package configuration arguments. The global
+(as opposed to package-specific) options and variables can be prefixed with
+the build bot worker script step ids or a leading portion thereof to restrict
+it to a specific step, operation, phase, or tool (see \l{bbot#arch-worker
+\cb{bbot} worker step ids}). The prefix can optionally begin with the \c{+} or
+\c{-} character (in this case the argument can be omitted) to enable or
+disable the respective step (see the list of \l{bbot#arch-controller worker
+steps} which can be enabled or disabled). Unprefixed global options,
+variables, and dependencies are passed to the \l{bpkg-pkg-build(1)} command at
+the \c{bpkg.configure.build} step. The package-specific configuration
+variables for this and/or the separate test packages are passed to
+\l{bpkg-pkg-build(1)} at the \c{bpkg.configure.build} and
+\c{bpkg.test-separate-installed.configure.build} steps. For example:
+
+\
+network-build-config: config.libfoo.network=true; Enable networking API.
+
+cache-build-config:
+\\
+config.libfoo.cache=true
+config.libfoo.buffer=4096
+;
+Enable caching.
+\\
+
+libbar-network-build-config:
+\\
+{ config.libbar.network=true }+ ?libbar
+;
+Enable networking API in libbar.
+\\
+
+older-libz-build-config: \"?libz ^1.0.0\"; Test with older libz version.
+
+sys-build-config:
+\\
+?sys:libbar ?sys:libz
+;
+Test with system dependencies.
+\\
+
+bindist-build-config:
+\\
++bpkg.bindist.debian:--recursive=full
+-bbot.sys-install:
++bbot.bindist.upload:
+;
+Generate and upload binary distribution package but don't test its installation.
+\\
+
+load-tests-build-config:
+\\
+{ config.libfoo_tests.load=true }+ libfoo-tests
+;
+Enable load testing.
+\\
+\
+
+Note that options with values can only be specified using the single argument
+notation, for example, \c{--verbose=4}.
+
+The package build configuration can override the common build target
+configurations set (specified with \l{#manifest-package-builds \c{builds}} and
+\l{#manifest-package-include-exclude \c{build-{include, exclude\}}}) by
+specifying the matching \c{*-builds} and/or \c{*-build-{include, exclude\}}
+values. For example:
+
+\
+network-builds: linux; Only supported on Linux.
+network-build-config: config.libfoo.network=true; Enable networking API.
+\
+
+Note that the common build target configurations set is overridden
+hierarchically meaning that the \c{*-build-{include, exclude\}} overrides
+don't discard the common \c{builds} values.
+
+The package build configuration can override the common build auxiliary
+machines. Note that the auxiliary machine set is overridden entirely, meaning
+that specifying one \c{*-build-auxiliary} value discard all the common
+\c{build-auxiliary} values for this package configuration.
+
+The package build configuration can override the common build custom bots.
+Note that the custom bot set is overridden entirely, meaning that specifying
+one \c{*-build-bot} value discards all the common \c{build-bot} values for
+this package configuration.
+
+The package build configuration can override the common build notification
+email addresses (specified with \l{#manifest-package-build-email
+\c{build-email}}, \l{#manifest-package-warning-email \c{build-warning-email}},
+and \l{#manifest-package-error-email \c{build-error-email}}) by specifying the
+matching \c{*-build-email} and/or \c{*-build-{warning, error\}-email} values.
+For example:
+
+\
+bindist-build-config:
+\\
++bpkg.bindist.debian:--recursive=full
++bbot.bindist.upload:
+;
+Generate and upload binary distribution package.
+\\
+bindist-build-error-email: builds@example.org
+\
+
+Note that to disable all the build notification emails for a specific package
+build configuration, specify the empty \c{*-build-email} value. For example:
+
+\
+sys-build-config: ?sys:libz; Test with system dependencies.
+sys-build-email:
+\
+
+The default configuration should normally build the package with no
+configuration arguments and for the common target build configurations
+set. While not recommended, this can be overridden by using the special
+\c{default} configuration name. For example:
+
+\
+default-build-config: config.libfoo.cache=true
+\
\h2#manifest-package-build-file|\c{build-file}|
@@ -2306,6 +2744,95 @@ automatically added, for example, when the \l{#manifest-package-list-pkg
package list manifest} is created.
+\h2#manifest-package-distribution|\c{*-{name, version, to-downstream-version\}}|
+
+\
+[<distribution>-name]: <name> [<name>...]
+[<distribution>-version]: <string>
+[<distribution>-to-downstream-version]: <regex>
+
+<distribution> = <name>[_<version>]
+<regex> = /<pattern>/<replacement>/
+\
+
+The binary distribution package name and version mapping. The \c{-name} value
+specifies the distribution package(s) this \c{bpkg} package maps to. If
+unspecified, then appropriate name(s) are automatically derived from the
+\c{bpkg} package name (\l{#manifest-package-name \c{name}}). Similarly, the
+\c{-version} value specifies the distribution package version. If unspecified,
+then the \c{upstream-version} value is used if specified and the \c{bpkg}
+version (\l{#manifest-package-version \c{version}}) otherwise. While the
+\c{-to-downstream-version} values specify the reverse mapping, that is, from
+the distribution version to the \c{bpkg} version. If unspecified or none
+match, then the appropriate part of the distribution version is used. For
+example:
+
+\
+name: libssl
+version 1.1.1+18
+debian-name: libssl1.1 libssl-dev
+debian-version: 1.1.1n
+debian-to-downstream-version: /1\.1\.1[a-z]/1.1.1/
+debian-to-downstream-version: /([3-9])\.([0-9]+)\.([0-9]+)/\1.\2.\3/
+\
+
+If \c{upstream-version} is specified but the the distribution package version
+should be the same as the \c{bpkg} package version, then the special \c{$}
+\c{-version} value can be used. For example:
+
+\
+debian-version: $
+\
+
+The \c{<distribution>} name prefix consists of the distribution name followed
+by the optional distribution version. If the version is omitted, then the
+value applies to all versions. Some examples of distribution names and
+versions:
+
+\
+debian
+debian_10
+ubuntu_16.04
+fedora_32
+rhel_8.5
+freebsd_12.1
+windows_10
+macos_10
+macos_10.15
+macos_12
+\
+
+Note also that some distributions are like others (for example, \c{ubuntu} is
+like \c{debian}) and the corresponding \"base\" distribution values are
+considered if no \"derived\" values are specified.
+
+The \c{-name} value is used both during package consumption as a system
+package and production with the \l{bpkg-pkg-bindist(1)} command. During
+production, if multiple mappings match, then the value with the highest
+matching distribution version from the package \c{manifest} with the latest
+version is used. If it's necessary to use different names for the generated
+binary packages (called \"non-native packages\" in contrast to \"native
+packages\" that come from the distribution), the special \c{0} distribution
+version can be used to specify such a mapping. For example:
+
+\
+name: libsqlite3
+debian_9-name: libsqlite3-0 libsqlite3-dev
+debian_0-name: libsqlite3 libsqlite3-dev
+\
+
+Note that this special non-native mapping is ignored during consumption and a
+deviation in the package names that it introduces may make it impossible to
+use native and non-native binary packages interchangeably, for example, to
+satisfy dependencies.
+
+
+The exact format of the \c{-name} and \c{-version} values and the distribution
+version part that is matched against the \c{-to-downstream-version} pattern
+are distribution-specific. For details, see \l{#bindist-mapping-debian Debian
+Package Mapping} and \l{#bindist-mapping-fedora Fedora Package Mapping}.
+
+
\h#manifest-package-list-pkg|Package List Manifest for \cb{pkg} Repositories|
The package list manifest (the \c{packages.manifest} file found in the
@@ -2759,6 +3286,469 @@ signature: <sig>
The signature of the \c{packages.manifest} file. It should be calculated by
encrypting the above \c{sha256sum} value with the repository certificate's
private key and then \c{base64}-encoding the result.
+
+
+\h1#bindist-mapping|Binary Distribution Package Mapping|
+
+
+\h#bindist-mapping-debian|Debian Package Mapping|
+
+This section describes the distribution package mapping for Debian and
+alike (Ubuntu, etc).
+
+\h2#bindist-mapping-debian-consume|Debian Package Mapping for Consumption|
+
+A library in Debian is normally split up into several packages: the shared
+library package (e.g., \c{libfoo1} where \c{1} is the ABI version), the
+development files package (e.g., \c{libfoo-dev}), the documentation files
+package (e.g., \c{libfoo-doc}), the debug symbols package (e.g.,
+\c{libfoo1-dbg}), and the architecture-independent files (e.g.,
+\c{libfoo1-common}). All the packages except \c{-dev} are optional and there
+is quite a bit of variability. Here are a few examples:
+
+\
+libsqlite3-0 libsqlite3-dev
+
+libssl1.1 libssl-dev libssl-doc
+libssl3 libssl-dev libssl-doc
+
+libcurl4 libcurl4-openssl-dev libcurl4-doc
+libcurl3-gnutls libcurl4-gnutls-dev libcurl4-doc
+\
+
+Note that while most library package names in Debian start with \c{lib} (per
+the policy), there are exceptions (e.g., \c{zlib1g} \c{zlib1g-dev}). The
+header-only library package names may or may not start with \c{lib} and end
+with \c{-dev} (e.g., \c{libeigen3-dev}, \c{rapidjson-dev}, \c{catch2}). Also
+note that manual \c{-dbg} packages are obsolete in favor of automatic
+\c{-dbgsym} packages from Debian 9.
+
+For executable packages there is normally no \c{-dev} packages but \c{-dbg},
+\c{-doc}, and \c{-common} are plausible.
+
+Based on that, our approach when trying to automatically map a \c{bpkg}
+library package name to Debian package names is to go for the \c{-dev} package
+first and figure out the shared library package from that based on the fact
+that the \c{-dev} package should have the \c{==} dependency on the shared
+library package with the same version and its name should normally start with
+the \c{-dev} package's stem.
+
+The format of the \c{debian-name} (or alike) manifest value is a
+comma-separated list of one or more package groups:
+
+\
+<package-group> [, <package-group>...]
+\
+
+Where each \c{<package-group>} is the space-separated list of one or more
+package names:
+
+\
+<package-name> [ <package-name>...]
+\
+
+All the packages in the group should be \"package components\" (for the lack
+of a better term) of the same \"logical package\", such as \c{-dev}, \c{-doc},
+\c{-common} packages. They normally have the same version.
+
+The first group is called the main group and the first package in the
+group is called the main package. Note that all the groups are consumed
+(installed) but only the main group is produced (packaged).
+
+We allow/recommend specifying the \c{-dev} package instead of the main package
+for libraries (see \l{#manifest-package-type-language \c{type}} for details),
+seeing that we are capable of detecting the main package automatically (see
+above). If the library name happens to end with \c{-dev} (which poses an
+ambiguity), then the \c{-dev} package should be specified explicitly as the
+second package to disambiguate this situation.
+
+The Debian package version has the \c{[<epoch>:]<upstream>[-<revision>]} form
+(see \cb{deb-version(5)} for details). If no explicit mapping to the \c{bpkg}
+version is specified with the \c{debian-to-downstream-version} (or alike)
+manifest values or none match, then we fallback to using the \c{<upstream>}
+part as the \c{bpkg} version. If explicit mapping is specified, then we match
+it against the \c{[<epoch>:]<upstream>} parts ignoring \c{<revision>}.
+
+
+\h2#bindist-mapping-debian-produce|Debian Package Mapping for Production|
+
+The same \c{debian-name} (or alike) manifest values as used for consumption
+are also used to derive the package names for production except here we have
+the option to specify alternative non-native package names using the special
+\c{debian_0-name} (or alike) value. If only the \c{-dev} package is specified,
+then the main package name is derived from that by removing the \c{-dev}
+suffix. Note that regardless of whether the main package name is specified or
+not, the \l{bpkg-pkg-bindist(1)} command may omit generating the main package
+for a binless library.
+
+The generated binary package version can be specified with the
+\c{debian-version} (or alike) manifest value. If it's not specified, then the
+\c{upstream-version} is used if specified. Otherwise, the \c{bpkg} version
+is translated to the Debian version as described next.
+
+To recap, a Debian package version has the following form:
+
+\
+[<epoch>:]<upstream>[-<revision>]
+\
+
+For details on the ordering semantics, see the \c{Version} \c{control} file
+field documentation in the Debian Policy Manual. While overall unsurprising,
+one notable exception is \c{~}, which sorts before anything else and is
+commonly used for upstream pre-releases. For example, \c{1.0~beta1~svn1245}
+sorts earlier than \c{1.0~beta1}, which sorts earlier than \c{1.0}.
+
+There are also various special version conventions (such as all the revision
+components in \c{1.4-5+deb10u1~bpo9u1}) but they all appear to express
+relationships between native packages and/or their upstream and thus do not
+apply to our case.
+
+To recap, the \c{bpkg} version has the following form (see
+\l{#package-version Package Version} for details):
+
+\
+[+<epoch>-]<upstream>[-<prerel>][+<revision>]
+\
+
+Let's start with the case where neither distribution (\c{debian-version}) nor
+upstream version (\c{upstream-version}) is specified and we need to derive
+everything from the \c{bpkg} version (what follows is as much description as
+rationale).
+
+\dl|
+
+\li|\c{<epoch>}
+
+ On one hand, if we keep our (as in, \c{bpkg}) epoch, it won't necessarily
+ match Debian's native package epoch. But on the other it will allow our
+ binary packages from different epochs to co-exist. Seeing that this can be
+ easily overridden with a custom distribution version (see below), we keep
+ it.
+
+ Note that while the Debian start/default epoch is 0, ours is 1 (we use the 0
+ epoch for stub packages). So we shift this value range.|
+
+\li|\c{<upstream>[-<prerel>]}
+
+ Our upstream version maps naturally to Debian's. That is, our upstream
+ version format/semantics is a subset of Debian's.
+
+ If this is a pre-release, then we could fail (that is, don't allow
+ pre-releases) but then we won't be able to test on pre-release packages, for
+ example, to make sure the name mapping is correct. Plus sometimes it's
+ useful to publish pre-releases. We could ignore it, but then such packages
+ will be indistinguishable from each other and the final release, which is
+ not ideal. On the other hand, Debian has the mechanism (\c{~}) which is
+ essentially meant for this, so we use it. We will use \c{<prerel>} as is
+ since its format is the same as upstream and thus should map naturally.|
+
+\li|\c{<revision>}
+
+ Similar to epoch, our revision won't necessarily match Debian's native
+ package revision. But on the other hand it will allow us to establish a
+ correspondence between source and binary packages. Plus, upgrades between
+ binary package revisions will be handled naturally. Seeing that we allow
+ overriding the revision with a custom distribution version (see below),
+ we keep it.
+
+ Note also that both Debian and our revision start/default is 0. However, it
+ is Debian's convention to start revision from 1. But it doesn't seem worth
+ it for us to do any shifting here and so we will use our revision as is.
+
+ Another related question is whether we should also include some metadata
+ that identifies the distribution and its version that this package is
+ for. The strongest precedent here is probably Ubuntu's PPA. While there
+ doesn't appear to be a consistent approach, one can often see versions like
+ these:
+
+ \
+ 2.1.0-1~ppa0~ubuntu14.04.1,
+ 1.4-5-1.2.1~ubuntu20.04.1~ppa1
+ 22.12.2-0ubuntu1~ubuntu23.04~ppa1
+ \
+
+ Seeing that this is a non-sortable component (what in semver would be called
+ \"build metadata\"), using \c{~} is probably not the worst choice.
+
+ So we follow this lead and add the \c{~<ID><VERSION_ID>} \c{os-release(5)}
+ component to revision. Note that this also means we will have to make the 0
+ revision explicit. For example:
+
+ \
+ 1.2.3-1~debian10
+ 1.2.3-0~ubuntu20.04
+ \
+
+||
+
+The next case to consider is when we have the upstream version
+(\c{upstream-version} manifest value). After some rumination it feels correct
+to use it in place of the \c{<epoch>-<upstream>} components in the above
+mapping (upstream version itself cannot have epoch). In other words, we will
+add the pre-release and revision components from the \c{bpkg} version. If this
+is not the desired semantics, then it can always be overridden with the
+distribution version (see below).
+
+Finally, we have the distribution version. The Debian \c{<epoch>} and
+\c{<upstream>} components are straightforward: they should be specified by the
+distribution version as required. This leaves pre-release and revision. It
+feels like in most cases we would want these copied over from the \c{bpkg}
+version automatically \- it's too tedious and error-prone to maintain them
+manually. However, we want the user to have the full override ability. So
+instead, if empty revision is specified, as in \c{1.2.3-}, then we
+automatically add the \c{bpkg} revision. Similarly, if empty pre-release is
+specified, as in \c{1.2.3~}, then we add the \c{bpkg} pre-release. To add both
+automatically, we would specify \c{1.2.3~-} (other combinations are
+\c{1.2.3~b.1-} and \c{1.2.3~-1}).
+
+Note also that per the Debian version specification, if upstream contains
+\c{:} and/or \c{-}, then epoch and/or revision must be specified explicitly,
+respectively. Note that the \c{bpkg} upstream version may not contain either.
+
+
+\h#bindist-mapping-fedora|Fedora Package Mapping|
+
+This section describes the distribution package mapping for Fedora and alike
+(Red Hat Enterprise Linux, Centos, etc).
+
+\h2#bindist-mapping-fedora-consume|Fedora Package Mapping for Consumption|
+
+A library in Fedora is normally split up into several packages: the shared
+library package (e.g., \c{libfoo}), the development files package (e.g.,
+\c{libfoo-devel}), the static library package (e.g., \c{libfoo-static}; may
+also be placed into the \c{-devel} package), the documentation files package
+(e.g., \c{libfoo-doc}), the debug symbols and source files packages (e.g.,
+\c{libfoo-debuginfo} and \c{libfoo-debugsource}), and the common or
+architecture-independent files (e.g., \c{libfoo-common}). All the packages
+except \c{-devel} are optional and there is quite a bit of variability. In
+particular, the \c{lib} prefix in \c{libfoo} is not a requirement (unlike in
+Debian) and is normally present only if upstream name has it (see some
+examples below).
+
+For application packages there is normally no \c{-devel} packages but
+\c{-debug*}, \c{-doc}, and \c{-common} are plausible.
+
+For mixed packages which include both applications and libraries, the shared
+library package normally has the \c{-libs} suffix (e.g., \c{foo-libs}).
+
+A package name may also include an upstream version based suffix if
+multiple versions of the package can be installed simultaneously (e.g.,
+\c{libfoo1.1} \c{libfoo1.1-devel}, \c{libfoo2} \c{libfoo2-devel}).
+
+Terminology-wise, the term \"base package\" (sometime also \"main package\")
+normally refers to either the application or shared library package (as
+decided by the package maintainer in the spec file) with the suffixed packages
+(\c{-devel}, \c{-doc}, etc) called \"subpackages\".
+
+Here are a few examples:
+
+\
+libpq libpq-devel
+
+zlib zlib-devel zlib-static
+
+catch-devel
+
+eigen3-devel eigen3-doc
+
+xerces-c xerces-c-devel xerces-c-doc
+
+libsigc++20 libsigc++20-devel libsigc++20-doc
+libsigc++30 libsigc++30-devel libsigc++30-doc
+
+icu libicu libicu-devel libicu-doc
+
+openssl openssl-libs openssl-devel openssl-static
+openssl1.1 openssl1.1-devel
+
+curl libcurl libcurl-devel
+
+sqlite sqlite-libs sqlite-devel sqlite-doc
+
+community-mysql community-mysql-libs community-mysql-devel
+community-mysql-common community-mysql-server
+
+ncurses ncurses-libs ncurses-c++-libs ncurses-devel ncurses-static
+
+keyutils keyutils-libs keyutils-libs-devel
+\
+
+Note that while we support arbitrary \c{-debug*} sub-package names for
+consumption, we only generate \c{<main-package>-debug*}.
+
+Based on that, our approach when trying to automatically map a \c{bpkg}
+library package name to Fedora package names is to go for the \c{-devel}
+package first and figure out the shared library package from that based on the
+fact that the \c{-devel} package should have the \c{==} dependency on the
+shared library package with the same version and its name should normally
+start with the \c{-devel} package's stem and potentially end with the
+\c{-libs} suffix. If failed to find the \c{-devel} package, we re-try but now
+using the \c{bpkg} project name instead of the package name (see, for example,
+\c{openssl}, \c{sqlite}).
+
+The format of the \c{fedora-name} (or alike) manifest value value is a
+comma-separated list of one or more package groups:
+
+\
+<package-group> [, <package-group>...]
+\
+
+Where each \c{<package-group>} is the space-separated list of one or more
+package names:
+
+\
+<package-name> [ <package-name>...]
+\
+
+All the packages in the group should belong to the same \"logical package\",
+such as \c{-devel}, \c{-doc}, \c{-common} packages. They normally have the
+same version.
+
+The first group is called the main group and the first package in the
+group is called the main package. Note that all the groups are consumed
+(installed) but only the main group is produced (packaged).
+
+(Note that above we use the term \"logical package\" instead of \"base
+package\" since the main package may not be the base package, for example
+being the \c{-libs} subpackage.)
+
+We allow/recommend specifying the \c{-devel} package instead of the main
+package for libraries (see \l{#manifest-package-type-language \c{type}} for
+details), seeing that we are capable of detecting the main package
+automatically (see above). If the library name happens to end with \c{-devel}
+(which poses an ambiguity), then the \c{-devel} package should be specified
+explicitly as the second package to disambiguate this situation.
+
+The Fedora package version has the \c{[<epoch>:]<version>-<release>} form (see
+Fedora Package Versioning Guidelines for details). If no explicit mapping
+to the \c{bpkg} version is specified with the \c{fedora-to-downstream-version}
+(or alike) manifest values or none match, then we fallback to using the
+\c{<version>} part as the \c{bpkg} version. If explicit mapping is specified,
+then we match it against the \c{[<epoch>:]<version>} parts ignoring
+\c{<release>}.
+
+
+\h2#bindist-mapping-fedora-produce|Fedora Package Mapping for Production|
+
+The same \c{fedora-name} (or alike) manifest values as used for consumption
+are also used to derive the package names for production except here we have
+the option to specify alternative non-native package names using the special
+\c{fedora_0-name} (or alike) value. If only the \c{-devel} package is
+specified, then the main package name is derived from that by removing the
+\c{-devel} suffix. Note that regardless of whether the main package name is
+specified or not, the \l{bpkg-pkg-bindist(1)} command may omit generating the
+main package for a binless library.
+
+The generated binary package version can be specified with the
+\c{fedora-version} (or alike) manifest value. If it's not specified, then the
+\c{upstream-version} is used if specified. Otherwise, the \c{bpkg} version
+is translated to the Fedora version as described next.
+
+To recap, a Fedora package version has the following form:
+
+\
+[<epoch>:]<version>-<release>
+\
+
+Where <release> has the following form:
+
+\
+<release-number>[.<distribution-tag>]
+\
+
+For details on the ordering semantics, see the Fedora Versioning Guidelines.
+While overall unsurprising, the only notable exceptions are \c{~}, which sorts
+before anything else and is commonly used for upstream pre-releases, and
+\c{^}, which sorts after anything else and is supposedly used for upstream
+post-release snapshots. For example, \c{0.1.0~alpha.1-1.fc35} sorts earlier
+than \c{0.1.0-1.fc35}.
+
+To recap, the bpkg version has the following form (see
+\l{#package-version Package Version} for details):
+
+\
+[+<epoch>-]<upstream>[-<prerel>][+<revision>]
+\
+
+Let's start with the case where neither distribution (\c{fedora-version}) nor
+upstream version (\c{upstream-version}) is specified and we need to derive
+everything from the \c{bpkg} version (what follows is as much description as
+rationale).
+
+\dl|
+
+\li|\c{<epoch>}
+
+ On one hand, if we keep our (as in, \c{bpkg}) epoch, it won't necessarily
+ match Fedora's native package epoch. But on the other it will allow our
+ binary packages from different epochs to co-exist. Seeing that this can be
+ easily overridden with a custom distribution version (see below), we keep
+ it.
+
+ Note that while the Fedora start/default epoch is 0, ours is 1 (we use the 0
+ epoch for stub packages). So we shift this value range.|
+
+\li|\c{<upstream>[-<prerel>]}
+
+ Our upstream version maps naturally to Fedora's \c{<version>}. That is, our
+ upstream version format/semantics is a subset of Fedora's \c{<version>}.
+
+ If this is a pre-release, then we could fail (that is, don't allow
+ pre-releases) but then we won't be able to test on pre-release packages, for
+ example, to make sure the name mapping is correct. Plus sometimes it's
+ useful to publish pre-releases. We could ignore it, but then such packages
+ will be indistinguishable from each other and the final release, which is
+ not ideal. On the other hand, Fedora has the mechanism (\c{~}) which is
+ essentially meant for this, so we use it. We will use \c{<prerel>} as is
+ since its format is the same as \c{<upstream>} and thus should map
+ naturally.|
+
+\li|\c{<revision>}
+
+ Similar to epoch, our revision won't necessarily match Fedora's native
+ package release number. But on the other hand it will allow us to establish a
+ correspondence between source and binary packages. Plus, upgrades between
+ binary package releases will be handled naturally. Also note that the
+ revision is mandatory in Fedora. Seeing that we allow overriding the
+ releases with a custom distribution version (see below), we use it.
+
+ Note that the Fedora start release number is 1 and our revision is 0. So we
+ shift this value range.
+
+ Also we automatically add the trailing distribution tag (\c{.fc35},
+ \c{.el8}, etc) to the Fedora release. The tag is deduced automatically
+ unless overridden on the command line (see \l{bpkg-pkg-bindist(1)} command
+ for details).
+
+||
+
+The next case to consider is when we have the upstream version
+(\c{upstream-version} manifest value). After some rumination it feels correct
+to use it in place of the \c{<epoch>-<upstream>} components in the above
+mapping (upstream version itself cannot have epoch). In other words, we will
+add the pre-release and revision components from the \c{bpkg} version. If this
+is not the desired semantics, then it can always be overridden with the
+distribution version (see below).
+
+Finally, we have the distribution version. The Fedora \c{<epoch>} and
+\c{<version>} components are straightforward: they should be specified by the
+distribution version as required. This leaves pre-release and release. It
+feels like in most cases we would want these copied over from the \c{bpkg}
+version automatically \- it's too tedious and error-prone to maintain them
+manually. However, we want the user to have the full override ability. So
+instead, if empty release is specified, as in \c{1.2.3-}, then we
+automatically add the \c{bpkg} revision. Similarly, if empty pre-release is
+specified, as in \c{1.2.3~}, then we add the \c{bpkg} pre-release. To add both
+automatically, we would specify \c{1.2.3~-} (other combinations are
+\c{1.2.3~b.1-} and \c{1.2.3~-1}). If specified, the release must not contain
+the distribution tag, since it is deduced automatically unless overridden on
+the command line (see \l{bpkg-pkg-bindist(1)} command for details). Also,
+since the release component is mandatory in Fedora, if it is omitted together
+with the separating dash we will add the release 1 automatically.
+
+Note also that per the RPM spec file format documentation neither version nor
+release components may contain \c{:} or \c{-}. Note that the \c{bpkg} upstream
+version may not contain either.
"
//@@ TODO items (grep).