// file      : bpkg/pkg-bindist.cli
// license   : MIT; see accompanying LICENSE file

include <map>;

include <bpkg/configuration.cli>;

"\section=1"
"\name=bpkg-pkg-bindist"
"\summary=generate binary distribution package"

namespace bpkg
{
  {
    "<options> <dir> <vars> <pkg>",

    "\h|SYNOPSIS|

     \c{\b{bpkg pkg-bindist}|\b{bindist} [\b{--output-root}|\b{-o} <dir>] [<options>] [<vars>] <pkg>...}

     \h|DESCRIPTION|

     The \cb{pkg-bindist} command generates a binary distribution package for
     the specified package. If additional packages are specified, then they
     are bundled in the same distribution package. All the specified packages
     must have been previously configured with \l{bpkg-pkg-build(1)} or
     \l{bpkg-pkg-configure(1)}. For some system package managers a directory
     for intermediate files and subdirectories as well as the resulting binary
     package may have to be specified explicitly with the
     \c{\b{--output-root}|\b{-o}} option.

     Underneath, this command roughly performs the following steps: First it
     installs the specified packages similar to the \l{bpkg-pkg-install(1)}
     command except that it may override the installation locations (via the
     \cb{config.install.*} variables) to match the distribution's layout. Then
     it generates any necessary distribution package metadata files based on
     the information from the package \cb{manifest} files. Finally, it invokes
     the distribution-specific command to produce the binary package. Unless
     overridden with the \cb{--architecture} and \cb{--distribution} options,
     the binary package is generated for the host architecture using the
     host's standard system package manager. Additional command line variables
     (<vars>, normally \cb{config.*}) can be passed to the build system during
     the installation step. See the following distribution-specific
     description sections below for details and invocation examples:

     \l{#debian  DEBIAN DESCRIPTION}

     \l{#fedora  FEDORA DESCRIPTION}

     \l{#archive ARCHIVE DESCRIPTION}

     The specified packages may have dependencies and the default behavior is
     to not bundle them but rather to specify them as dependencies in the
     corresponding distribution package metadata, if applicable. This default
     behavior can be overridden with the \cb{--recursive} option (see the
     option description for the available modes). Note, however, that
     dependencies that are satisfied by system packages are always specified
     as dependencies in the distribution package metadata (if applicable).
     "
  }

  // Place distribution-specific options into separate classes in case one day
  // we want to only pass their own options to each implementation.
  //
  class pkg_bindist_common_options: configuration_options
  {
    "\h|PKG-BINDIST OPTIONS|

     See the following sections below for distribution-specific options:

     \l{#debian-options  PKG-BINDIST DEBIAN OPTIONS}

     \l{#fedora-options  PKG-BINDIST FEDORA OPTIONS}

     \l{#archive-options PKG-BINDIST ARCHIVE OPTIONS}
    "

    string --distribution
    {
      "<name>",
      "Alternative system/distribution package manager to generate the binary
       package for. The valid <name> values are \cb{debian} (Debian and alike,
       such as Ubuntu, etc), \cb{fedora} (Fedora and alike, such as RHEL,
       CentOS, etc), and \cb{archive} (installation archive on any operating
       system). Note that some package managers may only be supported when
       running on certain host operating systems."
    }

    string --architecture
    {
      "<name>",
      "Alternative architecture to generate the binary package for. The
       valid <name> values are system/distribution package manager-specific.
       If unspecified, the host architecture is used."
    }

    string --recursive = "none"
    {
      "<mode>",
      "Bundle or generate dependencies of the specified packages. The <mode>
       value can be either \cb{auto}, in which case only the required files
       from each dependency package are bundled, \cb{full}, in which case
       all the files are bundled, or \cb{separate}, in which case a separate
       binary package is generated for each non-system dependency. It can
       also be \cb{none} which is equivalent to not specifying this option
       (primarily useful for overriding a previously-specified value).

       Specifically, in the \cb{auto} mode any required files, such as shared
       libraries, are pulled implicitly by the \cb{install} build system
       operation, for example, as part of installing an executable from one of
       the specified packages. In contrast, in the \cb{full} mode, each
       dependency package is installed explicitly and completely, as if they
       were specified as additional package on the command line. The
       \cb{separate} mode is equivalent to invoking the \cb{pkg-bindist}
       command on each dependency package. See also the \cb{--private} option."
    }

    bool --private
    {
      "Enable the private installation subdirectory functionality using the
       package name as the private subdirectory. This is primarily useful when
       bundling dependencies, such as shared libraries, of an executable that
       is being installed into a shared location, such as \cb{/usr/}.  See the
       \cb{config.install.private} configuration variable documentation in the
       build system manual for details. This option only makes sense together
       with the \cb{--recursive} option \cb{auto} and \cb{full} modes."
    }

    dir_path --output-root|-o
    {
      "<dir>",
      "Directory for intermediate files and subdirectories as well as the
       resulting binary package. Note that this option may be required for
       some system package managers and may not be specified for others."
    }

    bool --wipe-output
    {
      "Wipe the output root directory (either specified with \ci{--output-root}
       or system package manager-specific) clean before using it to generate
       the binary package."
    }

    bool --keep-output
    {
      "Keep intermediate files in the output root directory (either specified
       with \ci{--output-root} or system package manager-specific) that were
       used to generate the binary package. This is primarily useful for
       troubleshooting."
    }

    bool --allow-dependent-config
    {
      "Allow configuration that is imposed by dependent packages. Normally
       this is undesirable because the resulting binary packages become
       configured specificaly for particular dependent packages."
    }

    string --os-release-id
    {
      "<v>",
      "Override the \cb{ID} component in \cb{os-release(5)} or equivalent.
       Note that unlike the rest of the \cb{--os-release-*} options, this
       option suppresses automatic detection of the host operating system
       information."
    }

    string --os-release-version-id
    {
      "<v>",
      "Override the \cb{VERSION_ID} component in \cb{os-release(5)} or
       equivalent."
    }

    string --os-release-name
    {
      "<v>",
      "Override the \cb{NAME} component in \cb{os-release(5)} or equivalent."
    }
  };

  class pkg_bindist_debian_options
  {
    "\h#debian|DEBIAN DESCRIPTION|

     The Debian binary packages are generated by producing the standard
     \cb{debian/control}, \cb{debian/rules}, and other package metadata files
     and then invoking \cb{dpkg-buildpackage(1)} to build the binary package
     from that. In particular, the \cb{debian/rules} implemenation is based on
     the \cb{dh(1)} command sequencer. While this approach is normally used to
     build packages from source, this implementation \"pretends\" that this is
     what's happening by overriding a number of \cb{dh} targets to invoke the
     \cb{build2} build system on the required packages directly in their
     \cb{bpkg} configuration locations.

     The \cb{dpkg-dev} (or \cb{build-essential}) and \cb{debhelper} Debian
     packages must be installed before invocation. Typical invocation:

     \
     bpkg build libhello
     bpkg test libhello
     bpkg bindist -o /tmp/output/ libhello
     \

     Unless the \cb{--recursive} option \cb{auto} or \cb{full} modes are
     specified, dependencies of the specified package are translated to
     dependencies in the resulting binary package using names and versions
     that refer to packages that would be generated by the \cb{pkg-bindist}
     command (called \"non-native\" packages). If instead you would like
     certain dependencies to refer to binary packages provided by the
     distribution (called \"native\" packages), then you need to arrange for
     them to be built as system (see \l{bpkg-pkg-build(1)} for details). For
     example, if our \cb{libhello} has a dependency on \cb{libsqlite3} and we
     would like the binary package for \cb{libhello} to refer to
     \cb{libsqlite3} from Debian (or alike), then the \cb{pkg-build} command
     would need to be (\cb{--sys-install} is optional):

     \
     bpkg build --sys-install libhello ?sys:libsqlite3
     \

     Such a package with native dependencies can then be installed (including
     any missing native dependencies) using the \cb{apt} or \cb{apt-get}
     \cb{install} command. Note that the specified \cb{.deb} file must include
     a directory separator (\c{/}) in order to be recognized as a file rather
     than a package name. For example:

     \
     sudo apt-get install ./libhello_1.2.3-0~debian11_amd64.deb \
                          ./libhello-dev_1.2.3-0~debian11_amd64.deb
     \

     See \l{bpkg#bindist-mapping-debian-produce Debian Package Mapping for
     Production} for details on \cb{bpkg} to Debian package name and version
     mapping.
     "

    "\h#debian-options|PKG-BINDIST DEBIAN OPTIONS|"

    bool --debian-prepare-only
    {
      "Prepare all the package metadata files (\cb{control}, \cb{rules}, etc)
       but do not invoke \cb{dpkg-buildpackage} to generate the binary
       package, printing its command line instead unless requested to be
       quiet. Implies \cb{--keep-output}."
    }

    string --debian-buildflags = "assign"
    {
      "<mode>",
      "Package build flags (\cb{dpkg-buildflags}) usage mode. Valid <mode>
       values are \cb{assign} (use the build flags instead of configured),
       \cb{append} (use the build flags in addition to configured, putting
       them last), \cb{prepend} (use the build flags in addition to
       configured, putting them first), and \cb{ignore} (ignore build
       flags). The default mode is \cb{assign}. Note that compiler mode
       options, if any, are used as configured."
    }

    strings --debian-maint-option
    {
      "<o>",
      "Alternative options to specify in the \cb{DEB_BUILD_MAINT_OPTIONS}
       variable of the \cb{rules} file. To specify multiple maintainer options
       repeat this option and/or specify them as a single value separated
       with spaces."
    }

    strings --debian-build-option
    {
      "<o>",
      "Additional option to pass to the \cb{dpkg-buildpackage} program. Repeat
       this option to specify multiple build options."
    }

    string --debian-build-meta
    {
      "<data>",
      "Alternative or additional build metadata to include in the binary
       package version. If the specified value starts/ends with \cb{+} then
       the value (with \cb{+} removed) is added after/before the default
       metadata. Otherwise it is used as is instead of the default metadata.
       If empty value is specified, then no build metadata is included. By
       default, the build metadata is the \cb{ID} and \cb{VERSION_ID}
       components from \cb{os-release(5)}, for example, \cb{debian10} in
       version \cb{1.2.3-0~debian10}. See also \cb{--os-release-*}."
    }

    string --debian-section
    {
      "<v>",
      "Alternative \cb{Section} \cb{control} file field value for the main
       binary package. The default is either \cb{libs} or \cb{devel},
       depending on the package type."
    }

    string --debian-priority
    {
      "<v>",
      "Alternative \cb{Priority} \cb{control} file field value. The default
       is \cb{optional}."
    }

    string --debian-maintainer
    {
      "<v>",
      "Alternative \cb{Maintainer} \cb{control} file field value. The
       default is the \cb{package-email} value from package \cb{manifest}."
    }

    string --debian-architecture
    {
      "<v>",
      "Alternative \cb{Architecture} \cb{control} file field value for
       the main binary package, normally \cb{all} (architecture-independent).
       The default is \cb{any} (architecture-dependent)."
    }

    string --debian-main-langdep
    {
      "<v>",
      "Override the language runtime dependencies (such as \cb{libc6},
       \cb{libstdc++6}, etc) in the \cb{Depends} \cb{control} file field
       value of the main binary package."
    }

    string --debian-dev-langdep
    {
      "<v>",
      "Override the language runtime dependencies (such as \cb{libc-dev},
       \cb{libstdc++-dev}, etc) in the \cb{Depends} \cb{control} file field
       value of the development (\cb{-dev}) binary package."
    }

    string --debian-main-extradep
    {
      "<v>",
      "Extra dependencies to add to the \cb{Depends} \cb{control} file field
       value of the main binary package."
    }

    string --debian-dev-extradep
    {
      "<v>",
      "Extra dependencies to add to the \cb{Depends} \cb{control} file field
       value of the development (\cb{-dev}) binary package."
    }
  };

  class pkg_bindist_fedora_options
  {
    "\h#fedora|FEDORA DESCRIPTION|

     The Fedora binary packages are generated by producing the standard RPM
     spec file and then invoking \cb{rpmbuild(8)} to build the binary package
     from that. While this approach is normally used to build packages from
     source, this implementation \"pretends\" that this is what's happening by
     overriding a number of RPM spec file sections to invoke the \cb{build2}
     build system on the required packages directly in their \cb{bpkg}
     configuration locations.

     The \cb{rpmdevtools} Fedora package must be installed before invocation.
     Typical invocation:

     \
     bpkg build libhello
     bpkg test libhello
     bpkg bindist libhello
     \

     The resulting binary packages are placed into the standard \cb{rpmbuild}
     output directory (normally \c{\b{~/rpmbuild/RPMS/}\i{arch}\b{/}}).

     Unless the \cb{--recursive} option \cb{auto} or \cb{full} modes are
     specified, dependencies of the specified package are translated to
     dependencies in the resulting binary package using names and versions
     that refer to packages that would be generated by the \cb{pkg-bindist}
     command (called \"non-native\" packages). If instead you would like
     certain dependencies to refer to binary packages provided by the
     distribution (called \"native\" packages), then you need to arrange for
     them to be built as system (see \l{bpkg-pkg-build(1)} for details). For
     example, if our \cb{libhello} has a dependency on \cb{libsqlite3} and we
     would like the binary package for \cb{libhello} to refer to
     \cb{sqlite-libs} from Fedora (or alike), then the \cb{pkg-build} command
     would need to be (\cb{--sys-install} is optional):

     \
     bpkg build --sys-install libhello ?sys:libsqlite3
     \

     Such a package with native dependencies can then be installed (including
     any missing native dependencies) using the \cb{dnf install} command.
     For example:

     \
     sudo dnf install libhello-1.2.3-1.fc35.x86_64.rpm \
                      libhello-devel-1.2.3-1.fc35.x86_64.rpm
     \

     See \l{bpkg#bindist-mapping-fedora-produce Fedora Package Mapping for
     Production} for details on \cb{bpkg} to Fedora package name and version
     mapping.
     "

    "\h#fedora-options|PKG-BINDIST FEDORA OPTIONS|"

    bool --fedora-prepare-only
    {
      "Prepare the RPM spec file but do not invoke \cb{rpmbuild} to generate
       the binary package, printing its command line instead unless requested
       to be quiet."
    }

    string --fedora-buildflags = "assign"
    {
      "<mode>",
      "Package build flags (\cb{%{build_*flags\}} macros) usage mode. Valid
       <mode> values are \cb{assign} (use the build flags instead of
       configured), \cb{append} (use the build flags in addition to
       configured, putting them last), \cb{prepend} (use the build flags in
       addition to configured, putting them first), and \cb{ignore} (ignore
       build flags). The default mode is \cb{assign}. Note that compiler mode
       options, if any, are used as configured."
    }

    strings --fedora-build-option
    {
      "<o>",
      "Additional option to pass to the \cb{rpmbuild} program. If specified,
       these options must be consistent with the query options
       (\cb{--fedora-query-option}) to result in identical macro
       expansions. Repeat this option to specify multiple build options."
    }

    strings --fedora-query-option
    {
      "<o>",
      "Additional option to pass to the \cb{rpm} program. This program is used
       to query RPM macro values which affect the binary package. If
       specified, these options must be consistent with the build options
       (\cb{--fedora-build-option}) to result in identical macro expansions.
       Repeat this option to specify multiple query options."
    }

    string --fedora-dist-tag
    {
      "<tag>",
      "Alternative or additional distribution tag to use in the binary package
       release. If the specified value starts/ends with \cb{+} then the value
       (with \cb{+} removed) is added after/before the default distribution
       tag. Otherwise it is used as is instead of the default tag. If empty
       value is specified, then no distribution tag is included. The default
       is a value that identifies the distribution being used to build the
       package, for example, \cb{fc35} for Fedora 35 or \cb{el8} for RHEL 8."
    }

    string --fedora-packager
    {
      "<v>",
      "Alternative \cb{Packager} RPM spec file directive value. The default is
       the \cb{package-email} value from package \cb{manifest}. If empty value
       is specified, then the \cb{Packager} directive is omitted from the spec
       file."
    }

    string --fedora-build-arch
    {
      "<v>",
      "\cb{BuildArch} RPM spec file directive value for the main binary
       package, normally \cb{noarch} (architecture-independent). By default
       the directive is omitted, assuming that the package is
       architecture-dependent."
    }

    strings --fedora-main-langreq
    {
      "<v>",
      "Override the language runtime dependencies (such as \cb{glibc},
       \cb{libstdc++}, etc) of the main binary package by replacing the
       corresponding \cb{Requires} RPM spec file directives. If empty value is
       specified then no language runtime dependencies are specified. Repeat
       this option to specify multiple language runtime dependencies."
    }

    strings --fedora-devel-langreq
    {
      "<v>",
      "Override the language runtime dependencies (such as \cb{glibc-devel},
       \cb{libstdc++-devel}, etc) of the development (\cb{-devel}) binary
       package by replacing the corresponding \cb{Requires} RPM spec file
       directives. If empty value is specified then no language runtime
       dependencies are specified. Repeat this option to specify multiple
       language runtime dependencies."
    }

    strings --fedora-stat-langreq
    {
      "<v>",
      "Override the language runtime dependencies (such as \cb{glibc-static},
       \cb{libstdc++-static}, etc) of the static libraries (\cb{-static})
       binary package by replacing the corresponding \cb{Requires} RPM spec
       file directives. If empty value is specified then no language runtime
       dependencies are specified. Repeat this option to specify multiple
       language runtime dependencies."
    }

    strings --fedora-main-extrareq
    {
      "<v>",
      "Extra dependency to add to the main binary package as an additional
       \cb{Requires} RPM spec file directive. Repeat this option to specify
       multiple extra dependencies."
    }

    strings --fedora-devel-extrareq
    {
      "<v>",
      "Extra dependency to add to the development (\cb{-devel}) binary package
       as an additional \cb{Requires} RPM spec file directive. Repeat this
       option to specify multiple extra dependencies."
    }

    strings --fedora-stat-extrareq
    {
      "<v>",
      "Extra dependency to add to the static libraries (\cb{-static}) binary
       package as an additional \cb{Requires} RPM spec file directive. Repeat
       this option to specify multiple extra dependencies."
    }
  };

  class pkg_bindist_archive_options
  {
    "\h#archive|ARCHIVE DESCRIPTION|

     The installation archive binary packages are generated by invoking the
     \cb{build2} build system on the required packages directly in their
     \cb{bpkg} configuration locations and installing them into the binary
     package directory using the \cb{config.install.chroot} mechanism. Then
     this directory is packaged with \cb{tar} or \cb{zip} to produce one or
     more binary package archives.

     The generation of installation archive packages is never the default and
     should be requested explicitly with the \cb{--distribution=archive}
     option. The installation directory layout and the package archives to
     generate can be specified with the \cb{--archive-install-*} and
     \cb{--archive-type} options (refer to their documentation for defaults).

     The binary package directory (the top-level directory inside the
     archive) as well as the archive file base (the file name without
     the extension) are the same and have the following form:

     \c{\i{package}-\i{version}-\i{build_metadata}}

     Where \ci{package} is the package name and \ci{version} is the \cb{bpkg}
     package version. Unless overridden with the \cb{--archive-build-meta}
     option, \ci{build_metadata} has the following form:

     \c{\i{cpu}-\i{os}[-\i{langrt}...]}

     Where \ci{cpu} is the target CPU (for example, \cb{x86_64} or
     \cb{aarch64}; omitted if \cb{--archive-no-cpu} is specified), \ci{os} is
     the \cb{ID} and \cb{VERSION_ID} components from \cb{os-release(5)} (or
     equivalent, for example, \cb{debian11} or \cb{windows10}; omitted if
     \cb{--archive-no-os} is specified), and \ci{langrt} are the language
     runtimes as mapped by the \cb{--archive-lang*} options (for example,
     \cb{gcc12} or \cb{msvc17.4}).

     For example, given the following invocation on Debian 11 running on
     \cb{x86_64}:

     \
     bpkg build libhello
     bpkg test libhello
     bpkg bindist              \
       -o /tmp/output/         \
       --distribution=archive  \
       --archive-lang cc=gcc12 \
       libhello
     \

     We will end up with the package archive in the following form:

     \
     libhello-1.2.3-x86_64-debian11-gcc12.tar.xz
     \

     The recommended language runtime id format is the runtime name followed
     by the version, for example, \cb{gcc12} or \cb{msvc17.4}. Note that its
     purpose is not to provide a precise specification of requirements but
     rather to help the user of a binary package to pick the appropriate
     variant. Refer to the \cb{--archive-lang*} options documentation for
     details on the mapping semantics.

     Instead of mapping languages individually you can specify entire build
     metadata as a single value with the \cb{--archive-build-meta} (it is also
     possible to add additional metadata; see the option documentation for
     details). For example:

     \
     bpkg bindist                              \
       -o /tmp/output/                         \
       --distribution=archive                  \
       --archive-build-meta=x86_64-linux-glibc
       libhello
     \

     This will produce the package archive in the following form:

     \
     libhello-1.2.3-x86_64-linux-glibc.tar.xz
     \

     To install the binary package from archive simply unpack it using
     \cb{tar} or \cb{zip}. You can use the \cb{--strip-components} \cb{tar}
     option to remove the top-level package directory (the same can be
     achieved for \cb{zip} archives by using \cb{bsdtar} on Windows). For
     example, to unpack the package contents so that they end up in
     \cb{/usr/local/}:

     \
     sudo tar -xf libhello-1.2.3-x86_64-debian11-gcc12.tar.xz \
       -C / --strip-components=1
     \

     If you expect the binary package to be unpacked into a directory other
     than its original installation directory (\cb{--archive-install-root}),
     then it's recommended to make it relocatable by specifying the
     \cb{config.install.relocatable=true} configuration variable. For example:

     \
     bpkg bindist                      \
       ...                             \
       config.install.relocatable=true \
       libhello
     \

     Note that not all source packages support relocatable installation (see
     \l{b#install-reloc Rolocatable Installation} for details).

     Another mechanism that can useful when generating archive packages is the
     ability to filter the files being installed. This, for example, can be
     used to create binary packages that don't contain any development-related
     files. See \l{b#install-filter Installation Filtering} for details. See
     also the \cb{--archive-split} option.

     The installation archive package can be generated for a target other than
     the host by specifying the target triplet with the \cb{--architecture}
     option. In this case the \cb{bpkg} configuration is assumed to be
     appropriately configured for cross-compiling to the specified target. You
     will also need to explicitly specify the \cb{--archive-install-root}
     option (or \cb{--archive-install-config}) as well as the
     \cb{--os-release-id} option (and likely want to specify other
     \cb{--os-release-*} options). For example, for cross-compiling from Linux
     to Windows using the MinGW GCC toolchain:

     \
     bpkg bindist                        \
       --distribution=archive            \
       --architecture=x86_64-w64-mingw32 \
       --os-release-id=windows           \
       --os-release-name=Windows         \
       --os-release-version-id=10        \
       --archive-install-root /          \
       --archive-lang cc=mingw_w64_gcc12 \
       ...
     \
     "

    "\h#archive-options|PKG-BINDIST ARCHIVE OPTIONS|"

    bool --archive-prepare-only
    {
      "Prepare all the package contents but do not create the binary package
       archive, printing its directory instead unless requested to be quiet.
       Implies \cb{--keep-output}."
    }

    strings --archive-type
    {
      "<ext>",
      "Archive type to create specified as a file extension, for example,
       \cb{tar.xz}, \cb{tar.gz}, \cb{tar}, \cb{zip}. Repeat this option to
       generate multiple archive types. If unspecified, then a default type
       appropriate for the target operating system is used, currently \cb{zip}
       for Windows and \cb{tar.xz} for POSIX. Note, however, that these
       defaults may change in the future."
    }

    std::multimap<string, string> --archive-lang
    {
      "<ln>=<rt>",
      "Map interface language name <ln> to runtime id <rt>. If no mapping is
       found for an interface language in this map, then fallback to the
       \cb{--archive-lang-impl} map. If still no mapping is found, then
       fail. If the information about an interface language is unimportant and
       should be ignored, then empty runtime id can be specified. Note that
       the mapping specified with this option is only considered if the
       package type is a library (for other package types all languages used
       are implementation). Note also that multiple runtime ids specified for
       the same language are combined except for an empty id, which is treated
       as a request to clear previous entries."
    }

    std::multimap<string, string> --archive-lang-impl
    {
      "<ln>=<rt>",
      "Map implementation language name <ln> to runtime id <rt>. If no mapping
       is found for an implementation language in this map, then assume
       the information about this implementation language is unimportant
       and ignore it (examples of such cases include static linking as well
       as a language runtime that is always present). See \cb{--archive-lang}
       for background."
    }

    bool --archive-no-cpu
    {
      "Assume the package is CPU architecture-independent and omit it from
       the binary package directory name and archive file base."
    }

    bool --archive-no-os
    {
      "Assume the package is operating system-independent and omit it from
       the binary package directory name and archive file base."
    }

    string --archive-build-meta
    {
      "<data>",
      "Alternative or additional build metadata to include after the version
       in the binary package directory and file names. If the specified value
       starts/ends with \cb{+} then the value (with \cb{+} removed) is added
       after/before the default metadata. Otherwise it is used as is instead
       of the default metadata. If empty value is specified, then no build
       metadata is included."
    }

    dir_path --archive-install-root
    {
      "<d>",
      "Alternative installation root directory. The default is \cb{/usr/local/}
       on POSIX and \c{\b{C:\\}\i{project}\b{\\}} on Windows, where
       \ci{project} is the \l{bpkg#manifest-package-project \cb{project}}
       package manifest value."
    }

    bool --archive-install-config
    {
      "Use the installation directory layout (\cb{config.install.*} variables)
       as configured instead of overriding them with defaults appropriate for
       the target operating system. Note that this includes
       \cb{config.install.private} and \cb{config.bin.rpath} if needed for a
       private installation. Note also that the \cb{config.install.root} value
       is still overridden with the \cb{--archive-install-root} option value
       if specified."
    }

    std::map<string, string> --archive-split
    {
      "<key>=<filt>",
      "Split the installation into multiple binary packages. Specifically,
       for each <key>=<filt> pair, perform the \cb{install} operation with
       \c{\b{config.install.filter=}\i{filt}} and package the resulting files
       as \ci{package-key-version-build_metadata} omitting the \ci{-key} part
       if <key> is empty. Note that wildcard patterns in <filt> must be
       quoted. See \l{b#install-filter Installation Filtering} for background."
    }
  };

  "
   \h|STRUCTURED RESULT|

   Instead of printing to \cb{stderr} the list of generated binary packages in
   a format more suitable for human consumption, the \cb{pkg-bindist} command
   can be instructed to write it to \cb{stdout} in a machine-readable form by
   specifying the \cb{--structured-result} option. Currently, the only
   recognized format value for this option is \cb{json} with the output being
   a JSON object that is a serialized representation of the following C++
   struct \cb{bindist_result}:

   \
   struct os_release
   {
     string           name_id;     // ID
     vector<string>   like_ids;    // ID_LIKE
     optional<string> version_id;  // VERSION_ID
     optional<string> variant_id;  // VARIANT_ID

     optional<string> name;              // NAME
     optional<string> version_codename;  // VERSION_CODENAME
     optional<string> variant;           // VARIANT
   };

   struct file
   {
     string type;
     string path;
     optional<string> system_name;
   };

   struct package
   {
     string           name;
     string           version;
     optional<string> system_version;
     vector<file>     files;
   };

   struct bindist_result
   {
     string           distribution;     // --distribution or auto-detected
     string           architecture;     // --architecture or auto-detected
     os_release       os_release;       // --os-release-* or auto-detected
     optional<string> recursive;        // --recursive
     bool             private;          // --private
     bool             dependent_config; // See --allow-dependent-config

     package          package;
     vector<package>  dependencies;     // Only in --recursive=separate
   };
   \

   For example:

   \
   {
     \"distribution\": \"debian\",
     \"architecture\": \"amd64\",
     \"os_release\": {
       \"name_id\": \"debian\",
       \"version_id\": \"11\",
       \"name\": \"Debian GNU/Linux\"
     },
     \"package\": {
       \"name\": \"libfoo\",
       \"version\": \"2.5.0-b.23\",
       \"system_version\": \"2.5.0~b.23-0~debian11\",
       \"files\": [
         {
           \"type\": \"main.deb\",
           \"path\": \"/tmp/libfoo_2.5.0~b.23-0~debian11_amd64.deb\",
           \"system_name\": \"libfoo\"
         },
         {
           \"type\": \"dev.deb\",
           \"path\": \"/tmp/libfoo-dev_2.5.0~b.23-0~debian11_amd64.deb\",
           \"system_name\": \"libfoo-dev\"
         },
         ...
       ]
     }
   }
   \

   See the JSON OUTPUT section in \l{bpkg-common-options(1)} for details on
   the overall properties of this format and the semantics of the \cb{struct}
   serialization.

   The \cb{file::type} member is a distribution-specific value that classifies
   the file. For the \cb{debian} distribution the possible values are
   \cb{main.deb}, \cb{dev.deb}, \cb{doc.deb}, \cb{common.deb},
   \cb{dbgsym.deb}, \cb{changes} (\cb{.changes} file), and \cb{buildid}
   (\cb{.buildid} file); see \l{bpkg#bindist-mapping-debian-produce Debian
   Package Mapping for Production} for background. For the \cb{fedora}
   distribution the possible values are \cb{main.rpm}, \cb{devel.rpm},
   \cb{static.rpm}, \cb{doc.rpm}, \cb{common.rpm}, and \cb{debuginfo.rpm}; see
   \l{bpkg#bindist-mapping-fedora-produce Fedora Package Mapping for
   Production} for background. For the \cb{archive} distribution this is the
   archive type (\cb{--archive-type}), for example, \cb{tar.xz} or \cb{zip},
   potentially prefixed with \ci{key} if the \cb{--archive-split}
   functionality is used, for example, \cb{dev.tar.xz}.

   The \cb{package::system_version} and/or \cb{file::system_name} members are
   absent if not applicable to the distribution. The \cb{file::system_name}
   member is also absent if the file is not a binary package (for example,
   \cb{.changes} and \cb{.buildid} files in the \cb{debian} distribution).
  "

  // NOTE: remember to add the corresponding `--class-doc ...=exclude-base`
  //       (both in bpkg/ and doc/) if adding a new base class.
  //
  class pkg_bindist_options: pkg_bindist_common_options,
                             pkg_bindist_debian_options,
                             pkg_bindist_fedora_options,
                             pkg_bindist_archive_options {};

  "
   \h|DEFAULT OPTIONS FILES|

   See \l{bpkg-default-options-files(1)} for an overview of the default
   options files. For the \cb{pkg-bindist} command the search start
   directory is the configuration directory. The following options files are
   searched for in each directory and, if found, loaded in the order listed:

   \
   bpkg.options
   bpkg-pkg-bindist.options
   \

   The following \cb{pkg-bindist} command options cannot be specified in the
   default options files:

   \
   --directory|-d
   \
  "
}
