diff options
author | Karen Arutyunov <karen@codesynthesis.com> | 2024-05-22 16:02:45 +0300 |
---|---|---|
committer | Karen Arutyunov <karen@codesynthesis.com> | 2024-05-22 16:02:45 +0300 |
commit | d70180e831f50d199da619ddec36ef7c70d93122 (patch) | |
tree | 69878ac9a738791976c43f20db827dfd7afeac79 /bpkg/pkg-bindist-options.cxx | |
parent | 2d2dc7ccb2fff55fea9d5a87e98411d04f175f16 (diff) |
Make changes required for CI
Diffstat (limited to 'bpkg/pkg-bindist-options.cxx')
-rw-r--r-- | bpkg/pkg-bindist-options.cxx | 3081 |
1 files changed, 3081 insertions, 0 deletions
diff --git a/bpkg/pkg-bindist-options.cxx b/bpkg/pkg-bindist-options.cxx new file mode 100644 index 0000000..cceb8b7 --- /dev/null +++ b/bpkg/pkg-bindist-options.cxx @@ -0,0 +1,3081 @@ +// -*- C++ -*- +// +// This file was generated by CLI, a command line interface +// compiler for C++. +// + +// Begin prologue. +// +#include <bpkg/types-parsers.hxx> +// +// End prologue. + +#include <bpkg/pkg-bindist-options.hxx> + +#include <map> +#include <set> +#include <string> +#include <vector> +#include <utility> +#include <ostream> +#include <sstream> +#include <cstring> + +namespace bpkg +{ + namespace cli + { + template <typename X> + struct parser + { + static void + parse (X& x, bool& xs, scanner& s) + { + using namespace std; + + const char* o (s.next ()); + if (s.more ()) + { + string v (s.next ()); + istringstream is (v); + if (!(is >> x && is.peek () == istringstream::traits_type::eof ())) + throw invalid_value (o, v); + } + else + throw missing_value (o); + + xs = true; + } + + static void + merge (X& b, const X& a) + { + b = a; + } + }; + + template <> + struct parser<bool> + { + static void + parse (bool& x, bool& xs, scanner& s) + { + const char* o (s.next ()); + + if (s.more ()) + { + const char* v (s.next ()); + + if (std::strcmp (v, "1") == 0 || + std::strcmp (v, "true") == 0 || + std::strcmp (v, "TRUE") == 0 || + std::strcmp (v, "True") == 0) + x = true; + else if (std::strcmp (v, "0") == 0 || + std::strcmp (v, "false") == 0 || + std::strcmp (v, "FALSE") == 0 || + std::strcmp (v, "False") == 0) + x = false; + else + throw invalid_value (o, v); + } + else + throw missing_value (o); + + xs = true; + } + + static void + merge (bool& b, const bool&) + { + b = true; + } + }; + + template <> + struct parser<std::string> + { + static void + parse (std::string& x, bool& xs, scanner& s) + { + const char* o (s.next ()); + + if (s.more ()) + x = s.next (); + else + throw missing_value (o); + + xs = true; + } + + static void + merge (std::string& b, const std::string& a) + { + b = a; + } + }; + + template <typename X> + struct parser<std::pair<X, std::size_t> > + { + static void + parse (std::pair<X, std::size_t>& x, bool& xs, scanner& s) + { + x.second = s.position (); + parser<X>::parse (x.first, xs, s); + } + + static void + merge (std::pair<X, std::size_t>& b, const std::pair<X, std::size_t>& a) + { + b = a; + } + }; + + template <typename X> + struct parser<std::vector<X> > + { + static void + parse (std::vector<X>& c, bool& xs, scanner& s) + { + X x; + bool dummy; + parser<X>::parse (x, dummy, s); + c.push_back (x); + xs = true; + } + + static void + merge (std::vector<X>& b, const std::vector<X>& a) + { + b.insert (b.end (), a.begin (), a.end ()); + } + }; + + template <typename X, typename C> + struct parser<std::set<X, C> > + { + static void + parse (std::set<X, C>& c, bool& xs, scanner& s) + { + X x; + bool dummy; + parser<X>::parse (x, dummy, s); + c.insert (x); + xs = true; + } + + static void + merge (std::set<X, C>& b, const std::set<X, C>& a) + { + b.insert (a.begin (), a.end ()); + } + }; + + template <typename K, typename V, typename C> + struct parser<std::map<K, V, C> > + { + static void + parse (std::map<K, V, C>& m, bool& xs, scanner& s) + { + const char* o (s.next ()); + + if (s.more ()) + { + std::size_t pos (s.position ()); + std::string ov (s.next ()); + std::string::size_type p = ov.find ('='); + + K k = K (); + V v = V (); + std::string kstr (ov, 0, p); + std::string vstr (ov, (p != std::string::npos ? p + 1 : ov.size ())); + + int ac (2); + char* av[] = + { + const_cast<char*> (o), + 0 + }; + + bool dummy; + if (!kstr.empty ()) + { + av[1] = const_cast<char*> (kstr.c_str ()); + argv_scanner s (0, ac, av, false, pos); + parser<K>::parse (k, dummy, s); + } + + if (!vstr.empty ()) + { + av[1] = const_cast<char*> (vstr.c_str ()); + argv_scanner s (0, ac, av, false, pos); + parser<V>::parse (v, dummy, s); + } + + m[k] = v; + } + else + throw missing_value (o); + + xs = true; + } + + static void + merge (std::map<K, V, C>& b, const std::map<K, V, C>& a) + { + for (typename std::map<K, V, C>::const_iterator i (a.begin ()); + i != a.end (); + ++i) + b[i->first] = i->second; + } + }; + + template <typename K, typename V, typename C> + struct parser<std::multimap<K, V, C> > + { + static void + parse (std::multimap<K, V, C>& m, bool& xs, scanner& s) + { + const char* o (s.next ()); + + if (s.more ()) + { + std::size_t pos (s.position ()); + std::string ov (s.next ()); + std::string::size_type p = ov.find ('='); + + K k = K (); + V v = V (); + std::string kstr (ov, 0, p); + std::string vstr (ov, (p != std::string::npos ? p + 1 : ov.size ())); + + int ac (2); + char* av[] = + { + const_cast<char*> (o), + 0 + }; + + bool dummy; + if (!kstr.empty ()) + { + av[1] = const_cast<char*> (kstr.c_str ()); + argv_scanner s (0, ac, av, false, pos); + parser<K>::parse (k, dummy, s); + } + + if (!vstr.empty ()) + { + av[1] = const_cast<char*> (vstr.c_str ()); + argv_scanner s (0, ac, av, false, pos); + parser<V>::parse (v, dummy, s); + } + + m.insert (typename std::multimap<K, V, C>::value_type (k, v)); + } + else + throw missing_value (o); + + xs = true; + } + + static void + merge (std::multimap<K, V, C>& b, const std::multimap<K, V, C>& a) + { + for (typename std::multimap<K, V, C>::const_iterator i (a.begin ()); + i != a.end (); + ++i) + b.insert (typename std::multimap<K, V, C>::value_type (i->first, + i->second)); + } + }; + + template <typename X, typename T, T X::*M> + void + thunk (X& x, scanner& s) + { + parser<T>::parse (x.*M, s); + } + + template <typename X, bool X::*M> + void + thunk (X& x, scanner& s) + { + s.next (); + x.*M = true; + } + + template <typename X, typename T, T X::*M, bool X::*S> + void + thunk (X& x, scanner& s) + { + parser<T>::parse (x.*M, x.*S, s); + } + } +} + +#include <map> + +namespace bpkg +{ + // pkg_bindist_common_options + // + + pkg_bindist_common_options:: + pkg_bindist_common_options () + : distribution_ (), + distribution_specified_ (false), + architecture_ (), + architecture_specified_ (false), + recursive_ ("none"), + recursive_specified_ (false), + private__ (), + output_root_ (), + output_root_specified_ (false), + wipe_output_ (), + keep_output_ (), + allow_dependent_config_ (), + os_release_id_ (), + os_release_id_specified_ (false), + os_release_version_id_ (), + os_release_version_id_specified_ (false), + os_release_name_ (), + os_release_name_specified_ (false) + { + } + + bool pkg_bindist_common_options:: + parse (int& argc, + char** argv, + bool erase, + ::bpkg::cli::unknown_mode opt, + ::bpkg::cli::unknown_mode arg) + { + ::bpkg::cli::argv_scanner s (argc, argv, erase); + bool r = _parse (s, opt, arg); + return r; + } + + bool pkg_bindist_common_options:: + parse (int start, + int& argc, + char** argv, + bool erase, + ::bpkg::cli::unknown_mode opt, + ::bpkg::cli::unknown_mode arg) + { + ::bpkg::cli::argv_scanner s (start, argc, argv, erase); + bool r = _parse (s, opt, arg); + return r; + } + + bool pkg_bindist_common_options:: + parse (int& argc, + char** argv, + int& end, + bool erase, + ::bpkg::cli::unknown_mode opt, + ::bpkg::cli::unknown_mode arg) + { + ::bpkg::cli::argv_scanner s (argc, argv, erase); + bool r = _parse (s, opt, arg); + end = s.end (); + return r; + } + + bool pkg_bindist_common_options:: + parse (int start, + int& argc, + char** argv, + int& end, + bool erase, + ::bpkg::cli::unknown_mode opt, + ::bpkg::cli::unknown_mode arg) + { + ::bpkg::cli::argv_scanner s (start, argc, argv, erase); + bool r = _parse (s, opt, arg); + end = s.end (); + return r; + } + + bool pkg_bindist_common_options:: + parse (::bpkg::cli::scanner& s, + ::bpkg::cli::unknown_mode opt, + ::bpkg::cli::unknown_mode arg) + { + bool r = _parse (s, opt, arg); + return r; + } + + void pkg_bindist_common_options:: + merge (const pkg_bindist_common_options& a) + { + CLI_POTENTIALLY_UNUSED (a); + + // configuration_options base + // + ::bpkg::configuration_options::merge (a); + + if (a.distribution_specified_) + { + ::bpkg::cli::parser< string>::merge ( + this->distribution_, a.distribution_); + this->distribution_specified_ = true; + } + + if (a.architecture_specified_) + { + ::bpkg::cli::parser< string>::merge ( + this->architecture_, a.architecture_); + this->architecture_specified_ = true; + } + + if (a.recursive_specified_) + { + ::bpkg::cli::parser< string>::merge ( + this->recursive_, a.recursive_); + this->recursive_specified_ = true; + } + + if (a.private__) + { + ::bpkg::cli::parser< bool>::merge ( + this->private__, a.private__); + } + + if (a.output_root_specified_) + { + ::bpkg::cli::parser< dir_path>::merge ( + this->output_root_, a.output_root_); + this->output_root_specified_ = true; + } + + if (a.wipe_output_) + { + ::bpkg::cli::parser< bool>::merge ( + this->wipe_output_, a.wipe_output_); + } + + if (a.keep_output_) + { + ::bpkg::cli::parser< bool>::merge ( + this->keep_output_, a.keep_output_); + } + + if (a.allow_dependent_config_) + { + ::bpkg::cli::parser< bool>::merge ( + this->allow_dependent_config_, a.allow_dependent_config_); + } + + if (a.os_release_id_specified_) + { + ::bpkg::cli::parser< string>::merge ( + this->os_release_id_, a.os_release_id_); + this->os_release_id_specified_ = true; + } + + if (a.os_release_version_id_specified_) + { + ::bpkg::cli::parser< string>::merge ( + this->os_release_version_id_, a.os_release_version_id_); + this->os_release_version_id_specified_ = true; + } + + if (a.os_release_name_specified_) + { + ::bpkg::cli::parser< string>::merge ( + this->os_release_name_, a.os_release_name_); + this->os_release_name_specified_ = true; + } + } + + ::bpkg::cli::usage_para pkg_bindist_common_options:: + print_usage (::std::ostream& os, ::bpkg::cli::usage_para p) + { + CLI_POTENTIALLY_UNUSED (os); + + if (p != ::bpkg::cli::usage_para::none) + os << ::std::endl; + + os << "\033[1mPKG-BINDIST OPTIONS\033[0m" << ::std::endl + << ::std::endl + << "See the following sections below for distribution-specific options:" << ::std::endl + << ::std::endl + << "PKG-BINDIST DEBIAN OPTIONS" << ::std::endl + << ::std::endl + << "PKG-BINDIST FEDORA OPTIONS" << ::std::endl + << ::std::endl + << "PKG-BINDIST ARCHIVE OPTIONS" << ::std::endl; + + os << std::endl + << "\033[1m--distribution\033[0m \033[4mname\033[0m Alternative system/distribution package manager to" << ::std::endl + << " generate the binary package for. The valid \033[4mname\033[0m" << ::std::endl + << " values are \033[1mdebian\033[0m (Debian and alike, such as Ubuntu," << ::std::endl + << " etc), \033[1mfedora\033[0m (Fedora and alike, such as RHEL, CentOS," << ::std::endl + << " etc), and \033[1marchive\033[0m (installation archive on any" << ::std::endl + << " operating system). Note that some package managers" << ::std::endl + << " may only be supported when running on certain host" << ::std::endl + << " operating systems." << ::std::endl; + + os << std::endl + << "\033[1m--architecture\033[0m \033[4mname\033[0m Alternative architecture to generate the binary" << ::std::endl + << " package for. The valid \033[4mname\033[0m values are" << ::std::endl + << " system/distribution package manager-specific. If" << ::std::endl + << " unspecified, the host architecture is used." << ::std::endl; + + os << std::endl + << "\033[1m--recursive\033[0m \033[4mmode\033[0m Bundle or generate dependencies of the specified" << ::std::endl + << " packages. The \033[4mmode\033[0m value can be either \033[1mauto\033[0m, in which" << ::std::endl + << " case only the required files from each dependency" << ::std::endl + << " package are bundled, \033[1mfull\033[0m, in which case all the" << ::std::endl + << " files are bundled, or \033[1mseparate\033[0m, in which case a" << ::std::endl + << " separate binary package is generated for each" << ::std::endl + << " non-system dependency. It can also be \033[1mnone\033[0m which is" << ::std::endl + << " equivalent to not specifying this option (primarily" << ::std::endl + << " useful for overriding a previously-specified value)." << ::std::endl + << ::std::endl + << " Specifically, in the \033[1mauto\033[0m mode any required files," << ::std::endl + << " such as shared libraries, are pulled implicitly by" << ::std::endl + << " the \033[1minstall\033[0m build system operation, for example, as" << ::std::endl + << " part of installing an executable from one of the" << ::std::endl + << " specified packages. In contrast, in the \033[1mfull\033[0m mode," << ::std::endl + << " each dependency package is installed explicitly and" << ::std::endl + << " completely, as if they were specified as additional" << ::std::endl + << " package on the command line. The \033[1mseparate\033[0m mode is" << ::std::endl + << " equivalent to invoking the \033[1mpkg-bindist\033[0m command on" << ::std::endl + << " each dependency package. See also the \033[1m--private\033[0m" << ::std::endl + << " option." << ::std::endl; + + os << std::endl + << "\033[1m--private\033[0m Enable the private installation subdirectory" << ::std::endl + << " functionality using the package name as the private" << ::std::endl + << " subdirectory. This is primarily useful when bundling" << ::std::endl + << " dependencies, such as shared libraries, of an" << ::std::endl + << " executable that is being installed into a shared" << ::std::endl + << " location, such as \033[1m/usr/\033[0m. See the" << ::std::endl + << " \033[1mconfig.install.private\033[0m configuration variable" << ::std::endl + << " documentation in the build system manual for details." << ::std::endl + << " This option only makes sense together with the" << ::std::endl + << " \033[1m--recursive\033[0m option \033[1mauto\033[0m and \033[1mfull\033[0m modes." << ::std::endl; + + os << std::endl + << "\033[1m--output-root\033[0m|\033[1m-o\033[0m \033[4mdir\033[0m Directory for intermediate files and subdirectories" << ::std::endl + << " as well as the resulting binary package. Note that" << ::std::endl + << " this option may be required for some system package" << ::std::endl + << " managers and may not be specified for others." << ::std::endl; + + os << std::endl + << "\033[1m--wipe-output\033[0m Wipe the output root directory (either specified with" << ::std::endl + << " \033[4m--output-root\033[0m or system package manager-specific)" << ::std::endl + << " clean before using it to generate the binary package." << ::std::endl; + + os << std::endl + << "\033[1m--keep-output\033[0m Keep intermediate files in the output root directory" << ::std::endl + << " (either specified with \033[4m--output-root\033[0m or system" << ::std::endl + << " package manager-specific) that were used to generate" << ::std::endl + << " the binary package. This is primarily useful for" << ::std::endl + << " troubleshooting." << ::std::endl; + + os << std::endl + << "\033[1m--allow-dependent-config\033[0m Allow configuration that is imposed by dependent" << ::std::endl + << " packages. Normally this is undesirable because the" << ::std::endl + << " resulting binary packages become configured" << ::std::endl + << " specificaly for particular dependent packages." << ::std::endl; + + os << std::endl + << "\033[1m--os-release-id\033[0m \033[4mv\033[0m Override the \033[1mID\033[0m component in \033[1mos-release(5)\033[0m or" << ::std::endl + << " equivalent. Note that unlike the rest of the" << ::std::endl + << " \033[1m--os-release-*\033[0m options, this option suppresses" << ::std::endl + << " automatic detection of the host operating system" << ::std::endl + << " information." << ::std::endl; + + os << std::endl + << "\033[1m--os-release-version-id\033[0m \033[4mv\033[0m Override the \033[1mVERSION_ID\033[0m component in \033[1mos-release(5)\033[0m or" << ::std::endl + << " equivalent." << ::std::endl; + + os << std::endl + << "\033[1m--os-release-name\033[0m \033[4mv\033[0m Override the \033[1mNAME\033[0m component in \033[1mos-release(5)\033[0m or" << ::std::endl + << " equivalent." << ::std::endl; + + p = ::bpkg::cli::usage_para::option; + + // configuration_options base + // + p = ::bpkg::configuration_options::print_usage (os, p); + + return p; + } + + typedef + std::map<std::string, void (*) (pkg_bindist_common_options&, ::bpkg::cli::scanner&)> + _cli_pkg_bindist_common_options_map; + + static _cli_pkg_bindist_common_options_map _cli_pkg_bindist_common_options_map_; + + struct _cli_pkg_bindist_common_options_map_init + { + _cli_pkg_bindist_common_options_map_init () + { + _cli_pkg_bindist_common_options_map_["--distribution"] = + &::bpkg::cli::thunk< pkg_bindist_common_options, string, &pkg_bindist_common_options::distribution_, + &pkg_bindist_common_options::distribution_specified_ >; + _cli_pkg_bindist_common_options_map_["--architecture"] = + &::bpkg::cli::thunk< pkg_bindist_common_options, string, &pkg_bindist_common_options::architecture_, + &pkg_bindist_common_options::architecture_specified_ >; + _cli_pkg_bindist_common_options_map_["--recursive"] = + &::bpkg::cli::thunk< pkg_bindist_common_options, string, &pkg_bindist_common_options::recursive_, + &pkg_bindist_common_options::recursive_specified_ >; + _cli_pkg_bindist_common_options_map_["--private"] = + &::bpkg::cli::thunk< pkg_bindist_common_options, &pkg_bindist_common_options::private__ >; + _cli_pkg_bindist_common_options_map_["--output-root"] = + &::bpkg::cli::thunk< pkg_bindist_common_options, dir_path, &pkg_bindist_common_options::output_root_, + &pkg_bindist_common_options::output_root_specified_ >; + _cli_pkg_bindist_common_options_map_["-o"] = + &::bpkg::cli::thunk< pkg_bindist_common_options, dir_path, &pkg_bindist_common_options::output_root_, + &pkg_bindist_common_options::output_root_specified_ >; + _cli_pkg_bindist_common_options_map_["--wipe-output"] = + &::bpkg::cli::thunk< pkg_bindist_common_options, &pkg_bindist_common_options::wipe_output_ >; + _cli_pkg_bindist_common_options_map_["--keep-output"] = + &::bpkg::cli::thunk< pkg_bindist_common_options, &pkg_bindist_common_options::keep_output_ >; + _cli_pkg_bindist_common_options_map_["--allow-dependent-config"] = + &::bpkg::cli::thunk< pkg_bindist_common_options, &pkg_bindist_common_options::allow_dependent_config_ >; + _cli_pkg_bindist_common_options_map_["--os-release-id"] = + &::bpkg::cli::thunk< pkg_bindist_common_options, string, &pkg_bindist_common_options::os_release_id_, + &pkg_bindist_common_options::os_release_id_specified_ >; + _cli_pkg_bindist_common_options_map_["--os-release-version-id"] = + &::bpkg::cli::thunk< pkg_bindist_common_options, string, &pkg_bindist_common_options::os_release_version_id_, + &pkg_bindist_common_options::os_release_version_id_specified_ >; + _cli_pkg_bindist_common_options_map_["--os-release-name"] = + &::bpkg::cli::thunk< pkg_bindist_common_options, string, &pkg_bindist_common_options::os_release_name_, + &pkg_bindist_common_options::os_release_name_specified_ >; + } + }; + + static _cli_pkg_bindist_common_options_map_init _cli_pkg_bindist_common_options_map_init_; + + bool pkg_bindist_common_options:: + _parse (const char* o, ::bpkg::cli::scanner& s) + { + _cli_pkg_bindist_common_options_map::const_iterator i (_cli_pkg_bindist_common_options_map_.find (o)); + + if (i != _cli_pkg_bindist_common_options_map_.end ()) + { + (*(i->second)) (*this, s); + return true; + } + + // configuration_options base + // + if (::bpkg::configuration_options::_parse (o, s)) + return true; + + return false; + } + + bool pkg_bindist_common_options:: + _parse (::bpkg::cli::scanner& s, + ::bpkg::cli::unknown_mode opt_mode, + ::bpkg::cli::unknown_mode arg_mode) + { + // Can't skip combined flags (--no-combined-flags). + // + assert (opt_mode != ::bpkg::cli::unknown_mode::skip); + + bool r = false; + bool opt = true; + + while (s.more ()) + { + const char* o = s.peek (); + + if (std::strcmp (o, "--") == 0) + { + opt = false; + } + + if (opt) + { + if (_parse (o, s)) + { + r = true; + continue; + } + + if (std::strncmp (o, "-", 1) == 0 && o[1] != '\0') + { + // Handle combined option values. + // + std::string co; + if (const char* v = std::strchr (o, '=')) + { + co.assign (o, 0, v - o); + ++v; + + int ac (2); + char* av[] = + { + const_cast<char*> (co.c_str ()), + const_cast<char*> (v) + }; + + ::bpkg::cli::argv_scanner ns (0, ac, av); + + if (_parse (co.c_str (), ns)) + { + // Parsed the option but not its value? + // + if (ns.end () != 2) + throw ::bpkg::cli::invalid_value (co, v); + + s.next (); + r = true; + continue; + } + else + { + // Set the unknown option and fall through. + // + o = co.c_str (); + } + } + + // Handle combined flags. + // + char cf[3]; + { + const char* p = o + 1; + for (; *p != '\0'; ++p) + { + if (!((*p >= 'a' && *p <= 'z') || + (*p >= 'A' && *p <= 'Z') || + (*p >= '0' && *p <= '9'))) + break; + } + + if (*p == '\0') + { + for (p = o + 1; *p != '\0'; ++p) + { + std::strcpy (cf, "-"); + cf[1] = *p; + cf[2] = '\0'; + + int ac (1); + char* av[] = + { + cf + }; + + ::bpkg::cli::argv_scanner ns (0, ac, av); + + if (!_parse (cf, ns)) + break; + } + + if (*p == '\0') + { + // All handled. + // + s.next (); + r = true; + continue; + } + else + { + // Set the unknown option and fall through. + // + o = cf; + } + } + } + + switch (opt_mode) + { + case ::bpkg::cli::unknown_mode::skip: + { + s.skip (); + r = true; + continue; + } + case ::bpkg::cli::unknown_mode::stop: + { + break; + } + case ::bpkg::cli::unknown_mode::fail: + { + throw ::bpkg::cli::unknown_option (o); + } + } + + break; + } + } + + switch (arg_mode) + { + case ::bpkg::cli::unknown_mode::skip: + { + s.skip (); + r = true; + continue; + } + case ::bpkg::cli::unknown_mode::stop: + { + break; + } + case ::bpkg::cli::unknown_mode::fail: + { + throw ::bpkg::cli::unknown_argument (o); + } + } + + break; + } + + return r; + } + + // pkg_bindist_debian_options + // + + pkg_bindist_debian_options:: + pkg_bindist_debian_options () + : debian_prepare_only_ (), + debian_buildflags_ ("assign"), + debian_buildflags_specified_ (false), + debian_maint_option_ (), + debian_maint_option_specified_ (false), + debian_build_option_ (), + debian_build_option_specified_ (false), + debian_build_meta_ (), + debian_build_meta_specified_ (false), + debian_section_ (), + debian_section_specified_ (false), + debian_priority_ (), + debian_priority_specified_ (false), + debian_maintainer_ (), + debian_maintainer_specified_ (false), + debian_architecture_ (), + debian_architecture_specified_ (false), + debian_main_langdep_ (), + debian_main_langdep_specified_ (false), + debian_dev_langdep_ (), + debian_dev_langdep_specified_ (false), + debian_main_extradep_ (), + debian_main_extradep_specified_ (false), + debian_dev_extradep_ (), + debian_dev_extradep_specified_ (false) + { + } + + bool pkg_bindist_debian_options:: + parse (int& argc, + char** argv, + bool erase, + ::bpkg::cli::unknown_mode opt, + ::bpkg::cli::unknown_mode arg) + { + ::bpkg::cli::argv_scanner s (argc, argv, erase); + bool r = _parse (s, opt, arg); + return r; + } + + bool pkg_bindist_debian_options:: + parse (int start, + int& argc, + char** argv, + bool erase, + ::bpkg::cli::unknown_mode opt, + ::bpkg::cli::unknown_mode arg) + { + ::bpkg::cli::argv_scanner s (start, argc, argv, erase); + bool r = _parse (s, opt, arg); + return r; + } + + bool pkg_bindist_debian_options:: + parse (int& argc, + char** argv, + int& end, + bool erase, + ::bpkg::cli::unknown_mode opt, + ::bpkg::cli::unknown_mode arg) + { + ::bpkg::cli::argv_scanner s (argc, argv, erase); + bool r = _parse (s, opt, arg); + end = s.end (); + return r; + } + + bool pkg_bindist_debian_options:: + parse (int start, + int& argc, + char** argv, + int& end, + bool erase, + ::bpkg::cli::unknown_mode opt, + ::bpkg::cli::unknown_mode arg) + { + ::bpkg::cli::argv_scanner s (start, argc, argv, erase); + bool r = _parse (s, opt, arg); + end = s.end (); + return r; + } + + bool pkg_bindist_debian_options:: + parse (::bpkg::cli::scanner& s, + ::bpkg::cli::unknown_mode opt, + ::bpkg::cli::unknown_mode arg) + { + bool r = _parse (s, opt, arg); + return r; + } + + void pkg_bindist_debian_options:: + merge (const pkg_bindist_debian_options& a) + { + CLI_POTENTIALLY_UNUSED (a); + + if (a.debian_prepare_only_) + { + ::bpkg::cli::parser< bool>::merge ( + this->debian_prepare_only_, a.debian_prepare_only_); + } + + if (a.debian_buildflags_specified_) + { + ::bpkg::cli::parser< string>::merge ( + this->debian_buildflags_, a.debian_buildflags_); + this->debian_buildflags_specified_ = true; + } + + if (a.debian_maint_option_specified_) + { + ::bpkg::cli::parser< strings>::merge ( + this->debian_maint_option_, a.debian_maint_option_); + this->debian_maint_option_specified_ = true; + } + + if (a.debian_build_option_specified_) + { + ::bpkg::cli::parser< strings>::merge ( + this->debian_build_option_, a.debian_build_option_); + this->debian_build_option_specified_ = true; + } + + if (a.debian_build_meta_specified_) + { + ::bpkg::cli::parser< string>::merge ( + this->debian_build_meta_, a.debian_build_meta_); + this->debian_build_meta_specified_ = true; + } + + if (a.debian_section_specified_) + { + ::bpkg::cli::parser< string>::merge ( + this->debian_section_, a.debian_section_); + this->debian_section_specified_ = true; + } + + if (a.debian_priority_specified_) + { + ::bpkg::cli::parser< string>::merge ( + this->debian_priority_, a.debian_priority_); + this->debian_priority_specified_ = true; + } + + if (a.debian_maintainer_specified_) + { + ::bpkg::cli::parser< string>::merge ( + this->debian_maintainer_, a.debian_maintainer_); + this->debian_maintainer_specified_ = true; + } + + if (a.debian_architecture_specified_) + { + ::bpkg::cli::parser< string>::merge ( + this->debian_architecture_, a.debian_architecture_); + this->debian_architecture_specified_ = true; + } + + if (a.debian_main_langdep_specified_) + { + ::bpkg::cli::parser< string>::merge ( + this->debian_main_langdep_, a.debian_main_langdep_); + this->debian_main_langdep_specified_ = true; + } + + if (a.debian_dev_langdep_specified_) + { + ::bpkg::cli::parser< string>::merge ( + this->debian_dev_langdep_, a.debian_dev_langdep_); + this->debian_dev_langdep_specified_ = true; + } + + if (a.debian_main_extradep_specified_) + { + ::bpkg::cli::parser< string>::merge ( + this->debian_main_extradep_, a.debian_main_extradep_); + this->debian_main_extradep_specified_ = true; + } + + if (a.debian_dev_extradep_specified_) + { + ::bpkg::cli::parser< string>::merge ( + this->debian_dev_extradep_, a.debian_dev_extradep_); + this->debian_dev_extradep_specified_ = true; + } + } + + ::bpkg::cli::usage_para pkg_bindist_debian_options:: + print_usage (::std::ostream& os, ::bpkg::cli::usage_para p) + { + CLI_POTENTIALLY_UNUSED (os); + + if (p != ::bpkg::cli::usage_para::none) + os << ::std::endl; + + os << "\033[1mDEBIAN DESCRIPTION\033[0m" << ::std::endl + << ::std::endl + << "The Debian binary packages are generated by producing the standard" << ::std::endl + << "\033[1mdebian/control\033[0m, \033[1mdebian/rules\033[0m, and other package metadata files and then" << ::std::endl + << "invoking \033[1mdpkg-buildpackage(1)\033[0m to build the binary package from that. In" << ::std::endl + << "particular, the \033[1mdebian/rules\033[0m implemenation is based on the \033[1mdh(1)\033[0m command" << ::std::endl + << "sequencer. While this approach is normally used to build packages from source," << ::std::endl + << "this implementation \"pretends\" that this is what's happening by overriding a" << ::std::endl + << "number of \033[1mdh\033[0m targets to invoke the \033[1mbuild2\033[0m build system on the required packages" << ::std::endl + << "directly in their \033[1mbpkg\033[0m configuration locations." << ::std::endl + << ::std::endl + << "The \033[1mdpkg-dev\033[0m (or \033[1mbuild-essential\033[0m) and \033[1mdebhelper\033[0m Debian packages must be" << ::std::endl + << "installed before invocation. Typical invocation:" << ::std::endl + << ::std::endl + << "bpkg build libhello" << ::std::endl + << "bpkg test libhello" << ::std::endl + << "bpkg bindist -o /tmp/output/ libhello" << ::std::endl + << ::std::endl + << "Unless the \033[1m--recursive\033[0m option \033[1mauto\033[0m or \033[1mfull\033[0m modes are specified, dependencies of" << ::std::endl + << "the specified package are translated to dependencies in the resulting binary" << ::std::endl + << "package using names and versions that refer to packages that would be generated" << ::std::endl + << "by the \033[1mpkg-bindist\033[0m command (called \"non-native\" packages). If instead you would" << ::std::endl + << "like certain dependencies to refer to binary packages provided by the" << ::std::endl + << "distribution (called \"native\" packages), then you need to arrange for them to" << ::std::endl + << "be built as system (see \033[1mbpkg-pkg-build(1)\033[0m for details). For example, if our" << ::std::endl + << "\033[1mlibhello\033[0m has a dependency on \033[1mlibsqlite3\033[0m and we would like the binary package" << ::std::endl + << "for \033[1mlibhello\033[0m to refer to \033[1mlibsqlite3\033[0m from Debian (or alike), then the \033[1mpkg-build\033[0m" << ::std::endl + << "command would need to be (\033[1m--sys-install\033[0m is optional):" << ::std::endl + << ::std::endl + << "bpkg build --sys-install libhello ?sys:libsqlite3" << ::std::endl + << ::std::endl + << "Such a package with native dependencies can then be installed (including any" << ::std::endl + << "missing native dependencies) using the \033[1mapt\033[0m or \033[1mapt-get\033[0m \033[1minstall\033[0m command. Note" << ::std::endl + << "that the specified \033[1m.deb\033[0m file must include a directory separator (/\033[0m) in order to" << ::std::endl + << "be recognized as a file rather than a package name. For example:" << ::std::endl + << ::std::endl + << "sudo apt-get install ./libhello_1.2.3-0~debian11_amd64.deb \\" << ::std::endl + << " ./libhello-dev_1.2.3-0~debian11_amd64.deb" << ::std::endl + << ::std::endl + << "See Debian Package Mapping for Production (bpkg#bindist-mapping-debian-produce)" << ::std::endl + << "for details on \033[1mbpkg\033[0m to Debian package name and version mapping." << ::std::endl; + + os << std::endl + << "\033[1mPKG-BINDIST DEBIAN OPTIONS\033[0m" << ::std::endl; + + os << std::endl + << "\033[1m--debian-prepare-only\033[0m Prepare all the package metadata files (\033[1mcontrol\033[0m," << ::std::endl + << " \033[1mrules\033[0m, etc) but do not invoke \033[1mdpkg-buildpackage\033[0m to" << ::std::endl + << " generate the binary package, printing its command" << ::std::endl + << " line instead unless requested to be quiet. Implies" << ::std::endl + << " \033[1m--keep-output\033[0m." << ::std::endl; + + os << std::endl + << "\033[1m--debian-buildflags\033[0m \033[4mmode\033[0m Package build flags (\033[1mdpkg-buildflags\033[0m) usage mode." << ::std::endl + << " Valid \033[4mmode\033[0m values are \033[1massign\033[0m (use the build flags" << ::std::endl + << " instead of configured), \033[1mappend\033[0m (use the build flags" << ::std::endl + << " in addition to configured, putting them last)," << ::std::endl + << " \033[1mprepend\033[0m (use the build flags in addition to" << ::std::endl + << " configured, putting them first), and \033[1mignore\033[0m (ignore" << ::std::endl + << " build flags). The default mode is \033[1massign\033[0m. Note that" << ::std::endl + << " compiler mode options, if any, are used as" << ::std::endl + << " configured." << ::std::endl; + + os << std::endl + << "\033[1m--debian-maint-option\033[0m \033[4mo\033[0m Alternative options to specify in the" << ::std::endl + << " \033[1mDEB_BUILD_MAINT_OPTIONS\033[0m variable of the \033[1mrules\033[0m file." << ::std::endl + << " To specify multiple maintainer options repeat this" << ::std::endl + << " option and/or specify them as a single value" << ::std::endl + << " separated with spaces." << ::std::endl; + + os << std::endl + << "\033[1m--debian-build-option\033[0m \033[4mo\033[0m Additional option to pass to the \033[1mdpkg-buildpackage\033[0m" << ::std::endl + << " program. Repeat this option to specify multiple build" << ::std::endl + << " options." << ::std::endl; + + os << std::endl + << "\033[1m--debian-build-meta\033[0m \033[4mdata\033[0m Alternative or additional build metadata to include" << ::std::endl + << " in the binary package version. If the specified value" << ::std::endl + << " starts/ends with \033[1m+\033[0m then the value (with \033[1m+\033[0m removed) is" << ::std::endl + << " added after/before the default metadata. Otherwise it" << ::std::endl + << " is used as is instead of the default metadata. If" << ::std::endl + << " empty value is specified, then no build metadata is" << ::std::endl + << " included. By default, the build metadata is the \033[1mID\033[0m" << ::std::endl + << " and \033[1mVERSION_ID\033[0m components from \033[1mos-release(5)\033[0m, for" << ::std::endl + << " example, \033[1mdebian10\033[0m in version \033[1m1.2.3-0~debian10\033[0m. See" << ::std::endl + << " also \033[1m--os-release-*\033[0m." << ::std::endl; + + os << std::endl + << "\033[1m--debian-section\033[0m \033[4mv\033[0m Alternative \033[1mSection\033[0m \033[1mcontrol\033[0m file field value for the" << ::std::endl + << " main binary package. The default is either \033[1mlibs\033[0m or" << ::std::endl + << " \033[1mdevel\033[0m, depending on the package type." << ::std::endl; + + os << std::endl + << "\033[1m--debian-priority\033[0m \033[4mv\033[0m Alternative \033[1mPriority\033[0m \033[1mcontrol\033[0m file field value. The" << ::std::endl + << " default is \033[1moptional\033[0m." << ::std::endl; + + os << std::endl + << "\033[1m--debian-maintainer\033[0m \033[4mv\033[0m Alternative \033[1mMaintainer\033[0m \033[1mcontrol\033[0m file field value. The" << ::std::endl + << " default is the \033[1mpackage-email\033[0m value from package" << ::std::endl + << " \033[1mmanifest\033[0m." << ::std::endl; + + os << std::endl + << "\033[1m--debian-architecture\033[0m \033[4mv\033[0m Alternative \033[1mArchitecture\033[0m \033[1mcontrol\033[0m file field value for" << ::std::endl + << " the main binary package, normally \033[1mall\033[0m" << ::std::endl + << " (architecture-independent). The default is \033[1many\033[0m" << ::std::endl + << " (architecture-dependent)." << ::std::endl; + + os << std::endl + << "\033[1m--debian-main-langdep\033[0m \033[4mv\033[0m Override the language runtime dependencies (such as" << ::std::endl + << " \033[1mlibc6\033[0m, \033[1mlibstdc++6\033[0m, etc) in the \033[1mDepends\033[0m \033[1mcontrol\033[0m file" << ::std::endl + << " field value of the main binary package." << ::std::endl; + + os << std::endl + << "\033[1m--debian-dev-langdep\033[0m \033[4mv\033[0m Override the language runtime dependencies (such as" << ::std::endl + << " \033[1mlibc-dev\033[0m, \033[1mlibstdc++-dev\033[0m, etc) in the \033[1mDepends\033[0m \033[1mcontrol\033[0m" << ::std::endl + << " file field value of the development (\033[1m-dev\033[0m) binary" << ::std::endl + << " package." << ::std::endl; + + os << std::endl + << "\033[1m--debian-main-extradep\033[0m \033[4mv\033[0m Extra dependencies to add to the \033[1mDepends\033[0m \033[1mcontrol\033[0m file" << ::std::endl + << " field value of the main binary package." << ::std::endl; + + os << std::endl + << "\033[1m--debian-dev-extradep\033[0m \033[4mv\033[0m Extra dependencies to add to the \033[1mDepends\033[0m \033[1mcontrol\033[0m file" << ::std::endl + << " field value of the development (\033[1m-dev\033[0m) binary package." << ::std::endl; + + p = ::bpkg::cli::usage_para::option; + + return p; + } + + typedef + std::map<std::string, void (*) (pkg_bindist_debian_options&, ::bpkg::cli::scanner&)> + _cli_pkg_bindist_debian_options_map; + + static _cli_pkg_bindist_debian_options_map _cli_pkg_bindist_debian_options_map_; + + struct _cli_pkg_bindist_debian_options_map_init + { + _cli_pkg_bindist_debian_options_map_init () + { + _cli_pkg_bindist_debian_options_map_["--debian-prepare-only"] = + &::bpkg::cli::thunk< pkg_bindist_debian_options, &pkg_bindist_debian_options::debian_prepare_only_ >; + _cli_pkg_bindist_debian_options_map_["--debian-buildflags"] = + &::bpkg::cli::thunk< pkg_bindist_debian_options, string, &pkg_bindist_debian_options::debian_buildflags_, + &pkg_bindist_debian_options::debian_buildflags_specified_ >; + _cli_pkg_bindist_debian_options_map_["--debian-maint-option"] = + &::bpkg::cli::thunk< pkg_bindist_debian_options, strings, &pkg_bindist_debian_options::debian_maint_option_, + &pkg_bindist_debian_options::debian_maint_option_specified_ >; + _cli_pkg_bindist_debian_options_map_["--debian-build-option"] = + &::bpkg::cli::thunk< pkg_bindist_debian_options, strings, &pkg_bindist_debian_options::debian_build_option_, + &pkg_bindist_debian_options::debian_build_option_specified_ >; + _cli_pkg_bindist_debian_options_map_["--debian-build-meta"] = + &::bpkg::cli::thunk< pkg_bindist_debian_options, string, &pkg_bindist_debian_options::debian_build_meta_, + &pkg_bindist_debian_options::debian_build_meta_specified_ >; + _cli_pkg_bindist_debian_options_map_["--debian-section"] = + &::bpkg::cli::thunk< pkg_bindist_debian_options, string, &pkg_bindist_debian_options::debian_section_, + &pkg_bindist_debian_options::debian_section_specified_ >; + _cli_pkg_bindist_debian_options_map_["--debian-priority"] = + &::bpkg::cli::thunk< pkg_bindist_debian_options, string, &pkg_bindist_debian_options::debian_priority_, + &pkg_bindist_debian_options::debian_priority_specified_ >; + _cli_pkg_bindist_debian_options_map_["--debian-maintainer"] = + &::bpkg::cli::thunk< pkg_bindist_debian_options, string, &pkg_bindist_debian_options::debian_maintainer_, + &pkg_bindist_debian_options::debian_maintainer_specified_ >; + _cli_pkg_bindist_debian_options_map_["--debian-architecture"] = + &::bpkg::cli::thunk< pkg_bindist_debian_options, string, &pkg_bindist_debian_options::debian_architecture_, + &pkg_bindist_debian_options::debian_architecture_specified_ >; + _cli_pkg_bindist_debian_options_map_["--debian-main-langdep"] = + &::bpkg::cli::thunk< pkg_bindist_debian_options, string, &pkg_bindist_debian_options::debian_main_langdep_, + &pkg_bindist_debian_options::debian_main_langdep_specified_ >; + _cli_pkg_bindist_debian_options_map_["--debian-dev-langdep"] = + &::bpkg::cli::thunk< pkg_bindist_debian_options, string, &pkg_bindist_debian_options::debian_dev_langdep_, + &pkg_bindist_debian_options::debian_dev_langdep_specified_ >; + _cli_pkg_bindist_debian_options_map_["--debian-main-extradep"] = + &::bpkg::cli::thunk< pkg_bindist_debian_options, string, &pkg_bindist_debian_options::debian_main_extradep_, + &pkg_bindist_debian_options::debian_main_extradep_specified_ >; + _cli_pkg_bindist_debian_options_map_["--debian-dev-extradep"] = + &::bpkg::cli::thunk< pkg_bindist_debian_options, string, &pkg_bindist_debian_options::debian_dev_extradep_, + &pkg_bindist_debian_options::debian_dev_extradep_specified_ >; + } + }; + + static _cli_pkg_bindist_debian_options_map_init _cli_pkg_bindist_debian_options_map_init_; + + bool pkg_bindist_debian_options:: + _parse (const char* o, ::bpkg::cli::scanner& s) + { + _cli_pkg_bindist_debian_options_map::const_iterator i (_cli_pkg_bindist_debian_options_map_.find (o)); + + if (i != _cli_pkg_bindist_debian_options_map_.end ()) + { + (*(i->second)) (*this, s); + return true; + } + + return false; + } + + bool pkg_bindist_debian_options:: + _parse (::bpkg::cli::scanner& s, + ::bpkg::cli::unknown_mode opt_mode, + ::bpkg::cli::unknown_mode arg_mode) + { + // Can't skip combined flags (--no-combined-flags). + // + assert (opt_mode != ::bpkg::cli::unknown_mode::skip); + + bool r = false; + bool opt = true; + + while (s.more ()) + { + const char* o = s.peek (); + + if (std::strcmp (o, "--") == 0) + { + opt = false; + } + + if (opt) + { + if (_parse (o, s)) + { + r = true; + continue; + } + + if (std::strncmp (o, "-", 1) == 0 && o[1] != '\0') + { + // Handle combined option values. + // + std::string co; + if (const char* v = std::strchr (o, '=')) + { + co.assign (o, 0, v - o); + ++v; + + int ac (2); + char* av[] = + { + const_cast<char*> (co.c_str ()), + const_cast<char*> (v) + }; + + ::bpkg::cli::argv_scanner ns (0, ac, av); + + if (_parse (co.c_str (), ns)) + { + // Parsed the option but not its value? + // + if (ns.end () != 2) + throw ::bpkg::cli::invalid_value (co, v); + + s.next (); + r = true; + continue; + } + else + { + // Set the unknown option and fall through. + // + o = co.c_str (); + } + } + + // Handle combined flags. + // + char cf[3]; + { + const char* p = o + 1; + for (; *p != '\0'; ++p) + { + if (!((*p >= 'a' && *p <= 'z') || + (*p >= 'A' && *p <= 'Z') || + (*p >= '0' && *p <= '9'))) + break; + } + + if (*p == '\0') + { + for (p = o + 1; *p != '\0'; ++p) + { + std::strcpy (cf, "-"); + cf[1] = *p; + cf[2] = '\0'; + + int ac (1); + char* av[] = + { + cf + }; + + ::bpkg::cli::argv_scanner ns (0, ac, av); + + if (!_parse (cf, ns)) + break; + } + + if (*p == '\0') + { + // All handled. + // + s.next (); + r = true; + continue; + } + else + { + // Set the unknown option and fall through. + // + o = cf; + } + } + } + + switch (opt_mode) + { + case ::bpkg::cli::unknown_mode::skip: + { + s.skip (); + r = true; + continue; + } + case ::bpkg::cli::unknown_mode::stop: + { + break; + } + case ::bpkg::cli::unknown_mode::fail: + { + throw ::bpkg::cli::unknown_option (o); + } + } + + break; + } + } + + switch (arg_mode) + { + case ::bpkg::cli::unknown_mode::skip: + { + s.skip (); + r = true; + continue; + } + case ::bpkg::cli::unknown_mode::stop: + { + break; + } + case ::bpkg::cli::unknown_mode::fail: + { + throw ::bpkg::cli::unknown_argument (o); + } + } + + break; + } + + return r; + } + + // pkg_bindist_fedora_options + // + + pkg_bindist_fedora_options:: + pkg_bindist_fedora_options () + : fedora_prepare_only_ (), + fedora_buildflags_ ("assign"), + fedora_buildflags_specified_ (false), + fedora_build_option_ (), + fedora_build_option_specified_ (false), + fedora_query_option_ (), + fedora_query_option_specified_ (false), + fedora_dist_tag_ (), + fedora_dist_tag_specified_ (false), + fedora_packager_ (), + fedora_packager_specified_ (false), + fedora_build_arch_ (), + fedora_build_arch_specified_ (false), + fedora_main_langreq_ (), + fedora_main_langreq_specified_ (false), + fedora_devel_langreq_ (), + fedora_devel_langreq_specified_ (false), + fedora_stat_langreq_ (), + fedora_stat_langreq_specified_ (false), + fedora_main_extrareq_ (), + fedora_main_extrareq_specified_ (false), + fedora_devel_extrareq_ (), + fedora_devel_extrareq_specified_ (false), + fedora_stat_extrareq_ (), + fedora_stat_extrareq_specified_ (false) + { + } + + bool pkg_bindist_fedora_options:: + parse (int& argc, + char** argv, + bool erase, + ::bpkg::cli::unknown_mode opt, + ::bpkg::cli::unknown_mode arg) + { + ::bpkg::cli::argv_scanner s (argc, argv, erase); + bool r = _parse (s, opt, arg); + return r; + } + + bool pkg_bindist_fedora_options:: + parse (int start, + int& argc, + char** argv, + bool erase, + ::bpkg::cli::unknown_mode opt, + ::bpkg::cli::unknown_mode arg) + { + ::bpkg::cli::argv_scanner s (start, argc, argv, erase); + bool r = _parse (s, opt, arg); + return r; + } + + bool pkg_bindist_fedora_options:: + parse (int& argc, + char** argv, + int& end, + bool erase, + ::bpkg::cli::unknown_mode opt, + ::bpkg::cli::unknown_mode arg) + { + ::bpkg::cli::argv_scanner s (argc, argv, erase); + bool r = _parse (s, opt, arg); + end = s.end (); + return r; + } + + bool pkg_bindist_fedora_options:: + parse (int start, + int& argc, + char** argv, + int& end, + bool erase, + ::bpkg::cli::unknown_mode opt, + ::bpkg::cli::unknown_mode arg) + { + ::bpkg::cli::argv_scanner s (start, argc, argv, erase); + bool r = _parse (s, opt, arg); + end = s.end (); + return r; + } + + bool pkg_bindist_fedora_options:: + parse (::bpkg::cli::scanner& s, + ::bpkg::cli::unknown_mode opt, + ::bpkg::cli::unknown_mode arg) + { + bool r = _parse (s, opt, arg); + return r; + } + + void pkg_bindist_fedora_options:: + merge (const pkg_bindist_fedora_options& a) + { + CLI_POTENTIALLY_UNUSED (a); + + if (a.fedora_prepare_only_) + { + ::bpkg::cli::parser< bool>::merge ( + this->fedora_prepare_only_, a.fedora_prepare_only_); + } + + if (a.fedora_buildflags_specified_) + { + ::bpkg::cli::parser< string>::merge ( + this->fedora_buildflags_, a.fedora_buildflags_); + this->fedora_buildflags_specified_ = true; + } + + if (a.fedora_build_option_specified_) + { + ::bpkg::cli::parser< strings>::merge ( + this->fedora_build_option_, a.fedora_build_option_); + this->fedora_build_option_specified_ = true; + } + + if (a.fedora_query_option_specified_) + { + ::bpkg::cli::parser< strings>::merge ( + this->fedora_query_option_, a.fedora_query_option_); + this->fedora_query_option_specified_ = true; + } + + if (a.fedora_dist_tag_specified_) + { + ::bpkg::cli::parser< string>::merge ( + this->fedora_dist_tag_, a.fedora_dist_tag_); + this->fedora_dist_tag_specified_ = true; + } + + if (a.fedora_packager_specified_) + { + ::bpkg::cli::parser< string>::merge ( + this->fedora_packager_, a.fedora_packager_); + this->fedora_packager_specified_ = true; + } + + if (a.fedora_build_arch_specified_) + { + ::bpkg::cli::parser< string>::merge ( + this->fedora_build_arch_, a.fedora_build_arch_); + this->fedora_build_arch_specified_ = true; + } + + if (a.fedora_main_langreq_specified_) + { + ::bpkg::cli::parser< strings>::merge ( + this->fedora_main_langreq_, a.fedora_main_langreq_); + this->fedora_main_langreq_specified_ = true; + } + + if (a.fedora_devel_langreq_specified_) + { + ::bpkg::cli::parser< strings>::merge ( + this->fedora_devel_langreq_, a.fedora_devel_langreq_); + this->fedora_devel_langreq_specified_ = true; + } + + if (a.fedora_stat_langreq_specified_) + { + ::bpkg::cli::parser< strings>::merge ( + this->fedora_stat_langreq_, a.fedora_stat_langreq_); + this->fedora_stat_langreq_specified_ = true; + } + + if (a.fedora_main_extrareq_specified_) + { + ::bpkg::cli::parser< strings>::merge ( + this->fedora_main_extrareq_, a.fedora_main_extrareq_); + this->fedora_main_extrareq_specified_ = true; + } + + if (a.fedora_devel_extrareq_specified_) + { + ::bpkg::cli::parser< strings>::merge ( + this->fedora_devel_extrareq_, a.fedora_devel_extrareq_); + this->fedora_devel_extrareq_specified_ = true; + } + + if (a.fedora_stat_extrareq_specified_) + { + ::bpkg::cli::parser< strings>::merge ( + this->fedora_stat_extrareq_, a.fedora_stat_extrareq_); + this->fedora_stat_extrareq_specified_ = true; + } + } + + ::bpkg::cli::usage_para pkg_bindist_fedora_options:: + print_usage (::std::ostream& os, ::bpkg::cli::usage_para p) + { + CLI_POTENTIALLY_UNUSED (os); + + if (p != ::bpkg::cli::usage_para::none) + os << ::std::endl; + + os << "\033[1mFEDORA DESCRIPTION\033[0m" << ::std::endl + << ::std::endl + << "The Fedora binary packages are generated by producing the standard RPM spec" << ::std::endl + << "file and then invoking \033[1mrpmbuild(8)\033[0m to build the binary package from that. While" << ::std::endl + << "this approach is normally used to build packages from source, this" << ::std::endl + << "implementation \"pretends\" that this is what's happening by overriding a number" << ::std::endl + << "of RPM spec file sections to invoke the \033[1mbuild2\033[0m build system on the required" << ::std::endl + << "packages directly in their \033[1mbpkg\033[0m configuration locations." << ::std::endl + << ::std::endl + << "The \033[1mrpmdevtools\033[0m Fedora package must be installed before invocation. Typical" << ::std::endl + << "invocation:" << ::std::endl + << ::std::endl + << "bpkg build libhello" << ::std::endl + << "bpkg test libhello" << ::std::endl + << "bpkg bindist libhello" << ::std::endl + << ::std::endl + << "The resulting binary packages are placed into the standard \033[1mrpmbuild\033[0m output" << ::std::endl + << "directory (normally \033[1m~/rpmbuild/RPMS/\033[0m\033[4march\033[0m\033[1m/\033[0m\033[0m)." << ::std::endl + << ::std::endl + << "Unless the \033[1m--recursive\033[0m option \033[1mauto\033[0m or \033[1mfull\033[0m modes are specified, dependencies of" << ::std::endl + << "the specified package are translated to dependencies in the resulting binary" << ::std::endl + << "package using names and versions that refer to packages that would be generated" << ::std::endl + << "by the \033[1mpkg-bindist\033[0m command (called \"non-native\" packages). If instead you would" << ::std::endl + << "like certain dependencies to refer to binary packages provided by the" << ::std::endl + << "distribution (called \"native\" packages), then you need to arrange for them to" << ::std::endl + << "be built as system (see \033[1mbpkg-pkg-build(1)\033[0m for details). For example, if our" << ::std::endl + << "\033[1mlibhello\033[0m has a dependency on \033[1mlibsqlite3\033[0m and we would like the binary package" << ::std::endl + << "for \033[1mlibhello\033[0m to refer to \033[1msqlite-libs\033[0m from Fedora (or alike), then the" << ::std::endl + << "\033[1mpkg-build\033[0m command would need to be (\033[1m--sys-install\033[0m is optional):" << ::std::endl + << ::std::endl + << "bpkg build --sys-install libhello ?sys:libsqlite3" << ::std::endl + << ::std::endl + << "Such a package with native dependencies can then be installed (including any" << ::std::endl + << "missing native dependencies) using the \033[1mdnf install\033[0m command. For example:" << ::std::endl + << ::std::endl + << "sudo dnf install libhello-1.2.3-1.fc35.x86_64.rpm \\" << ::std::endl + << " libhello-devel-1.2.3-1.fc35.x86_64.rpm" << ::std::endl + << ::std::endl + << "See Fedora Package Mapping for Production (bpkg#bindist-mapping-fedora-produce)" << ::std::endl + << "for details on \033[1mbpkg\033[0m to Fedora package name and version mapping." << ::std::endl; + + os << std::endl + << "\033[1mPKG-BINDIST FEDORA OPTIONS\033[0m" << ::std::endl; + + os << std::endl + << "\033[1m--fedora-prepare-only\033[0m Prepare the RPM spec file but do not invoke \033[1mrpmbuild\033[0m" << ::std::endl + << " to generate the binary package, printing its command" << ::std::endl + << " line instead unless requested to be quiet." << ::std::endl; + + os << std::endl + << "\033[1m--fedora-buildflags\033[0m \033[4mmode\033[0m Package build flags (\033[1m%{build_*flags}\033[0m macros) usage" << ::std::endl + << " mode. Valid \033[4mmode\033[0m values are \033[1massign\033[0m (use the build" << ::std::endl + << " flags instead of configured), \033[1mappend\033[0m (use the build" << ::std::endl + << " flags in addition to configured, putting them last)," << ::std::endl + << " \033[1mprepend\033[0m (use the build flags in addition to" << ::std::endl + << " configured, putting them first), and \033[1mignore\033[0m (ignore" << ::std::endl + << " build flags). The default mode is \033[1massign\033[0m. Note that" << ::std::endl + << " compiler mode options, if any, are used as" << ::std::endl + << " configured." << ::std::endl; + + os << std::endl + << "\033[1m--fedora-build-option\033[0m \033[4mo\033[0m Additional option to pass to the \033[1mrpmbuild\033[0m program. If" << ::std::endl + << " specified, these options must be consistent with the" << ::std::endl + << " query options (\033[1m--fedora-query-option\033[0m) to result in" << ::std::endl + << " identical macro expansions. Repeat this option to" << ::std::endl + << " specify multiple build options." << ::std::endl; + + os << std::endl + << "\033[1m--fedora-query-option\033[0m \033[4mo\033[0m Additional option to pass to the \033[1mrpm\033[0m program. This" << ::std::endl + << " program is used to query RPM macro values which" << ::std::endl + << " affect the binary package. If specified, these" << ::std::endl + << " options must be consistent with the build options" << ::std::endl + << " (\033[1m--fedora-build-option\033[0m) to result in identical macro" << ::std::endl + << " expansions. Repeat this option to specify multiple" << ::std::endl + << " query options." << ::std::endl; + + os << std::endl + << "\033[1m--fedora-dist-tag\033[0m \033[4mtag\033[0m Alternative or additional distribution tag to use in" << ::std::endl + << " the binary package release. If the specified value" << ::std::endl + << " starts/ends with \033[1m+\033[0m then the value (with \033[1m+\033[0m removed) is" << ::std::endl + << " added after/before the default distribution tag." << ::std::endl + << " Otherwise it is used as is instead of the default" << ::std::endl + << " tag. If empty value is specified, then no" << ::std::endl + << " distribution tag is included. The default is a value" << ::std::endl + << " that identifies the distribution being used to build" << ::std::endl + << " the package, for example, \033[1mfc35\033[0m for Fedora 35 or \033[1mel8\033[0m" << ::std::endl + << " for RHEL 8." << ::std::endl; + + os << std::endl + << "\033[1m--fedora-packager\033[0m \033[4mv\033[0m Alternative \033[1mPackager\033[0m RPM spec file directive value." << ::std::endl + << " The default is the \033[1mpackage-email\033[0m value from package" << ::std::endl + << " \033[1mmanifest\033[0m. If empty value is specified, then the" << ::std::endl + << " \033[1mPackager\033[0m directive is omitted from the spec file." << ::std::endl; + + os << std::endl + << "\033[1m--fedora-build-arch\033[0m \033[4mv\033[0m \033[1mBuildArch\033[0m RPM spec file directive value for the main" << ::std::endl + << " binary package, normally \033[1mnoarch\033[0m" << ::std::endl + << " (architecture-independent). By default the directive" << ::std::endl + << " is omitted, assuming that the package is" << ::std::endl + << " architecture-dependent." << ::std::endl; + + os << std::endl + << "\033[1m--fedora-main-langreq\033[0m \033[4mv\033[0m Override the language runtime dependencies (such as" << ::std::endl + << " \033[1mglibc\033[0m, \033[1mlibstdc++\033[0m, etc) of the main binary package by" << ::std::endl + << " replacing the corresponding \033[1mRequires\033[0m RPM spec file" << ::std::endl + << " directives. If empty value is specified then no" << ::std::endl + << " language runtime dependencies are specified. Repeat" << ::std::endl + << " this option to specify multiple language runtime" << ::std::endl + << " dependencies." << ::std::endl; + + os << std::endl + << "\033[1m--fedora-devel-langreq\033[0m \033[4mv\033[0m Override the language runtime dependencies (such as" << ::std::endl + << " \033[1mglibc-devel\033[0m, \033[1mlibstdc++-devel\033[0m, etc) of the development" << ::std::endl + << " (\033[1m-devel\033[0m) binary package by replacing the" << ::std::endl + << " corresponding \033[1mRequires\033[0m RPM spec file directives. If" << ::std::endl + << " empty value is specified then no language runtime" << ::std::endl + << " dependencies are specified. Repeat this option to" << ::std::endl + << " specify multiple language runtime dependencies." << ::std::endl; + + os << std::endl + << "\033[1m--fedora-stat-langreq\033[0m \033[4mv\033[0m Override the language runtime dependencies (such as" << ::std::endl + << " \033[1mglibc-static\033[0m, \033[1mlibstdc++-static\033[0m, etc) of the static" << ::std::endl + << " libraries (\033[1m-static\033[0m) binary package by replacing the" << ::std::endl + << " corresponding \033[1mRequires\033[0m RPM spec file directives. If" << ::std::endl + << " empty value is specified then no language runtime" << ::std::endl + << " dependencies are specified. Repeat this option to" << ::std::endl + << " specify multiple language runtime dependencies." << ::std::endl; + + os << std::endl + << "\033[1m--fedora-main-extrareq\033[0m \033[4mv\033[0m Extra dependency to add to the main binary package as" << ::std::endl + << " an additional \033[1mRequires\033[0m RPM spec file directive." << ::std::endl + << " Repeat this option to specify multiple extra" << ::std::endl + << " dependencies." << ::std::endl; + + os << std::endl + << "\033[1m--fedora-devel-extrareq\033[0m \033[4mv\033[0m Extra dependency to add to the development (\033[1m-devel\033[0m)" << ::std::endl + << " binary package as an additional \033[1mRequires\033[0m RPM spec" << ::std::endl + << " file directive. Repeat this option to specify" << ::std::endl + << " multiple extra dependencies." << ::std::endl; + + os << std::endl + << "\033[1m--fedora-stat-extrareq\033[0m \033[4mv\033[0m Extra dependency to add to the static libraries" << ::std::endl + << " (\033[1m-static\033[0m) binary package as an additional \033[1mRequires\033[0m" << ::std::endl + << " RPM spec file directive. Repeat this option to" << ::std::endl + << " specify multiple extra dependencies." << ::std::endl; + + p = ::bpkg::cli::usage_para::option; + + return p; + } + + typedef + std::map<std::string, void (*) (pkg_bindist_fedora_options&, ::bpkg::cli::scanner&)> + _cli_pkg_bindist_fedora_options_map; + + static _cli_pkg_bindist_fedora_options_map _cli_pkg_bindist_fedora_options_map_; + + struct _cli_pkg_bindist_fedora_options_map_init + { + _cli_pkg_bindist_fedora_options_map_init () + { + _cli_pkg_bindist_fedora_options_map_["--fedora-prepare-only"] = + &::bpkg::cli::thunk< pkg_bindist_fedora_options, &pkg_bindist_fedora_options::fedora_prepare_only_ >; + _cli_pkg_bindist_fedora_options_map_["--fedora-buildflags"] = + &::bpkg::cli::thunk< pkg_bindist_fedora_options, string, &pkg_bindist_fedora_options::fedora_buildflags_, + &pkg_bindist_fedora_options::fedora_buildflags_specified_ >; + _cli_pkg_bindist_fedora_options_map_["--fedora-build-option"] = + &::bpkg::cli::thunk< pkg_bindist_fedora_options, strings, &pkg_bindist_fedora_options::fedora_build_option_, + &pkg_bindist_fedora_options::fedora_build_option_specified_ >; + _cli_pkg_bindist_fedora_options_map_["--fedora-query-option"] = + &::bpkg::cli::thunk< pkg_bindist_fedora_options, strings, &pkg_bindist_fedora_options::fedora_query_option_, + &pkg_bindist_fedora_options::fedora_query_option_specified_ >; + _cli_pkg_bindist_fedora_options_map_["--fedora-dist-tag"] = + &::bpkg::cli::thunk< pkg_bindist_fedora_options, string, &pkg_bindist_fedora_options::fedora_dist_tag_, + &pkg_bindist_fedora_options::fedora_dist_tag_specified_ >; + _cli_pkg_bindist_fedora_options_map_["--fedora-packager"] = + &::bpkg::cli::thunk< pkg_bindist_fedora_options, string, &pkg_bindist_fedora_options::fedora_packager_, + &pkg_bindist_fedora_options::fedora_packager_specified_ >; + _cli_pkg_bindist_fedora_options_map_["--fedora-build-arch"] = + &::bpkg::cli::thunk< pkg_bindist_fedora_options, string, &pkg_bindist_fedora_options::fedora_build_arch_, + &pkg_bindist_fedora_options::fedora_build_arch_specified_ >; + _cli_pkg_bindist_fedora_options_map_["--fedora-main-langreq"] = + &::bpkg::cli::thunk< pkg_bindist_fedora_options, strings, &pkg_bindist_fedora_options::fedora_main_langreq_, + &pkg_bindist_fedora_options::fedora_main_langreq_specified_ >; + _cli_pkg_bindist_fedora_options_map_["--fedora-devel-langreq"] = + &::bpkg::cli::thunk< pkg_bindist_fedora_options, strings, &pkg_bindist_fedora_options::fedora_devel_langreq_, + &pkg_bindist_fedora_options::fedora_devel_langreq_specified_ >; + _cli_pkg_bindist_fedora_options_map_["--fedora-stat-langreq"] = + &::bpkg::cli::thunk< pkg_bindist_fedora_options, strings, &pkg_bindist_fedora_options::fedora_stat_langreq_, + &pkg_bindist_fedora_options::fedora_stat_langreq_specified_ >; + _cli_pkg_bindist_fedora_options_map_["--fedora-main-extrareq"] = + &::bpkg::cli::thunk< pkg_bindist_fedora_options, strings, &pkg_bindist_fedora_options::fedora_main_extrareq_, + &pkg_bindist_fedora_options::fedora_main_extrareq_specified_ >; + _cli_pkg_bindist_fedora_options_map_["--fedora-devel-extrareq"] = + &::bpkg::cli::thunk< pkg_bindist_fedora_options, strings, &pkg_bindist_fedora_options::fedora_devel_extrareq_, + &pkg_bindist_fedora_options::fedora_devel_extrareq_specified_ >; + _cli_pkg_bindist_fedora_options_map_["--fedora-stat-extrareq"] = + &::bpkg::cli::thunk< pkg_bindist_fedora_options, strings, &pkg_bindist_fedora_options::fedora_stat_extrareq_, + &pkg_bindist_fedora_options::fedora_stat_extrareq_specified_ >; + } + }; + + static _cli_pkg_bindist_fedora_options_map_init _cli_pkg_bindist_fedora_options_map_init_; + + bool pkg_bindist_fedora_options:: + _parse (const char* o, ::bpkg::cli::scanner& s) + { + _cli_pkg_bindist_fedora_options_map::const_iterator i (_cli_pkg_bindist_fedora_options_map_.find (o)); + + if (i != _cli_pkg_bindist_fedora_options_map_.end ()) + { + (*(i->second)) (*this, s); + return true; + } + + return false; + } + + bool pkg_bindist_fedora_options:: + _parse (::bpkg::cli::scanner& s, + ::bpkg::cli::unknown_mode opt_mode, + ::bpkg::cli::unknown_mode arg_mode) + { + // Can't skip combined flags (--no-combined-flags). + // + assert (opt_mode != ::bpkg::cli::unknown_mode::skip); + + bool r = false; + bool opt = true; + + while (s.more ()) + { + const char* o = s.peek (); + + if (std::strcmp (o, "--") == 0) + { + opt = false; + } + + if (opt) + { + if (_parse (o, s)) + { + r = true; + continue; + } + + if (std::strncmp (o, "-", 1) == 0 && o[1] != '\0') + { + // Handle combined option values. + // + std::string co; + if (const char* v = std::strchr (o, '=')) + { + co.assign (o, 0, v - o); + ++v; + + int ac (2); + char* av[] = + { + const_cast<char*> (co.c_str ()), + const_cast<char*> (v) + }; + + ::bpkg::cli::argv_scanner ns (0, ac, av); + + if (_parse (co.c_str (), ns)) + { + // Parsed the option but not its value? + // + if (ns.end () != 2) + throw ::bpkg::cli::invalid_value (co, v); + + s.next (); + r = true; + continue; + } + else + { + // Set the unknown option and fall through. + // + o = co.c_str (); + } + } + + // Handle combined flags. + // + char cf[3]; + { + const char* p = o + 1; + for (; *p != '\0'; ++p) + { + if (!((*p >= 'a' && *p <= 'z') || + (*p >= 'A' && *p <= 'Z') || + (*p >= '0' && *p <= '9'))) + break; + } + + if (*p == '\0') + { + for (p = o + 1; *p != '\0'; ++p) + { + std::strcpy (cf, "-"); + cf[1] = *p; + cf[2] = '\0'; + + int ac (1); + char* av[] = + { + cf + }; + + ::bpkg::cli::argv_scanner ns (0, ac, av); + + if (!_parse (cf, ns)) + break; + } + + if (*p == '\0') + { + // All handled. + // + s.next (); + r = true; + continue; + } + else + { + // Set the unknown option and fall through. + // + o = cf; + } + } + } + + switch (opt_mode) + { + case ::bpkg::cli::unknown_mode::skip: + { + s.skip (); + r = true; + continue; + } + case ::bpkg::cli::unknown_mode::stop: + { + break; + } + case ::bpkg::cli::unknown_mode::fail: + { + throw ::bpkg::cli::unknown_option (o); + } + } + + break; + } + } + + switch (arg_mode) + { + case ::bpkg::cli::unknown_mode::skip: + { + s.skip (); + r = true; + continue; + } + case ::bpkg::cli::unknown_mode::stop: + { + break; + } + case ::bpkg::cli::unknown_mode::fail: + { + throw ::bpkg::cli::unknown_argument (o); + } + } + + break; + } + + return r; + } + + // pkg_bindist_archive_options + // + + pkg_bindist_archive_options:: + pkg_bindist_archive_options () + : archive_prepare_only_ (), + archive_type_ (), + archive_type_specified_ (false), + archive_lang_ (), + archive_lang_specified_ (false), + archive_lang_impl_ (), + archive_lang_impl_specified_ (false), + archive_no_cpu_ (), + archive_no_os_ (), + archive_build_meta_ (), + archive_build_meta_specified_ (false), + archive_install_root_ (), + archive_install_root_specified_ (false), + archive_install_config_ (), + archive_split_ (), + archive_split_specified_ (false) + { + } + + bool pkg_bindist_archive_options:: + parse (int& argc, + char** argv, + bool erase, + ::bpkg::cli::unknown_mode opt, + ::bpkg::cli::unknown_mode arg) + { + ::bpkg::cli::argv_scanner s (argc, argv, erase); + bool r = _parse (s, opt, arg); + return r; + } + + bool pkg_bindist_archive_options:: + parse (int start, + int& argc, + char** argv, + bool erase, + ::bpkg::cli::unknown_mode opt, + ::bpkg::cli::unknown_mode arg) + { + ::bpkg::cli::argv_scanner s (start, argc, argv, erase); + bool r = _parse (s, opt, arg); + return r; + } + + bool pkg_bindist_archive_options:: + parse (int& argc, + char** argv, + int& end, + bool erase, + ::bpkg::cli::unknown_mode opt, + ::bpkg::cli::unknown_mode arg) + { + ::bpkg::cli::argv_scanner s (argc, argv, erase); + bool r = _parse (s, opt, arg); + end = s.end (); + return r; + } + + bool pkg_bindist_archive_options:: + parse (int start, + int& argc, + char** argv, + int& end, + bool erase, + ::bpkg::cli::unknown_mode opt, + ::bpkg::cli::unknown_mode arg) + { + ::bpkg::cli::argv_scanner s (start, argc, argv, erase); + bool r = _parse (s, opt, arg); + end = s.end (); + return r; + } + + bool pkg_bindist_archive_options:: + parse (::bpkg::cli::scanner& s, + ::bpkg::cli::unknown_mode opt, + ::bpkg::cli::unknown_mode arg) + { + bool r = _parse (s, opt, arg); + return r; + } + + void pkg_bindist_archive_options:: + merge (const pkg_bindist_archive_options& a) + { + CLI_POTENTIALLY_UNUSED (a); + + if (a.archive_prepare_only_) + { + ::bpkg::cli::parser< bool>::merge ( + this->archive_prepare_only_, a.archive_prepare_only_); + } + + if (a.archive_type_specified_) + { + ::bpkg::cli::parser< strings>::merge ( + this->archive_type_, a.archive_type_); + this->archive_type_specified_ = true; + } + + if (a.archive_lang_specified_) + { + ::bpkg::cli::parser< std::multimap<string, string>>::merge ( + this->archive_lang_, a.archive_lang_); + this->archive_lang_specified_ = true; + } + + if (a.archive_lang_impl_specified_) + { + ::bpkg::cli::parser< std::multimap<string, string>>::merge ( + this->archive_lang_impl_, a.archive_lang_impl_); + this->archive_lang_impl_specified_ = true; + } + + if (a.archive_no_cpu_) + { + ::bpkg::cli::parser< bool>::merge ( + this->archive_no_cpu_, a.archive_no_cpu_); + } + + if (a.archive_no_os_) + { + ::bpkg::cli::parser< bool>::merge ( + this->archive_no_os_, a.archive_no_os_); + } + + if (a.archive_build_meta_specified_) + { + ::bpkg::cli::parser< string>::merge ( + this->archive_build_meta_, a.archive_build_meta_); + this->archive_build_meta_specified_ = true; + } + + if (a.archive_install_root_specified_) + { + ::bpkg::cli::parser< dir_path>::merge ( + this->archive_install_root_, a.archive_install_root_); + this->archive_install_root_specified_ = true; + } + + if (a.archive_install_config_) + { + ::bpkg::cli::parser< bool>::merge ( + this->archive_install_config_, a.archive_install_config_); + } + + if (a.archive_split_specified_) + { + ::bpkg::cli::parser< std::map<string, string>>::merge ( + this->archive_split_, a.archive_split_); + this->archive_split_specified_ = true; + } + } + + ::bpkg::cli::usage_para pkg_bindist_archive_options:: + print_usage (::std::ostream& os, ::bpkg::cli::usage_para p) + { + CLI_POTENTIALLY_UNUSED (os); + + if (p != ::bpkg::cli::usage_para::none) + os << ::std::endl; + + os << "\033[1mARCHIVE DESCRIPTION\033[0m" << ::std::endl + << ::std::endl + << "The installation archive binary packages are generated by invoking the \033[1mbuild2\033[0m" << ::std::endl + << "build system on the required packages directly in their \033[1mbpkg\033[0m configuration" << ::std::endl + << "locations and installing them into the binary package directory using the" << ::std::endl + << "\033[1mconfig.install.chroot\033[0m mechanism. Then this directory is packaged with \033[1mtar\033[0m or" << ::std::endl + << "\033[1mzip\033[0m to produce one or more binary package archives." << ::std::endl + << ::std::endl + << "The generation of installation archive packages is never the default and should" << ::std::endl + << "be requested explicitly with the \033[1m--distribution=archive\033[0m option. The" << ::std::endl + << "installation directory layout and the package archives to generate can be" << ::std::endl + << "specified with the \033[1m--archive-install-*\033[0m and \033[1m--archive-type\033[0m options (refer to" << ::std::endl + << "their documentation for defaults)." << ::std::endl + << ::std::endl + << "The binary package directory (the top-level directory inside the archive) as" << ::std::endl + << "well as the archive file base (the file name without the extension) are the" << ::std::endl + << "same and have the following form:" << ::std::endl + << ::std::endl + << "\033[4mpackage\033[0m-\033[4mversion\033[0m-\033[4mbuild_metadata\033[0m\033[0m" << ::std::endl + << ::std::endl + << "Where \033[4mpackage\033[0m is the package name and \033[4mversion\033[0m is the \033[1mbpkg\033[0m package version." << ::std::endl + << "Unless overridden with the \033[1m--archive-build-meta\033[0m option, \033[4mbuild_metadata\033[0m has the" << ::std::endl + << "following form:" << ::std::endl + << ::std::endl + << "\033[4mcpu\033[0m-\033[4mos\033[0m[-\033[4mlangrt\033[0m...]\033[0m" << ::std::endl + << ::std::endl + << "Where \033[4mcpu\033[0m is the target CPU (for example, \033[1mx86_64\033[0m or \033[1maarch64\033[0m; omitted if" << ::std::endl + << "\033[1m--archive-no-cpu\033[0m is specified), \033[4mos\033[0m is the \033[1mID\033[0m and \033[1mVERSION_ID\033[0m components from" << ::std::endl + << "\033[1mos-release(5)\033[0m (or equivalent, for example, \033[1mdebian11\033[0m or \033[1mwindows10\033[0m; omitted if" << ::std::endl + << "\033[1m--archive-no-os\033[0m is specified), and \033[4mlangrt\033[0m are the language runtimes as mapped" << ::std::endl + << "by the \033[1m--archive-lang*\033[0m options (for example, \033[1mgcc12\033[0m or \033[1mmsvc17.4\033[0m)." << ::std::endl + << ::std::endl + << "For example, given the following invocation on Debian 11 running on \033[1mx86_64\033[0m:" << ::std::endl + << ::std::endl + << "bpkg build libhello" << ::std::endl + << "bpkg test libhello" << ::std::endl + << "bpkg bindist \\" << ::std::endl + << " -o /tmp/output/ \\" << ::std::endl + << " --distribution=archive \\" << ::std::endl + << " --archive-lang cc=gcc12 \\" << ::std::endl + << " libhello" << ::std::endl + << ::std::endl + << "We will end up with the package archive in the following form:" << ::std::endl + << ::std::endl + << "libhello-1.2.3-x86_64-debian11-gcc12.tar.xz" << ::std::endl + << ::std::endl + << "The recommended language runtime id format is the runtime name followed by the" << ::std::endl + << "version, for example, \033[1mgcc12\033[0m or \033[1mmsvc17.4\033[0m. Note that its purpose is not to" << ::std::endl + << "provide a precise specification of requirements but rather to help the user of" << ::std::endl + << "a binary package to pick the appropriate variant. Refer to the \033[1m--archive-lang*\033[0m" << ::std::endl + << "options documentation for details on the mapping semantics." << ::std::endl + << ::std::endl + << "Instead of mapping languages individually you can specify entire build metadata" << ::std::endl + << "as a single value with the \033[1m--archive-build-meta\033[0m (it is also possible to add" << ::std::endl + << "additional metadata; see the option documentation for details). For example:" << ::std::endl + << ::std::endl + << "bpkg bindist \\" << ::std::endl + << " -o /tmp/output/ \\" << ::std::endl + << " --distribution=archive \\" << ::std::endl + << " --archive-build-meta=x86_64-linux-glibc" << ::std::endl + << " libhello" << ::std::endl + << ::std::endl + << "This will produce the package archive in the following form:" << ::std::endl + << ::std::endl + << "libhello-1.2.3-x86_64-linux-glibc.tar.xz" << ::std::endl + << ::std::endl + << "To install the binary package from archive simply unpack it using \033[1mtar\033[0m or \033[1mzip\033[0m." << ::std::endl + << "You can use the \033[1m--strip-components\033[0m \033[1mtar\033[0m option to remove the top-level package" << ::std::endl + << "directory (the same can be achieved for \033[1mzip\033[0m archives by using \033[1mbsdtar\033[0m on" << ::std::endl + << "Windows). For example, to unpack the package contents so that they end up in" << ::std::endl + << "\033[1m/usr/local/\033[0m:" << ::std::endl + << ::std::endl + << "sudo tar -xf libhello-1.2.3-x86_64-debian11-gcc12.tar.xz \\" << ::std::endl + << " -C / --strip-components=1" << ::std::endl + << ::std::endl + << "If you expect the binary package to be unpacked into a directory other than its" << ::std::endl + << "original installation directory (\033[1m--archive-install-root\033[0m), then it's recommended" << ::std::endl + << "to make it relocatable by specifying the \033[1mconfig.install.relocatable=true\033[0m" << ::std::endl + << "configuration variable. For example:" << ::std::endl + << ::std::endl + << "bpkg bindist \\" << ::std::endl + << " ... \\" << ::std::endl + << " config.install.relocatable=true \\" << ::std::endl + << " libhello" << ::std::endl + << ::std::endl + << "Note that not all source packages support relocatable installation (see" << ::std::endl + << "Rolocatable Installation (b#install-reloc) for details)." << ::std::endl + << ::std::endl + << "Another mechanism that can useful when generating archive packages is the" << ::std::endl + << "ability to filter the files being installed. This, for example, can be used to" << ::std::endl + << "create binary packages that don't contain any development-related files. See" << ::std::endl + << "Installation Filtering (b#install-filter) for details. See also the" << ::std::endl + << "\033[1m--archive-split\033[0m option." << ::std::endl + << ::std::endl + << "The installation archive package can be generated for a target other than the" << ::std::endl + << "host by specifying the target triplet with the \033[1m--architecture\033[0m option. In this" << ::std::endl + << "case the \033[1mbpkg\033[0m configuration is assumed to be appropriately configured for" << ::std::endl + << "cross-compiling to the specified target. You will also need to explicitly" << ::std::endl + << "specify the \033[1m--archive-install-root\033[0m option (or \033[1m--archive-install-config\033[0m) as well" << ::std::endl + << "as the \033[1m--os-release-id\033[0m option (and likely want to specify other \033[1m--os-release-*\033[0m" << ::std::endl + << "options). For example, for cross-compiling from Linux to Windows using the" << ::std::endl + << "MinGW GCC toolchain:" << ::std::endl + << ::std::endl + << "bpkg bindist \\" << ::std::endl + << " --distribution=archive \\" << ::std::endl + << " --architecture=x86_64-w64-mingw32 \\" << ::std::endl + << " --os-release-id=windows \\" << ::std::endl + << " --os-release-name=Windows \\" << ::std::endl + << " --os-release-version-id=10 \\" << ::std::endl + << " --archive-install-root / \\" << ::std::endl + << " --archive-lang cc=mingw_w64_gcc12 \\" << ::std::endl + << " ..." << ::std::endl; + + os << std::endl + << "\033[1mPKG-BINDIST ARCHIVE OPTIONS\033[0m" << ::std::endl; + + os << std::endl + << "\033[1m--archive-prepare-only\033[0m Prepare all the package contents but do not create" << ::std::endl + << " the binary package archive, printing its directory" << ::std::endl + << " instead unless requested to be quiet. Implies" << ::std::endl + << " \033[1m--keep-output\033[0m." << ::std::endl; + + os << std::endl + << "\033[1m--archive-type\033[0m \033[4mext\033[0m Archive type to create specified as a file extension," << ::std::endl + << " for example, \033[1mtar.xz\033[0m, \033[1mtar.gz\033[0m, \033[1mtar\033[0m, \033[1mzip\033[0m. Repeat this" << ::std::endl + << " option to generate multiple archive types. If" << ::std::endl + << " unspecified, then a default type appropriate for the" << ::std::endl + << " target operating system is used, currently \033[1mzip\033[0m for" << ::std::endl + << " Windows and \033[1mtar.xz\033[0m for POSIX. Note, however, that" << ::std::endl + << " these defaults may change in the future." << ::std::endl; + + os << std::endl + << "\033[1m--archive-lang\033[0m \033[4mln\033[0m=\033[4mrt\033[0m Map interface language name \033[4mln\033[0m to runtime id \033[4mrt\033[0m. If" << ::std::endl + << " no mapping is found for an interface language in this" << ::std::endl + << " map, then fallback to the \033[1m--archive-lang-impl\033[0m map. If" << ::std::endl + << " still no mapping is found, then fail. If the" << ::std::endl + << " information about an interface language is" << ::std::endl + << " unimportant and should be ignored, then empty runtime" << ::std::endl + << " id can be specified. Note that the mapping specified" << ::std::endl + << " with this option is only considered if the package" << ::std::endl + << " type is a library (for other package types all" << ::std::endl + << " languages used are implementation). Note also that" << ::std::endl + << " multiple runtime ids specified for the same language" << ::std::endl + << " are combined except for an empty id, which is treated" << ::std::endl + << " as a request to clear previous entries." << ::std::endl; + + os << std::endl + << "\033[1m--archive-lang-impl\033[0m \033[4mln\033[0m=\033[4mrt\033[0m Map implementation language name \033[4mln\033[0m to runtime id \033[4mrt\033[0m." << ::std::endl + << " If no mapping is found for an implementation language" << ::std::endl + << " in this map, then assume the information about this" << ::std::endl + << " implementation language is unimportant and ignore it" << ::std::endl + << " (examples of such cases include static linking as" << ::std::endl + << " well as a language runtime that is always present)." << ::std::endl + << " See \033[1m--archive-lang\033[0m for background." << ::std::endl; + + os << std::endl + << "\033[1m--archive-no-cpu\033[0m Assume the package is CPU architecture-independent" << ::std::endl + << " and omit it from the binary package directory name" << ::std::endl + << " and archive file base." << ::std::endl; + + os << std::endl + << "\033[1m--archive-no-os\033[0m Assume the package is operating system-independent" << ::std::endl + << " and omit it from the binary package directory name" << ::std::endl + << " and archive file base." << ::std::endl; + + os << std::endl + << "\033[1m--archive-build-meta\033[0m \033[4mdata\033[0m Alternative or additional build metadata to include" << ::std::endl + << " after the version in the binary package directory and" << ::std::endl + << " file names. If the specified value starts/ends with" << ::std::endl + << " \033[1m+\033[0m then the value (with \033[1m+\033[0m removed) is added" << ::std::endl + << " after/before the default metadata. Otherwise it is" << ::std::endl + << " used as is instead of the default metadata. If empty" << ::std::endl + << " value is specified, then no build metadata is" << ::std::endl + << " included." << ::std::endl; + + os << std::endl + << "\033[1m--archive-install-root\033[0m \033[4md\033[0m Alternative installation root directory. The default" << ::std::endl + << " is \033[1m/usr/local/\033[0m on POSIX and \033[1mC:\\\033[0m\033[4mproject\033[0m\033[1m\\\033[0m\033[0m on Windows," << ::std::endl + << " where \033[4mproject\033[0m is the \033[1mproject\033[0m" << ::std::endl + << " (bpkg#manifest-package-project) package manifest" << ::std::endl + << " value." << ::std::endl; + + os << std::endl + << "\033[1m--archive-install-config\033[0m Use the installation directory layout" << ::std::endl + << " (\033[1mconfig.install.*\033[0m variables) as configured instead of" << ::std::endl + << " overriding them with defaults appropriate for the" << ::std::endl + << " target operating system. Note that this includes" << ::std::endl + << " \033[1mconfig.install.private\033[0m and \033[1mconfig.bin.rpath\033[0m if needed" << ::std::endl + << " for a private installation. Note also that the" << ::std::endl + << " \033[1mconfig.install.root\033[0m value is still overridden with" << ::std::endl + << " the \033[1m--archive-install-root\033[0m option value if specified." << ::std::endl; + + os << std::endl + << "\033[1m--archive-split\033[0m \033[4mkey\033[0m=\033[4mfilt\033[0m Split the installation into multiple binary packages." << ::std::endl + << " Specifically, for each \033[4mkey\033[0m=\033[4mfilt\033[0m pair, perform the" << ::std::endl + << " \033[1minstall\033[0m operation with \033[1mconfig.install.filter=\033[0m\033[4mfilt\033[0m\033[0m and" << ::std::endl + << " package the resulting files as" << ::std::endl + << " \033[4mpackage-key-version-build_metadata\033[0m omitting the \033[4m-key\033[0m" << ::std::endl + << " part if \033[4mkey\033[0m is empty. Note that wildcard patterns in" << ::std::endl + << " \033[4mfilt\033[0m must be quoted. See Installation Filtering" << ::std::endl + << " (b#install-filter) for background." << ::std::endl; + + p = ::bpkg::cli::usage_para::option; + + return p; + } + + typedef + std::map<std::string, void (*) (pkg_bindist_archive_options&, ::bpkg::cli::scanner&)> + _cli_pkg_bindist_archive_options_map; + + static _cli_pkg_bindist_archive_options_map _cli_pkg_bindist_archive_options_map_; + + struct _cli_pkg_bindist_archive_options_map_init + { + _cli_pkg_bindist_archive_options_map_init () + { + _cli_pkg_bindist_archive_options_map_["--archive-prepare-only"] = + &::bpkg::cli::thunk< pkg_bindist_archive_options, &pkg_bindist_archive_options::archive_prepare_only_ >; + _cli_pkg_bindist_archive_options_map_["--archive-type"] = + &::bpkg::cli::thunk< pkg_bindist_archive_options, strings, &pkg_bindist_archive_options::archive_type_, + &pkg_bindist_archive_options::archive_type_specified_ >; + _cli_pkg_bindist_archive_options_map_["--archive-lang"] = + &::bpkg::cli::thunk< pkg_bindist_archive_options, std::multimap<string, string>, &pkg_bindist_archive_options::archive_lang_, + &pkg_bindist_archive_options::archive_lang_specified_ >; + _cli_pkg_bindist_archive_options_map_["--archive-lang-impl"] = + &::bpkg::cli::thunk< pkg_bindist_archive_options, std::multimap<string, string>, &pkg_bindist_archive_options::archive_lang_impl_, + &pkg_bindist_archive_options::archive_lang_impl_specified_ >; + _cli_pkg_bindist_archive_options_map_["--archive-no-cpu"] = + &::bpkg::cli::thunk< pkg_bindist_archive_options, &pkg_bindist_archive_options::archive_no_cpu_ >; + _cli_pkg_bindist_archive_options_map_["--archive-no-os"] = + &::bpkg::cli::thunk< pkg_bindist_archive_options, &pkg_bindist_archive_options::archive_no_os_ >; + _cli_pkg_bindist_archive_options_map_["--archive-build-meta"] = + &::bpkg::cli::thunk< pkg_bindist_archive_options, string, &pkg_bindist_archive_options::archive_build_meta_, + &pkg_bindist_archive_options::archive_build_meta_specified_ >; + _cli_pkg_bindist_archive_options_map_["--archive-install-root"] = + &::bpkg::cli::thunk< pkg_bindist_archive_options, dir_path, &pkg_bindist_archive_options::archive_install_root_, + &pkg_bindist_archive_options::archive_install_root_specified_ >; + _cli_pkg_bindist_archive_options_map_["--archive-install-config"] = + &::bpkg::cli::thunk< pkg_bindist_archive_options, &pkg_bindist_archive_options::archive_install_config_ >; + _cli_pkg_bindist_archive_options_map_["--archive-split"] = + &::bpkg::cli::thunk< pkg_bindist_archive_options, std::map<string, string>, &pkg_bindist_archive_options::archive_split_, + &pkg_bindist_archive_options::archive_split_specified_ >; + } + }; + + static _cli_pkg_bindist_archive_options_map_init _cli_pkg_bindist_archive_options_map_init_; + + bool pkg_bindist_archive_options:: + _parse (const char* o, ::bpkg::cli::scanner& s) + { + _cli_pkg_bindist_archive_options_map::const_iterator i (_cli_pkg_bindist_archive_options_map_.find (o)); + + if (i != _cli_pkg_bindist_archive_options_map_.end ()) + { + (*(i->second)) (*this, s); + return true; + } + + return false; + } + + bool pkg_bindist_archive_options:: + _parse (::bpkg::cli::scanner& s, + ::bpkg::cli::unknown_mode opt_mode, + ::bpkg::cli::unknown_mode arg_mode) + { + // Can't skip combined flags (--no-combined-flags). + // + assert (opt_mode != ::bpkg::cli::unknown_mode::skip); + + bool r = false; + bool opt = true; + + while (s.more ()) + { + const char* o = s.peek (); + + if (std::strcmp (o, "--") == 0) + { + opt = false; + } + + if (opt) + { + if (_parse (o, s)) + { + r = true; + continue; + } + + if (std::strncmp (o, "-", 1) == 0 && o[1] != '\0') + { + // Handle combined option values. + // + std::string co; + if (const char* v = std::strchr (o, '=')) + { + co.assign (o, 0, v - o); + ++v; + + int ac (2); + char* av[] = + { + const_cast<char*> (co.c_str ()), + const_cast<char*> (v) + }; + + ::bpkg::cli::argv_scanner ns (0, ac, av); + + if (_parse (co.c_str (), ns)) + { + // Parsed the option but not its value? + // + if (ns.end () != 2) + throw ::bpkg::cli::invalid_value (co, v); + + s.next (); + r = true; + continue; + } + else + { + // Set the unknown option and fall through. + // + o = co.c_str (); + } + } + + // Handle combined flags. + // + char cf[3]; + { + const char* p = o + 1; + for (; *p != '\0'; ++p) + { + if (!((*p >= 'a' && *p <= 'z') || + (*p >= 'A' && *p <= 'Z') || + (*p >= '0' && *p <= '9'))) + break; + } + + if (*p == '\0') + { + for (p = o + 1; *p != '\0'; ++p) + { + std::strcpy (cf, "-"); + cf[1] = *p; + cf[2] = '\0'; + + int ac (1); + char* av[] = + { + cf + }; + + ::bpkg::cli::argv_scanner ns (0, ac, av); + + if (!_parse (cf, ns)) + break; + } + + if (*p == '\0') + { + // All handled. + // + s.next (); + r = true; + continue; + } + else + { + // Set the unknown option and fall through. + // + o = cf; + } + } + } + + switch (opt_mode) + { + case ::bpkg::cli::unknown_mode::skip: + { + s.skip (); + r = true; + continue; + } + case ::bpkg::cli::unknown_mode::stop: + { + break; + } + case ::bpkg::cli::unknown_mode::fail: + { + throw ::bpkg::cli::unknown_option (o); + } + } + + break; + } + } + + switch (arg_mode) + { + case ::bpkg::cli::unknown_mode::skip: + { + s.skip (); + r = true; + continue; + } + case ::bpkg::cli::unknown_mode::stop: + { + break; + } + case ::bpkg::cli::unknown_mode::fail: + { + throw ::bpkg::cli::unknown_argument (o); + } + } + + break; + } + + return r; + } + + // pkg_bindist_options + // + + pkg_bindist_options:: + pkg_bindist_options () + { + } + + bool pkg_bindist_options:: + parse (int& argc, + char** argv, + bool erase, + ::bpkg::cli::unknown_mode opt, + ::bpkg::cli::unknown_mode arg) + { + ::bpkg::cli::argv_scanner s (argc, argv, erase); + bool r = _parse (s, opt, arg); + return r; + } + + bool pkg_bindist_options:: + parse (int start, + int& argc, + char** argv, + bool erase, + ::bpkg::cli::unknown_mode opt, + ::bpkg::cli::unknown_mode arg) + { + ::bpkg::cli::argv_scanner s (start, argc, argv, erase); + bool r = _parse (s, opt, arg); + return r; + } + + bool pkg_bindist_options:: + parse (int& argc, + char** argv, + int& end, + bool erase, + ::bpkg::cli::unknown_mode opt, + ::bpkg::cli::unknown_mode arg) + { + ::bpkg::cli::argv_scanner s (argc, argv, erase); + bool r = _parse (s, opt, arg); + end = s.end (); + return r; + } + + bool pkg_bindist_options:: + parse (int start, + int& argc, + char** argv, + int& end, + bool erase, + ::bpkg::cli::unknown_mode opt, + ::bpkg::cli::unknown_mode arg) + { + ::bpkg::cli::argv_scanner s (start, argc, argv, erase); + bool r = _parse (s, opt, arg); + end = s.end (); + return r; + } + + bool pkg_bindist_options:: + parse (::bpkg::cli::scanner& s, + ::bpkg::cli::unknown_mode opt, + ::bpkg::cli::unknown_mode arg) + { + bool r = _parse (s, opt, arg); + return r; + } + + void pkg_bindist_options:: + merge (const pkg_bindist_options& a) + { + CLI_POTENTIALLY_UNUSED (a); + + // pkg_bindist_common_options base + // + ::bpkg::pkg_bindist_common_options::merge (a); + + // pkg_bindist_debian_options base + // + ::bpkg::pkg_bindist_debian_options::merge (a); + + // pkg_bindist_fedora_options base + // + ::bpkg::pkg_bindist_fedora_options::merge (a); + + // pkg_bindist_archive_options base + // + ::bpkg::pkg_bindist_archive_options::merge (a); + } + + ::bpkg::cli::usage_para pkg_bindist_options:: + print_usage (::std::ostream& os, ::bpkg::cli::usage_para p) + { + CLI_POTENTIALLY_UNUSED (os); + + return p; + } + + typedef + std::map<std::string, void (*) (pkg_bindist_options&, ::bpkg::cli::scanner&)> + _cli_pkg_bindist_options_map; + + static _cli_pkg_bindist_options_map _cli_pkg_bindist_options_map_; + + struct _cli_pkg_bindist_options_map_init + { + _cli_pkg_bindist_options_map_init () + { + } + }; + + static _cli_pkg_bindist_options_map_init _cli_pkg_bindist_options_map_init_; + + bool pkg_bindist_options:: + _parse (const char* o, ::bpkg::cli::scanner& s) + { + _cli_pkg_bindist_options_map::const_iterator i (_cli_pkg_bindist_options_map_.find (o)); + + if (i != _cli_pkg_bindist_options_map_.end ()) + { + (*(i->second)) (*this, s); + return true; + } + + // pkg_bindist_common_options base + // + if (::bpkg::pkg_bindist_common_options::_parse (o, s)) + return true; + + // pkg_bindist_debian_options base + // + if (::bpkg::pkg_bindist_debian_options::_parse (o, s)) + return true; + + // pkg_bindist_fedora_options base + // + if (::bpkg::pkg_bindist_fedora_options::_parse (o, s)) + return true; + + // pkg_bindist_archive_options base + // + if (::bpkg::pkg_bindist_archive_options::_parse (o, s)) + return true; + + return false; + } + + bool pkg_bindist_options:: + _parse (::bpkg::cli::scanner& s, + ::bpkg::cli::unknown_mode opt_mode, + ::bpkg::cli::unknown_mode arg_mode) + { + // Can't skip combined flags (--no-combined-flags). + // + assert (opt_mode != ::bpkg::cli::unknown_mode::skip); + + bool r = false; + bool opt = true; + + while (s.more ()) + { + const char* o = s.peek (); + + if (std::strcmp (o, "--") == 0) + { + opt = false; + } + + if (opt) + { + if (_parse (o, s)) + { + r = true; + continue; + } + + if (std::strncmp (o, "-", 1) == 0 && o[1] != '\0') + { + // Handle combined option values. + // + std::string co; + if (const char* v = std::strchr (o, '=')) + { + co.assign (o, 0, v - o); + ++v; + + int ac (2); + char* av[] = + { + const_cast<char*> (co.c_str ()), + const_cast<char*> (v) + }; + + ::bpkg::cli::argv_scanner ns (0, ac, av); + + if (_parse (co.c_str (), ns)) + { + // Parsed the option but not its value? + // + if (ns.end () != 2) + throw ::bpkg::cli::invalid_value (co, v); + + s.next (); + r = true; + continue; + } + else + { + // Set the unknown option and fall through. + // + o = co.c_str (); + } + } + + // Handle combined flags. + // + char cf[3]; + { + const char* p = o + 1; + for (; *p != '\0'; ++p) + { + if (!((*p >= 'a' && *p <= 'z') || + (*p >= 'A' && *p <= 'Z') || + (*p >= '0' && *p <= '9'))) + break; + } + + if (*p == '\0') + { + for (p = o + 1; *p != '\0'; ++p) + { + std::strcpy (cf, "-"); + cf[1] = *p; + cf[2] = '\0'; + + int ac (1); + char* av[] = + { + cf + }; + + ::bpkg::cli::argv_scanner ns (0, ac, av); + + if (!_parse (cf, ns)) + break; + } + + if (*p == '\0') + { + // All handled. + // + s.next (); + r = true; + continue; + } + else + { + // Set the unknown option and fall through. + // + o = cf; + } + } + } + + switch (opt_mode) + { + case ::bpkg::cli::unknown_mode::skip: + { + s.skip (); + r = true; + continue; + } + case ::bpkg::cli::unknown_mode::stop: + { + break; + } + case ::bpkg::cli::unknown_mode::fail: + { + throw ::bpkg::cli::unknown_option (o); + } + } + + break; + } + } + + switch (arg_mode) + { + case ::bpkg::cli::unknown_mode::skip: + { + s.skip (); + r = true; + continue; + } + case ::bpkg::cli::unknown_mode::stop: + { + break; + } + case ::bpkg::cli::unknown_mode::fail: + { + throw ::bpkg::cli::unknown_argument (o); + } + } + + break; + } + + return r; + } +} + +namespace bpkg +{ + ::bpkg::cli::usage_para + print_bpkg_pkg_bindist_usage (::std::ostream& os, ::bpkg::cli::usage_para p) + { + CLI_POTENTIALLY_UNUSED (os); + + if (p != ::bpkg::cli::usage_para::none) + os << ::std::endl; + + os << "\033[1mSYNOPSIS\033[0m" << ::std::endl + << ::std::endl + << "\033[1mbpkg pkg-bindist\033[0m|\033[1mbindist\033[0m [\033[1m--output-root\033[0m|\033[1m-o\033[0m \033[4mdir\033[0m] [\033[4moptions\033[0m] [\033[4mvars\033[0m] \033[4mpkg\033[0m...\033[0m" << ::std::endl + << ::std::endl + << "\033[1mDESCRIPTION\033[0m" << ::std::endl + << ::std::endl + << "The \033[1mpkg-bindist\033[0m command generates a binary distribution package for the" << ::std::endl + << "specified package. If additional packages are specified, then they are bundled" << ::std::endl + << "in the same distribution package. All the specified packages must have been" << ::std::endl + << "previously configured with \033[1mbpkg-pkg-build(1)\033[0m or \033[1mbpkg-pkg-configure(1)\033[0m. For some" << ::std::endl + << "system package managers a directory for intermediate files and subdirectories" << ::std::endl + << "as well as the resulting binary package may have to be specified explicitly" << ::std::endl + << "with the \033[1m--output-root\033[0m|\033[1m-o\033[0m\033[0m option." << ::std::endl + << ::std::endl + << "Underneath, this command roughly performs the following steps: First it" << ::std::endl + << "installs the specified packages similar to the \033[1mbpkg-pkg-install(1)\033[0m command" << ::std::endl + << "except that it may override the installation locations (via the" << ::std::endl + << "\033[1mconfig.install.*\033[0m variables) to match the distribution's layout. Then it" << ::std::endl + << "generates any necessary distribution package metadata files based on the" << ::std::endl + << "information from the package \033[1mmanifest\033[0m files. Finally, it invokes the" << ::std::endl + << "distribution-specific command to produce the binary package. Unless overridden" << ::std::endl + << "with the \033[1m--architecture\033[0m and \033[1m--distribution\033[0m options, the binary package is" << ::std::endl + << "generated for the host architecture using the host's standard system package" << ::std::endl + << "manager. Additional command line variables (\033[4mvars\033[0m, normally \033[1mconfig.*\033[0m) can be" << ::std::endl + << "passed to the build system during the installation step. See the following" << ::std::endl + << "distribution-specific description sections below for details and invocation" << ::std::endl + << "examples:" << ::std::endl + << ::std::endl + << "DEBIAN DESCRIPTION" << ::std::endl + << ::std::endl + << "FEDORA DESCRIPTION" << ::std::endl + << ::std::endl + << "ARCHIVE DESCRIPTION" << ::std::endl + << ::std::endl + << "The specified packages may have dependencies and the default behavior is to not" << ::std::endl + << "bundle them but rather to specify them as dependencies in the corresponding" << ::std::endl + << "distribution package metadata, if applicable. This default behavior can be" << ::std::endl + << "overridden with the \033[1m--recursive\033[0m option (see the option description for the" << ::std::endl + << "available modes). Note, however, that dependencies that are satisfied by system" << ::std::endl + << "packages are always specified as dependencies in the distribution package" << ::std::endl + << "metadata (if applicable)." << ::std::endl; + + p = ::bpkg::pkg_bindist_common_options::print_usage (os, ::bpkg::cli::usage_para::text); + + p = ::bpkg::pkg_bindist_debian_options::print_usage (os, p); + + p = ::bpkg::pkg_bindist_fedora_options::print_usage (os, p); + + p = ::bpkg::pkg_bindist_archive_options::print_usage (os, p); + + if (p != ::bpkg::cli::usage_para::none) + os << ::std::endl; + + os << "\033[1mSTRUCTURED RESULT\033[0m" << ::std::endl + << ::std::endl + << "Instead of printing to \033[1mstderr\033[0m the list of generated binary packages in a format" << ::std::endl + << "more suitable for human consumption, the \033[1mpkg-bindist\033[0m command can be instructed" << ::std::endl + << "to write it to \033[1mstdout\033[0m in a machine-readable form by specifying the" << ::std::endl + << "\033[1m--structured-result\033[0m option. Currently, the only recognized format value for" << ::std::endl + << "this option is \033[1mjson\033[0m with the output being a JSON object that is a serialized" << ::std::endl + << "representation of the following C++ struct \033[1mbindist_result\033[0m:" << ::std::endl + << ::std::endl + << "struct os_release" << ::std::endl + << "{" << ::std::endl + << " string name_id; // ID" << ::std::endl + << " vector<string> like_ids; // ID_LIKE" << ::std::endl + << " optional<string> version_id; // VERSION_ID" << ::std::endl + << " optional<string> variant_id; // VARIANT_ID" << ::std::endl + << ::std::endl + << " optional<string> name; // NAME" << ::std::endl + << " optional<string> version_codename; // VERSION_CODENAME" << ::std::endl + << " optional<string> variant; // VARIANT" << ::std::endl + << "};" << ::std::endl + << ::std::endl + << "struct file" << ::std::endl + << "{" << ::std::endl + << " string type;" << ::std::endl + << " string path;" << ::std::endl + << " optional<string> system_name;" << ::std::endl + << "};" << ::std::endl + << ::std::endl + << "struct package" << ::std::endl + << "{" << ::std::endl + << " string name;" << ::std::endl + << " string version;" << ::std::endl + << " optional<string> system_version;" << ::std::endl + << " vector<file> files;" << ::std::endl + << "};" << ::std::endl + << ::std::endl + << "struct bindist_result" << ::std::endl + << "{" << ::std::endl + << " string distribution; // --distribution or auto-detected" << ::std::endl + << " string architecture; // --architecture or auto-detected" << ::std::endl + << " os_release os_release; // --os-release-* or auto-detected" << ::std::endl + << " optional<string> recursive; // --recursive" << ::std::endl + << " bool private; // --private" << ::std::endl + << " bool dependent_config; // See --allow-dependent-config" << ::std::endl + << ::std::endl + << " package package;" << ::std::endl + << " vector<package> dependencies; // Only in --recursive=separate" << ::std::endl + << "};" << ::std::endl + << ::std::endl + << "For example:" << ::std::endl + << ::std::endl + << "{" << ::std::endl + << " \"distribution\": \"debian\"," << ::std::endl + << " \"architecture\": \"amd64\"," << ::std::endl + << " \"os_release\": {" << ::std::endl + << " \"name_id\": \"debian\"," << ::std::endl + << " \"version_id\": \"11\"," << ::std::endl + << " \"name\": \"Debian GNU/Linux\"" << ::std::endl + << " }," << ::std::endl + << " \"package\": {" << ::std::endl + << " \"name\": \"libfoo\"," << ::std::endl + << " \"version\": \"2.5.0-b.23\"," << ::std::endl + << " \"system_version\": \"2.5.0~b.23-0~debian11\"," << ::std::endl + << " \"files\": [" << ::std::endl + << " {" << ::std::endl + << " \"type\": \"main.deb\"," << ::std::endl + << " \"path\": \"/tmp/libfoo_2.5.0~b.23-0~debian11_amd64.deb\"," << ::std::endl + << " \"system_name\": \"libfoo\"" << ::std::endl + << " }," << ::std::endl + << " {" << ::std::endl + << " \"type\": \"dev.deb\"," << ::std::endl + << " \"path\": \"/tmp/libfoo-dev_2.5.0~b.23-0~debian11_amd64.deb\"," << ::std::endl + << " \"system_name\": \"libfoo-dev\"" << ::std::endl + << " }," << ::std::endl + << " ..." << ::std::endl + << " ]" << ::std::endl + << " }" << ::std::endl + << "}" << ::std::endl + << ::std::endl + << "See the JSON OUTPUT section in \033[1mbpkg-common-options(1)\033[0m for details on the" << ::std::endl + << "overall properties of this format and the semantics of the \033[1mstruct\033[0m" << ::std::endl + << "serialization." << ::std::endl + << ::std::endl + << "The \033[1mfile::type\033[0m member is a distribution-specific value that classifies the" << ::std::endl + << "file. For the \033[1mdebian\033[0m distribution the possible values are \033[1mmain.deb\033[0m, \033[1mdev.deb\033[0m," << ::std::endl + << "\033[1mdoc.deb\033[0m, \033[1mcommon.deb\033[0m, \033[1mdbgsym.deb\033[0m, \033[1mchanges\033[0m (\033[1m.changes\033[0m file), and \033[1mbuildid\033[0m" << ::std::endl + << "(\033[1m.buildid\033[0m file); see Debian Package Mapping for Production" << ::std::endl + << "(bpkg#bindist-mapping-debian-produce) for background. For the \033[1mfedora\033[0m" << ::std::endl + << "distribution the possible values are \033[1mmain.rpm\033[0m, \033[1mdevel.rpm\033[0m, \033[1mstatic.rpm\033[0m, \033[1mdoc.rpm\033[0m," << ::std::endl + << "\033[1mcommon.rpm\033[0m, and \033[1mdebuginfo.rpm\033[0m; see Fedora Package Mapping for Production" << ::std::endl + << "(bpkg#bindist-mapping-fedora-produce) for background. For the \033[1marchive\033[0m" << ::std::endl + << "distribution this is the archive type (\033[1m--archive-type\033[0m), for example, \033[1mtar.xz\033[0m or" << ::std::endl + << "\033[1mzip\033[0m, potentially prefixed with \033[4mkey\033[0m if the \033[1m--archive-split\033[0m functionality is" << ::std::endl + << "used, for example, \033[1mdev.tar.xz\033[0m." << ::std::endl + << ::std::endl + << "The \033[1mpackage::system_version\033[0m and/or \033[1mfile::system_name\033[0m members are absent if not" << ::std::endl + << "applicable to the distribution. The \033[1mfile::system_name\033[0m member is also absent if" << ::std::endl + << "the file is not a binary package (for example, \033[1m.changes\033[0m and \033[1m.buildid\033[0m files in" << ::std::endl + << "the \033[1mdebian\033[0m distribution)." << ::std::endl; + + p = ::bpkg::pkg_bindist_options::print_usage (os, ::bpkg::cli::usage_para::text); + + if (p != ::bpkg::cli::usage_para::none) + os << ::std::endl; + + os << "\033[1mDEFAULT OPTIONS FILES\033[0m" << ::std::endl + << ::std::endl + << "See \033[1mbpkg-default-options-files(1)\033[0m for an overview of the default options files." << ::std::endl + << "For the \033[1mpkg-bindist\033[0m command the search start directory is the configuration" << ::std::endl + << "directory. The following options files are searched for in each directory and," << ::std::endl + << "if found, loaded in the order listed:" << ::std::endl + << ::std::endl + << "bpkg.options" << ::std::endl + << "bpkg-pkg-bindist.options" << ::std::endl + << ::std::endl + << "The following \033[1mpkg-bindist\033[0m command options cannot be specified in the default" << ::std::endl + << "options files:" << ::std::endl + << ::std::endl + << "--directory|-d" << ::std::endl; + + p = ::bpkg::cli::usage_para::text; + + return p; + } +} + +// Begin epilogue. +// +// +// End epilogue. + |