diff options
-rw-r--r-- | bbot/worker/worker.cxx | 2527 | ||||
-rw-r--r-- | doc/manual.cli | 133 | ||||
-rw-r--r-- | tests/integration/testscript | 14 |
3 files changed, 1580 insertions, 1094 deletions
diff --git a/bbot/worker/worker.cxx b/bbot/worker/worker.cxx index 6c96b5b..f1e5e8c 100644 --- a/bbot/worker/worker.cxx +++ b/bbot/worker/worker.cxx @@ -151,6 +151,9 @@ catch (const system_error& e) // Step IDs. // +// NOTE: keep ids ordered according to the sequence of steps and remember to +// update unreachable breakpoint checks if changing anything here. +// enum class step_id { // Common fallbacks for bpkg_*_create/b_test_installed_create and @@ -302,6 +305,12 @@ static const strings step_id_str { "end"}; +static inline const string& +to_string (step_id s) +{ + return step_id_str[static_cast<size_t> (s)]; +} + using std::regex; namespace regex_constants = std::regex_constants; using regexes = vector<regex>; @@ -390,7 +399,7 @@ run_cmd (step_id step, auto prompt_step = [step, &t, &log, &bkp_step, &prompt] () { - const string& sid (step_id_str[static_cast<size_t> (step)]); + const string& sid (to_string (step)); // Prompt the user if the breakpoint is reached. // @@ -789,7 +798,7 @@ upload_manifest (tracer& trace, } } -static const string worker_checksum ("4"); // Logic version. +static const string worker_checksum ("5"); // Logic version. static int bbot:: build (size_t argc, const char* argv[]) @@ -915,53 +924,105 @@ build (size_t argc, const char* argv[]) } // Split the argument into prefix (empty if not present) and unquoted - // value. Return nullopt if the prefix is invalid. + // value (absent if not present) and determine the step status. If the + // prefix is present and is prepended with the '+'/'-' character, then the + // respective step needs to be enabled/disabled. Return nullopt if the + // prefix is invalid. // - auto parse_arg = [] (const string& a) -> optional<pair<string, string>> + // Note that arguments with absent values are normally used to + // enable/disable steps and are omitted from the command lines. + // + struct argument + { + string prefix; + + // Absent if the argument value is an empty unquoted string. + // + optional<string> value; + + // True - enable, false - disable, nullopt - neutral. + // + optional<bool> step_status; + }; + + auto parse_arg = [] (const string& a) -> optional<argument> { size_t p (a.find_first_of (":=\"'")); + auto value = [] (const string& v) + { + return !v.empty () ? unquote (v) : optional<string> (); + }; + if (p == string::npos || a[p] != ':') // No prefix. - return make_pair (string (), unquote (a)); + return argument {string (), value (a), nullopt}; + + string prefix (a, 0, p); + + optional<bool> enable; + if (prefix[0] == '+' || prefix[0] == '-') + { + enable = (prefix[0] == '+'); + + prefix.erase (0, 1); + + if (prefix != "bpkg.update" && + prefix != "bpkg.test" && + prefix != "bpkg.test-separate.update" && + prefix != "bpkg.test-separate.test" && + prefix != "bpkg.install" && + prefix != "b.test-installed.test" && + prefix != "bpkg.test-separate-installed.update" && + prefix != "bpkg.test-separate-installed.test") + { + return nullopt; // Prefix is invalid. + } + } for (const string& id: step_id_str) { - if (a.compare (0, p, id, 0, p) == 0 && - (id.size () == p || (id.size () > p && id[p] == '.'))) - return make_pair (a.substr (0, p), unquote (a.substr (p + 1))); + size_t n (prefix.size ()); + if (id.compare (0, n, prefix) == 0 && + (id.size () == n || (id.size () > n && id[n] == '.'))) + return argument {move (prefix), value (a.substr (p + 1)), enable}; } return nullopt; // Prefix is invalid. }; - // Parse configuration arguments. Report failures to the bbot controller. + // Keep track of explicitly enabled/disabled steps. // - std::multimap<string, string> tgt_args; + std::map<string, bool> step_statuses; - for (const string& c: tm.target_config) + // Return true if the step is explicitly enabled via a +<prefix>:[<value>] + // environment/configuration argument. + // + // @@ TMP Use it for bpkg.bindist step. + // +#if 0 + auto step_enabled = [&step_statuses] (step_id step) -> bool { - optional<pair<string, string>> v (parse_arg (c)); - - if (!v) - { - rm.status |= result_status::abort; - l3 ([&]{trace << "invalid configuration argument prefix in " - << "'" << c << "'";}); - break; - } - - if (v->second[0] != '-' && v->second.find ('=') == string::npos) - { - rm.status |= result_status::abort; - l3 ([&]{trace << "invalid configuration argument '" << c << "'";}); - break; - } + auto i (step_statuses.find (to_string (step))); + return i != step_statuses.end () && i->second; + }; +#endif - tgt_args.emplace (move (*v)); - } + // Return true if the step is explicitly disabled via a -<prefix>:[<value>] + // environment/configuration argument. + // + auto step_disabled = [&step_statuses] (step_id step) -> bool + { + auto i (step_statuses.find (to_string (step))); + return i != step_statuses.end () && !i->second; + }; - if (!rm.status) - break; + // Parse the environment, target configuration, and build package + // configuration arguments. + // + // NOTE: keep this parsing order intact so that, for example, a build + // package configuration argument can override step status specified + // by a target configuration argument. + // // Parse environment arguments. // @@ -971,147 +1032,73 @@ build (size_t argc, const char* argv[]) for (size_t i (1); i != argc; ++i) { const char* a (argv[i]); - optional<pair<string, string>> v (parse_arg (a)); + optional<argument> v (parse_arg (a)); if (!v) fail << "invalid environment argument prefix in '" << a << "'"; - bool mod (v->second[0] != '-' && v->second.find ('=') == string::npos); - - if (mod && !v->first.empty () && - v->first != "b.create" && - v->first != "bpkg.create" && - v->first != "bpkg.target.create" && - v->first != "bpkg.host.create" && - v->first != "bpkg.module.create" && - v->first != "b.test-installed.create" && - v->first != "bpkg.test-separate-installed.create" && - v->first != "bpkg.test-separate-installed.create_for_target" && - v->first != "bpkg.test-separate-installed.create_for_host" && - v->first != "bpkg.test-separate-installed.create_for_module") + bool mod (v->value && + (*v->value)[0] != '-' && + v->value->find ('=') == string::npos); + + if (mod && + !v->prefix.empty () && + v->prefix != "b.create" && + v->prefix != "bpkg.create" && + v->prefix != "bpkg.target.create" && + v->prefix != "bpkg.host.create" && + v->prefix != "bpkg.module.create" && + v->prefix != "b.test-installed.create" && + v->prefix != "bpkg.test-separate-installed.create" && + v->prefix != "bpkg.test-separate-installed.create_for_target" && + v->prefix != "bpkg.test-separate-installed.create_for_host" && + v->prefix != "bpkg.test-separate-installed.create_for_module") fail << "invalid module prefix in '" << a << "'"; - (mod ? modules : env_args).emplace (move (*v)); + if (v->step_status) + step_statuses[v->prefix] = *v->step_status; + + if (v->value) + (mod ? modules : env_args).emplace (make_pair (move (v->prefix), + move (*v->value))); } - // Return command arguments for the specified step id, complementing - // *.create[_for_*] steps with un-prefixed arguments. If no arguments are - // specified for the step then use the specified fallbacks, potentially - // both. Arguments with more specific prefixes come last. + // Parse target configuration arguments. Report failures to the bbot + // controller. // - auto step_args = [] (const std::multimap<string, string>& args, - step_id step, - optional<step_id> fallback1 = nullopt, - optional<step_id> fallback2 = nullopt) -> cstrings - { - cstrings r; - - // Add arguments for a specified, potentially empty, prefix. - // - auto add_args = [&args, &r] (const string& prefix) - { - auto range (args.equal_range (prefix)); + std::multimap<string, string> tgt_args; - for (auto i (range.first); i != range.second; ++i) - r.emplace_back (i->second.c_str ()); - }; + for (const string& c: tm.target_config) + { + optional<argument> v (parse_arg (c)); - // Add un-prefixed arguments if this is one of the *.create[_for_*] - // steps. - // - switch (step) + if (!v) { - case step_id::b_create: - case step_id::bpkg_create: - case step_id::bpkg_target_create: - case step_id::bpkg_host_create: - case step_id::bpkg_module_create: - case step_id::b_test_installed_create: - case step_id::bpkg_test_separate_installed_create: - case step_id::bpkg_test_separate_installed_create_for_target: - case step_id::bpkg_test_separate_installed_create_for_host: - case step_id::bpkg_test_separate_installed_create_for_module: - { - add_args (""); - break; - } - default: break; + rm.status |= result_status::abort; + l3 ([&]{trace << "invalid target configuration argument prefix in " + << "'" << c << "'";}); + break; } - auto add_step_args = [&add_args] (step_id step) - { - const string& s (step_id_str[static_cast<size_t> (step)]); - - for (size_t n (0);; ++n) - { - n = s.find ('.', n); - - add_args (n == string::npos ? s : string (s, 0, n)); - - if (n == string::npos) - break; - } - }; - - // If no arguments found for the step id, then use the fallback step - // ids, if specified. - // - if (args.find (step_id_str[static_cast<size_t> (step)]) != args.end ()) - { - add_step_args (step); - } - else + if (v->value && + (*v->value)[0] != '-' && + v->value->find ('=') == string::npos) { - // Note that if we ever need to specify fallback pairs with common - // ancestors, we may want to suppress duplicate ancestor step ids. - // - if (fallback1) - add_step_args (*fallback1); - - if (fallback2) - add_step_args (*fallback2); + rm.status |= result_status::abort; + l3 ([&]{trace << "invalid target configuration argument '" << c + << "'";}); + break; } - return r; - }; + if (v->step_status) + step_statuses[v->prefix] = *v->step_status; - // bpkg-rep-fetch trust options. - // - cstrings trust_ops; - { - const char* t ("--trust-no"); - - for (const string& fp: tm.trust) - { - if (fp == "yes") - t = "--trust-yes"; - else - { - trust_ops.push_back ("--trust"); - trust_ops.push_back (fp.c_str ()); - } - } - - trust_ops.push_back (t); + if (v->value) + tgt_args.emplace (make_pair (move (v->prefix), move (*v->value))); } - const string& pkg (tm.name.string ()); - const version& ver (tm.version); - const string repo (tm.repository.string ()); - const dir_path pkg_dir (pkg + '-' + ver.string ()); - const string pkg_var (tm.name.variable ()); - - // Specify the revision explicitly for the bpkg-build command not to end - // up with a race condition building the latest revision rather than the - // zero revision. - // - const string pkg_rev (pkg + - '/' + - version (ver.epoch, - ver.upstream, - ver.release, - ver.effective_revision (), - ver.iteration).string ()); + if (!rm.status) + break; // Parse the build package configuration represented as a whitespace // separated list of the following potentially quoted bpkg-pkg-build @@ -1120,12 +1107,21 @@ build (size_t argc, const char* argv[]) // <option>... <config-var>... ({ <config-var>... }+ (?[sys:]|sys:)<pkg-name>[<version-spec>])... // // If the package configuration is specified, then parse it into the - // options list, the main package-specific configuration variables list, - // and the dependency packages list, potentially with their own - // configuration variables (but not options). + // prefixed global options and configuration variables map, unprefixed + // global options list, the main package-specific configuration variables + // list, and the dependency packages list, potentially with their own + // configuration variables (but not options). The prefixed arguments are + // added to the command lines at the corresponding steps after potential + // environment and target configuration arguments. Unprefixed arguments + // are added to the bpkg-pkg-build command line at the + // bpkg.configure.build step. Specifically, the unprefixed global options + // are specified after all the prefixed global options and the unprefixed + // variables are specified for the main package only, wherever it is + // configured. // - strings pkg_config_opts; - strings pkg_config_vars; + std::multimap<string, string> pkg_args; + strings pkg_config_opts; + strings pkg_config_vars; vector<pair<string, strings>> pkg_config_deps; if (!tm.package_config.empty ()) @@ -1148,13 +1144,47 @@ build (size_t argc, const char* argv[]) try { strings argsv (string_parser::parse_quoted (tm.package_config, - true /* unquote */)); + false /* unquote */)); cli::vector_scanner scanv (argsv); cli::group_scanner args (scanv); while (args.more ()) { + string a (args.next ()); + + // Unless the argument is an unquoted dependency (starts with `?` or + // `sys:`), first try to interpret it as a prefixed option/variable + // and/or step id status (enabled/disabled). + // + if (!(a[0] == '?' || a.compare (0, 4, "sys:") == 0)) + { + optional<argument> v (parse_arg (a)); + + if (v && !v->prefix.empty ()) + { + if (v->value && + (*v->value)[0] != '-' && + v->value->find ('=') == string::npos) + fail ("invalid prefixed argument '" + a + '\''); + + if (args.group ().more ()) + fail ("unexpected options group for prefixed argument '" + a + + '\''); + + if (v->step_status) + step_statuses[v->prefix] = *v->step_status; + + if (v->value) + pkg_args.emplace (make_pair (move (v->prefix), + move (*v->value))); + + continue; + } + } + + a = unquote (a); + // Return true if the argument is an option. // // Note that options with values can only be specified using @@ -1180,7 +1210,6 @@ build (size_t argc, const char* argv[]) a.find ('=') != string::npos; }; - string a (args.next ()); bool o (opt (a)); bool v (var (a)); @@ -1214,7 +1243,7 @@ build (size_t argc, const char* argv[]) strings vars; while (ag.more ()) { - string da (ag.next ()); + string da (unquote (ag.next ())); if (!var (da)) fail ("argument is not a configuration variable for " "dependency " + a + ": '" + da + '\''); @@ -1241,6 +1270,125 @@ build (size_t argc, const char* argv[]) } } + // Return command arguments for the specified step id, complementing + // *.create[_for_*] steps with un-prefixed arguments. If no arguments are + // specified for the step then use the specified fallbacks, potentially + // both. Arguments with more specific prefixes come last. + // + auto step_args = [] (const std::multimap<string, string>& args, + step_id step, + optional<step_id> fallback1 = nullopt, + optional<step_id> fallback2 = nullopt) -> cstrings + { + cstrings r; + + // Add arguments for a specified, potentially empty, prefix. + // + auto add_args = [&args, &r] (const string& prefix) + { + auto range (args.equal_range (prefix)); + + for (auto i (range.first); i != range.second; ++i) + r.emplace_back (i->second.c_str ()); + }; + + // Add un-prefixed arguments if this is one of the *.create[_for_*] + // steps. + // + switch (step) + { + case step_id::b_create: + case step_id::bpkg_create: + case step_id::bpkg_target_create: + case step_id::bpkg_host_create: + case step_id::bpkg_module_create: + case step_id::b_test_installed_create: + case step_id::bpkg_test_separate_installed_create: + case step_id::bpkg_test_separate_installed_create_for_target: + case step_id::bpkg_test_separate_installed_create_for_host: + case step_id::bpkg_test_separate_installed_create_for_module: + { + add_args (""); + break; + } + default: break; + } + + auto add_step_args = [&add_args] (step_id step) + { + const string& s (to_string (step)); + + for (size_t n (0);; ++n) + { + n = s.find ('.', n); + + add_args (n == string::npos ? s : string (s, 0, n)); + + if (n == string::npos) + break; + } + }; + + // If no arguments found for the step id, then use the fallback step + // ids, if specified. + // + if (args.find (to_string (step)) != args.end ()) + { + add_step_args (step); + } + else + { + // Note that if we ever need to specify fallback pairs with common + // ancestors, we may want to suppress duplicate ancestor step ids. + // + if (fallback1) + add_step_args (*fallback1); + + if (fallback2) + add_step_args (*fallback2); + } + + return r; + }; + + // bpkg-rep-fetch trust options. + // + cstrings trust_ops; + { + const char* t ("--trust-no"); + + for (const string& fp: tm.trust) + { + if (fp == "yes") + t = "--trust-yes"; + else + { + trust_ops.push_back ("--trust"); + trust_ops.push_back (fp.c_str ()); + } + } + + trust_ops.push_back (t); + } + + const string& pkg (tm.name.string ()); + const version& ver (tm.version); + const string repo (tm.repository.string ()); + const dir_path pkg_dir (pkg + '-' + ver.string ()); + const string pkg_var (tm.name.variable ()); + + // Specify the revision explicitly for the bpkg-build command not to end + // up with a race condition building the latest revision rather than the + // zero revision. + // + const string pkg_rev (pkg + + '/' + + version (ver.epoch, + ver.upstream, + ver.release, + ver.effective_revision (), + ver.iteration).string ()); + // Query the project's build system information with `b info`. // auto prj_info = [&trace] (const dir_path& d, @@ -1588,7 +1736,9 @@ build (size_t argc, const char* argv[]) // // Create the target configuration. // - // bpkg create <env-modules> <env-config-args> <tgt-config-args> + // bpkg create <env-modules> <env-config-args> + // <tgt-config-args> + // <pkg-config-args> // if (create_target) { @@ -1607,7 +1757,8 @@ build (size_t argc, const char* argv[]) !target_pkg ? cstrings ({"--uuid", target_uuid}) : cstrings (), step_args (modules, s, f1, f2), step_args (env_args, s, f1, f2), - step_args (tgt_args, s, f1, f2)); + step_args (tgt_args, s, f1, f2), + step_args (pkg_args, s, f1, f2)); if (!r.status) break; @@ -1628,7 +1779,9 @@ build (size_t argc, const char* argv[]) step_id f1 (step_id::b_create); step_id f2 (step_id::bpkg_create); - // bpkg create --type host <env-modules> <env-config-args> <tgt-config-args> + // bpkg create --type host <env-modules> <env-config-args> + // <tgt-config-args> + // <pkg-config-args> // r.status |= run_bpkg ( b, @@ -1641,7 +1794,8 @@ build (size_t argc, const char* argv[]) "--uuid", host_uuid, step_args (modules, s, f1, f2), step_args (env_args, s, f1, f2), - step_args (tgt_args, s, f1, f2)); + step_args (tgt_args, s, f1, f2), + step_args (pkg_args, s, f1, f2)); if (!r.status) break; @@ -1649,7 +1803,9 @@ build (size_t argc, const char* argv[]) // Create the install configuration. // - // bpkg create <env-modules> <env-config-args> <tgt-config-args> + // bpkg create <env-modules> <env-config-args> + // <tgt-config-args> + // <pkg-config-args> // if (create_install) { @@ -1667,7 +1823,8 @@ build (size_t argc, const char* argv[]) "--uuid", install_uuid, step_args (modules, s, f1, f2), step_args (env_args, s, f1, f2), - step_args (tgt_args, s, f1, f2)); + step_args (tgt_args, s, f1, f2), + step_args (pkg_args, s, f1, f2)); if (!r.status) break; @@ -1718,7 +1875,9 @@ build (size_t argc, const char* argv[]) // Create the module configuration. // { - // b create(<dir>) config.config.load=~build2 [<env-config-args> <tgt-config-args>] + // b create(<dir>) config.config.load=~build2 [<env-config-args> + // <tgt-config-args> + // <pkg-config-args>] // // Note also that we suppress warnings about unused config.* values. // @@ -1731,6 +1890,7 @@ build (size_t argc, const char* argv[]) string mods; cstrings eas; cstrings cas; + cstrings pas; if (module_pkg && selfhost) { @@ -1746,6 +1906,7 @@ build (size_t argc, const char* argv[]) eas = step_args (env_args, s); cas = step_args (tgt_args, s); + pas = step_args (pkg_args, s); } else mods = "cc"; @@ -1759,7 +1920,8 @@ build (size_t argc, const char* argv[]) "config.config.load=~build2", "config.config.persist+='config.*'@unused=drop", eas, - cas); + cas, + pas); if (!r.status) break; @@ -1796,7 +1958,9 @@ build (size_t argc, const char* argv[]) mods += m; } - // b create(<dir>) config.config.load=~build2 [<env-config-args> <tgt-config-args>] + // b create(<dir>) config.config.load=~build2 [<env-config-args> + // <tgt-config-args> + // <pkg-config-args>] // r.status |= run_b ( b, @@ -1807,7 +1971,8 @@ build (size_t argc, const char* argv[]) "config.config.load=~build2", "config.config.persist+='config.*'@unused=drop", step_args (env_args, s), - step_args (tgt_args, s)); + step_args (tgt_args, s), + step_args (pkg_args, s)); if (!r.status) break; @@ -1926,7 +2091,8 @@ build (size_t argc, const char* argv[]) // configuration for external build-time tests, if any, and the install // configuration, if present. // - // bpkg add <env-config-args> <tgt-config-args> <repository-url> + // bpkg add <env-config-args> <tgt-config-args> <pkg-config-args> + // <repository-url> // { step_id b (step_id::bpkg_configure_add); @@ -1941,13 +2107,15 @@ build (size_t argc, const char* argv[]) "-d", main_pkg_conf, step_args (env_args, s), step_args (tgt_args, s), + step_args (pkg_args, s), repo); if (!r.status) break; } - // bpkg fetch <env-config-args> <tgt-config-args> <trust-options> + // bpkg fetch <env-config-args> <tgt-config-args> <pkg-config-args> + // <trust-options> // { step_id b (step_id::bpkg_configure_fetch); @@ -1962,6 +2130,7 @@ build (size_t argc, const char* argv[]) "-d", main_pkg_conf, step_args (env_args, s), step_args (tgt_args, s), + step_args (pkg_args, s), trust_ops); if (!r.status) @@ -1970,7 +2139,8 @@ build (size_t argc, const char* argv[]) if (create_install) { - // bpkg add <env-config-args> <tgt-config-args> <repository-url> + // bpkg add <env-config-args> <tgt-config-args> <pkg-config-args> + // <repository-url> // { step_id b (step_id::bpkg_configure_add); @@ -1985,13 +2155,15 @@ build (size_t argc, const char* argv[]) "-d", install_conf, step_args (env_args, s), step_args (tgt_args, s), + step_args (pkg_args, s), repo); if (!r.status) break; } - // bpkg fetch <env-config-args> <tgt-config-args> <trust-options> + // bpkg fetch <env-config-args> <tgt-config-args> <pkg-config-args> + // <trust-options> // { step_id b (step_id::bpkg_configure_fetch); @@ -2006,6 +2178,7 @@ build (size_t argc, const char* argv[]) "-d", install_conf, step_args (env_args, s), step_args (tgt_args, s), + step_args (pkg_args, s), trust_ops); if (!r.status) @@ -2015,7 +2188,8 @@ build (size_t argc, const char* argv[]) if (has_buildtime_tests) { - // bpkg add <env-config-args> <tgt-config-args> <repository-url> + // bpkg add <env-config-args> <tgt-config-args> <pkg-config-args> + // <repository-url> // { step_id b (step_id::bpkg_configure_add); @@ -2030,13 +2204,15 @@ build (size_t argc, const char* argv[]) "-d", target_conf, step_args (env_args, s), step_args (tgt_args, s), + step_args (pkg_args, s), repo); if (!r.status) break; } - // bpkg fetch <env-config-args> <tgt-config-args> <trust-options> + // bpkg fetch <env-config-args> <tgt-config-args> <pkg-config-args> + // <trust-options> // { step_id b (step_id::bpkg_configure_fetch); @@ -2051,6 +2227,7 @@ build (size_t argc, const char* argv[]) "-d", target_conf, step_args (env_args, s), step_args (tgt_args, s), + step_args (pkg_args, s), trust_ops); if (!r.status) @@ -2086,13 +2263,17 @@ build (size_t argc, const char* argv[]) // it simple for now. // strings common_args; - strings pkg_args; + strings pkgs; if (target_pkg) // The simple common case (see above)? { // The overall command looks like this (but some parts may be omitted): // - // bpkg build --configure-only <pkg-config-opts> <env-config-args> <tgt-config-args> -- + // bpkg build --configure-only <env-config-args> + // <tgt-config-args> + // <pkg-config-args> + // <pkg-config-opts> + // -- // { <pkg-config-vars>|config.<pkg-name>.develop=false }+ <pkg> // { config.<runtime-test-name>.develop=false }+ <runtime-test>... // { <dep-config-vars> }+ <dep>... @@ -2104,16 +2285,18 @@ build (size_t argc, const char* argv[]) cstrings eas (step_args (env_args, s, f1, f2)); cstrings cas (step_args (tgt_args, s, f1, f2)); + cstrings pas (step_args (pkg_args, s, f1, f2)); common_args.push_back ("--checkout-root"); common_args.push_back (dist_root.string ()); common_args.insert (common_args.end (), eas.begin (), eas.end ()); common_args.insert (common_args.end (), cas.begin (), cas.end ()); + common_args.insert (common_args.end (), pas.begin (), pas.end ()); // Add the main package. // - pkg_args.push_back ("{"); + pkgs.push_back ("{"); // @@ config.<pkg>.develop=false // @@ -2121,16 +2304,16 @@ build (size_t argc, const char* argv[]) // configuration variables specified. // if (!pkg_config_vars.empty ()) - pkg_args.insert (pkg_args.end (), - pkg_config_vars.begin (), pkg_config_vars.end ()); + pkgs.insert (pkgs.end (), + pkg_config_vars.begin (), pkg_config_vars.end ()); #if 1 else - pkg_args.push_back ("config." + pkg_var + ".develop=false"); + pkgs.push_back ("config." + pkg_var + ".develop=false"); #endif - pkg_args.push_back ("}+"); + pkgs.push_back ("}+"); - pkg_args.push_back (pkg_rev); + pkgs.push_back (pkg_rev); // Add the runtime test packages. // @@ -2139,17 +2322,15 @@ build (size_t argc, const char* argv[]) // @@ config.<pkg>.develop=false // #if 1 - pkg_args.push_back ("{"); - pkg_args.push_back ("config." + - t.name.variable () + - ".develop=false"); - pkg_args.push_back ("}+"); + pkgs.push_back ("{"); + pkgs.push_back ("config." + t.name.variable () + ".develop=false"); + pkgs.push_back ("}+"); #endif // Add test dependency package constraints (for example // 'bar > 1.0.0'). // - pkg_args.push_back (t.string ()); + pkgs.push_back (t.string ()); } // Add the main package dependencies. @@ -2158,25 +2339,45 @@ build (size_t argc, const char* argv[]) { if (!d.second.empty ()) { - pkg_args.push_back ("{"); - pkg_args.insert (pkg_args.end (), d.second.begin (), d.second.end ()); - pkg_args.push_back ("}+"); + pkgs.push_back ("{"); + pkgs.insert (pkgs.end (), d.second.begin (), d.second.end ()); + pkgs.push_back ("}+"); } - pkg_args.push_back (d.first); + pkgs.push_back (d.first); } } else { // The overall command looks like this (but some parts may be omitted): // - // bpkg build --configure-only <pkg-config-opts> <env-config-args> <tgt-config-args> -- - // { <build-config> <env-config-args> <tgt-config-args> <pkg-config-vars>|config.<pkg-name>.develop=false }+ <pkg> - // { <build-config> <env-config-args> <tgt-config-args> config.<runtime-test-name>.develop=false }+ <runtime-test>... - // { <install-config> <env-config-args> <tgt-config-args> <pkg-config-vars> }+ <pkg> - // { <target-config> <env-config-args> <tgt-config-args> config.<buildtime-test-name>.develop=false }+ <buildtime-test>... - // { <build-config> <install-config> <dep-config-vars> }+ <dep>... - // { <build-config> <install-config> }+ { <dep>... } + // bpkg build --configure-only <env-config-args> + // <tgt-config-args> + // <pkg-config-args> + // <pkg-config-opts> + // -- + // { <build-config> <env-config-args> + // <tgt-config-args> + // <pkg-config-args> + // <pkg-config-vars>|config.<pkg-name>.develop=false }+ <pkg> + // + // { <build-config> <env-config-args> + // <tgt-config-args> + // <pkg-config-args> + // config.<runtime-test-name>.develop=false }+ <runtime-test>... + // + // { <install-config> <env-config-args> + // <tgt-config-args> + // <pkg-config-args> + // <pkg-config-vars> }+ <pkg> + // + // { <target-config> <env-config-args> + // <tgt-config-args> + // <pkg-config-args> + // config.<buildtime-test-name>.develop=false }+ <buildtime-test>... + // + // { <build-config> <install-config> <dep-config-vars> }+ <dep>... + // { <build-config> <install-config> }+ { <dep>... } // // Main package configuration name. @@ -2198,20 +2399,22 @@ build (size_t argc, const char* argv[]) cstrings eas (step_args (env_args, s, f1, f2)); cstrings cas (step_args (tgt_args, s, f1, f2)); + cstrings pas (step_args (pkg_args, s, f1, f2)); // Add the main package. // { - pkg_args.push_back ("{"); + pkgs.push_back ("{"); - pkg_args.push_back ("--config-uuid"); - pkg_args.push_back (conf_uuid); + pkgs.push_back ("--config-uuid"); + pkgs.push_back (conf_uuid); - pkg_args.push_back ("--checkout-root"); - pkg_args.push_back (dist_root.string ()); + pkgs.push_back ("--checkout-root"); + pkgs.push_back (dist_root.string ()); - pkg_args.insert (pkg_args.end (), eas.begin (), eas.end ()); - pkg_args.insert (pkg_args.end (), cas.begin (), cas.end ()); + pkgs.insert (pkgs.end (), eas.begin (), eas.end ()); + pkgs.insert (pkgs.end (), cas.begin (), cas.end ()); + pkgs.insert (pkgs.end (), pas.begin (), pas.end ()); // @@ config.<pkg>.develop=false // @@ -2219,16 +2422,16 @@ build (size_t argc, const char* argv[]) // package configuration variables specified. // if (!pkg_config_vars.empty ()) - pkg_args.insert (pkg_args.end (), - pkg_config_vars.begin (), pkg_config_vars.end ()); + pkgs.insert (pkgs.end (), + pkg_config_vars.begin (), pkg_config_vars.end ()); #if 1 else - pkg_args.push_back ("config." + pkg_var + ".develop=false"); + pkgs.push_back ("config." + pkg_var + ".develop=false"); #endif - pkg_args.push_back ("}+"); + pkgs.push_back ("}+"); - pkg_args.push_back (pkg_rev); + pkgs.push_back (pkg_rev); } // Add the runtime test packages. @@ -2238,58 +2441,58 @@ build (size_t argc, const char* argv[]) #if 1 for (const auto& t: runtime_tests) { - pkg_args.push_back ("{"); + pkgs.push_back ("{"); - pkg_args.push_back ("--config-uuid"); - pkg_args.push_back (conf_uuid); + pkgs.push_back ("--config-uuid"); + pkgs.push_back (conf_uuid); - pkg_args.push_back ("--checkout-root"); - pkg_args.push_back (dist_root.string ()); + pkgs.push_back ("--checkout-root"); + pkgs.push_back (dist_root.string ()); if (bootstrap_import) - pkg_args.push_back (*bootstrap_import); + pkgs.push_back (*bootstrap_import); - pkg_args.insert (pkg_args.end (), eas.begin (), eas.end ()); - pkg_args.insert (pkg_args.end (), cas.begin (), cas.end ()); + pkgs.insert (pkgs.end (), eas.begin (), eas.end ()); + pkgs.insert (pkgs.end (), cas.begin (), cas.end ()); + pkgs.insert (pkgs.end (), pas.begin (), pas.end ()); - pkg_args.push_back ("config." + - t.name.variable () + - ".develop=false"); + pkgs.push_back ("config." + t.name.variable () + ".develop=false"); - pkg_args.push_back ("}+"); + pkgs.push_back ("}+"); - pkg_args.push_back (t.string ()); + pkgs.push_back (t.string ()); } #else if (has_runtime_tests) { - pkg_args.push_back ("{"); + pkgs.push_back ("{"); - pkg_args.push_back ("--config-uuid"); - pkg_args.push_back (conf_uuid); + pkgs.push_back ("--config-uuid"); + pkgs.push_back (conf_uuid); - pkg_args.push_back ("--checkout-root"); - pkg_args.push_back (dist_root.string ()); + pkgs.push_back ("--checkout-root"); + pkgs.push_back (dist_root.string ()); if (bootstrap_import) - pkg_args.push_back (*bootstrap_import); + pkgs.push_back (*bootstrap_import); - pkg_args.insert (pkg_args.end (), eas.begin (), eas.end ()); - pkg_args.insert (pkg_args.end (), cas.begin (), cas.end ()); + pkgs.insert (pkgs.end (), eas.begin (), eas.end ()); + pkgs.insert (pkgs.end (), cas.begin (), cas.end ()); + pkgs.insert (pkgs.end (), pas.begin (), pas.end ()); - pkg_args.push_back ("}+"); + pkgs.push_back ("}+"); // Add test dependency package constraints and group them if there // are multiple of them. // if (runtime_tests.size () != 1) - pkg_args.push_back ("{"); + pkgs.push_back ("{"); for (const auto& t: runtime_tests) - pkg_args.push_back (t.string ()); + pkgs.push_back (t.string ()); if (runtime_tests.size () != 1) - pkg_args.push_back ("}"); + pkgs.push_back ("}"); } #endif } @@ -2304,6 +2507,7 @@ build (size_t argc, const char* argv[]) cstrings eas (step_args (env_args, s, f1, f2)); cstrings cas (step_args (tgt_args, s, f1, f2)); + cstrings pas (step_args (pkg_args, s, f1, f2)); // Add the main package. // @@ -2312,27 +2516,28 @@ build (size_t argc, const char* argv[]) common_args.push_back ("-d"); common_args.push_back (install_conf.string ()); - pkg_args.push_back ("{"); + pkgs.push_back ("{"); - pkg_args.push_back ("--config-uuid"); - pkg_args.push_back (install_uuid); + pkgs.push_back ("--config-uuid"); + pkgs.push_back (install_uuid); // Note that we do another re-distribution (with a separate // --checkout-root) in case the package is missing file that // are only used during installation. // - pkg_args.push_back ("--checkout-root"); - pkg_args.push_back (dist_install_root.string ()); + pkgs.push_back ("--checkout-root"); + pkgs.push_back (dist_install_root.string ()); - pkg_args.insert (pkg_args.end (), eas.begin (), eas.end ()); - pkg_args.insert (pkg_args.end (), cas.begin (), cas.end ()); + pkgs.insert (pkgs.end (), eas.begin (), eas.end ()); + pkgs.insert (pkgs.end (), cas.begin (), cas.end ()); + pkgs.insert (pkgs.end (), pas.begin (), pas.end ()); - pkg_args.insert (pkg_args.end (), - pkg_config_vars.begin (), pkg_config_vars.end ()); + pkgs.insert (pkgs.end (), + pkg_config_vars.begin (), pkg_config_vars.end ()); - pkg_args.push_back ("}+"); + pkgs.push_back ("}+"); - pkg_args.push_back (pkg_rev); + pkgs.push_back (pkg_rev); } // Add the build-time test packages. @@ -2342,62 +2547,62 @@ build (size_t argc, const char* argv[]) #if 1 for (const auto& t: buildtime_tests) { - pkg_args.push_back ("{"); + pkgs.push_back ("{"); - pkg_args.push_back ("--config-uuid"); - pkg_args.push_back (target_uuid); + pkgs.push_back ("--config-uuid"); + pkgs.push_back (target_uuid); - pkg_args.push_back ("--checkout-root"); - pkg_args.push_back (dist_root.string ()); + pkgs.push_back ("--checkout-root"); + pkgs.push_back (dist_root.string ()); if (bootstrap_import) - pkg_args.push_back (*bootstrap_import); + pkgs.push_back (*bootstrap_import); - pkg_args.insert (pkg_args.end (), eas.begin (), eas.end ()); - pkg_args.insert (pkg_args.end (), cas.begin (), cas.end ()); + pkgs.insert (pkgs.end (), eas.begin (), eas.end ()); + pkgs.insert (pkgs.end (), cas.begin (), cas.end ()); + pkgs.insert (pkgs.end (), pas.begin (), pas.end ()); - pkg_args.push_back ("config." + - t.name.variable () + - ".develop=false"); + pkgs.push_back ("config." + t.name.variable () + ".develop=false"); - pkg_args.push_back ("}+"); + pkgs.push_back ("}+"); // Strip the build-time mark. // - pkg_args.push_back (t.dependency::string ()); + pkgs.push_back (t.dependency::string ()); } #else if (has_buildtime_tests) { - pkg_args.push_back ("{"); + pkgs.push_back ("{"); - pkg_args.push_back ("--config-uuid"); - pkg_args.push_back (target_uuid); + pkgs.push_back ("--config-uuid"); + pkgs.push_back (target_uuid); - pkg_args.push_back ("--checkout-root"); - pkg_args.push_back (dist_root.string ()); + pkgs.push_back ("--checkout-root"); + pkgs.push_back (dist_root.string ()); if (bootstrap_import) - pkg_args.push_back (*bootstrap_import); + pkgs.push_back (*bootstrap_import); - pkg_args.insert (pkg_args.end (), eas.begin (), eas.end ()); - pkg_args.insert (pkg_args.end (), cas.begin (), cas.end ()); + pkgs.insert (pkgs.end (), eas.begin (), eas.end ()); + pkgs.insert (pkgs.end (), cas.begin (), cas.end ()); + pkgs.insert (pkgs.end (), pas.begin (), pas.end ()); - pkg_args.push_back ("}+"); + pkgs.push_back ("}+"); // Add test dependency package constraints and group them if there // are multiple of them. // if (buildtime_tests.size () != 1) - pkg_args.push_back ("{"); + pkgs.push_back ("{"); // Strip the build-time mark. // for (const auto& t: buildtime_tests) - pkg_args.push_back (t.dependency::string ()); + pkgs.push_back (t.dependency::string ()); if (buildtime_tests.size () != 1) - pkg_args.push_back ("}"); + pkgs.push_back ("}"); } #endif } @@ -2414,21 +2619,22 @@ build (size_t argc, const char* argv[]) { if (!d.second.empty ()) { - pkg_args.push_back ("{"); + pkgs.push_back ("{"); - pkg_args.push_back ("--config-uuid"); - pkg_args.push_back (conf_uuid); + pkgs.push_back ("--config-uuid"); + pkgs.push_back (conf_uuid); if (create_install) { - pkg_args.push_back ("--config-uuid"); - pkg_args.push_back (install_uuid); + pkgs.push_back ("--config-uuid"); + pkgs.push_back (install_uuid); } - pkg_args.insert (pkg_args.end (), d.second.begin (), d.second.end ()); - pkg_args.push_back ("}+"); + pkgs.insert (pkgs.end (), d.second.begin (), d.second.end ()); + + pkgs.push_back ("}+"); - pkg_args.push_back (d.first); + pkgs.push_back (d.first); } else ++no_vars; @@ -2438,30 +2644,30 @@ build (size_t argc, const char* argv[]) // if (no_vars != 0) { - pkg_args.push_back ("{"); + pkgs.push_back ("{"); - pkg_args.push_back ("--config-uuid"); - pkg_args.push_back (conf_uuid); + pkgs.push_back ("--config-uuid"); + pkgs.push_back (conf_uuid); if (create_install) { - pkg_args.push_back ("--config-uuid"); - pkg_args.push_back (install_uuid); + pkgs.push_back ("--config-uuid"); + pkgs.push_back (install_uuid); } - pkg_args.push_back ("}+"); + pkgs.push_back ("}+"); if (no_vars != 1) - pkg_args.push_back ("{"); + pkgs.push_back ("{"); for (const pair<string, strings>& d: pkg_config_deps) { if (d.second.empty ()) - pkg_args.push_back (d.first); + pkgs.push_back (d.first); } if (no_vars != 1) - pkg_args.push_back ("}"); + pkgs.push_back ("}"); } } } @@ -2481,16 +2687,17 @@ build (size_t argc, const char* argv[]) "-v", "build", "--configure-only", - pkg_config_opts, "--rebuild-checksum", tm.dependency_checksum ? *tm.dependency_checksum : "", "--yes", "-d", root_conf, step_args (env_args, s), step_args (tgt_args, s), + step_args (pkg_args, s), common_args, + pkg_config_opts, "--", - pkg_args); + pkgs); // The dependency checksum is tricky, here are the possibilities: // @@ -2585,952 +2792,1182 @@ build (size_t argc, const char* argv[]) Sleep (5000); #endif - // Update the main package. - // - { - operation_result& r (add_result ("update")); - - change_wd (trace, &r.log, rwd / main_pkg_conf); - - // bpkg update <env-config-args> <tgt-config-args> <package-name> - // - step_id b (step_id::bpkg_update); - step_id s (step_id::bpkg_update); - - r.status |= run_bpkg ( - b, - trace, r.log, wre, - bkp_step, bkp_status, last_cmd, - "-v", - "update", - step_args (env_args, s), - step_args (tgt_args, s), - pkg); - - if (!r.status) - break; - - rm.status |= r.status; - } - - // Re-distribute if comes from a version control-based repository, update, - // and test external test packages in the bpkg configuration in the - // current working directory. Optionally pass the config.import.* variable - // override and/or set the environment variables for the bpkg processes. - // Return true if all operations for all packages succeeded. - // - // Pass true as the installed argument to use the test separate installed - // phase step ids (bpkg.test-separate-installed.*) and the test separate - // phase step ids (bpkg.test-separate.*) otherwise. In both cases fall - // back to the main phase step ids (bpkg.*) when no environment/ - // configuration arguments are specified for them. - // - auto test = [&trace, &wre, - &bkp_step, &bkp_status, &last_cmd, - &step_args, &tgt_args, &env_args, - &bootstrap_import, - &redist] - (operation_result& r, - const small_vector<test_dependency, 1>& tests, - const dir_path& dist_root, - bool installed, - const small_vector<string, 1>& envvars = {}) + auto fail_unreached_breakpoint = [&bkp_step, &fail_operation] + (operation_result& r) { - const optional<string>& import (!installed - ? bootstrap_import - : nullopt); - - for (const test_dependency& td: tests) - { - const string& pkg (td.name.string ()); - - // Re-distribute. - // - if (exists (dist_root)) - { - // Note that re-distributing the test package is a bit tricky since - // we don't know its version and so cannot deduce its source - // directory name easily. We could potentially run the bpkg-status - // command after the package is configured and parse the output to - // obtain the version. Let's, however, keep it simple and find the - // source directory using the package directory name pattern. - // - try - { - dir_path pkg_dir; - - // Note: doesn't follow symlinks. - // - path_search (dir_path (pkg + "-*/"), - [&pkg_dir] (path&& pe, const string&, bool interm) - { - if (!interm) - pkg_dir = path_cast<dir_path> (move (pe)); - - return interm; - }, - dist_root, - path_match_flags::none); - - if (!pkg_dir.empty ()) - { - step_id b ( - installed - ? step_id::bpkg_test_separate_installed_configure_build - : step_id::bpkg_configure_build); - - if (!redist (b, r, dist_root, pkg_dir, import, envvars)) - return false; - } - } - catch (const system_error& e) - { - fail << "unable to scan directory " << dist_root << ": " << e; - } - } + assert (bkp_step); - // Update. - // - // bpkg update <env-config-args> <tgt-config-args> <package-name> - // - { - step_id b (installed - ? step_id::bpkg_test_separate_installed_update - : step_id::bpkg_test_separate_update); - - step_id s (b); - - step_id f (step_id::bpkg_update); - - r.status |= run_bpkg ( - b, - envvars, - trace, r.log, wre, - bkp_step, bkp_status, last_cmd, - "-v", - "update", - step_args (env_args, s, f), - step_args (tgt_args, s, f), - import, - pkg); - - if (!r.status) - return false; - } - - // Test. - // - // Note that we assume that the package supports the test operation - // since this is its main purpose. - // - // bpkg test <env-config-args> <tgt-config-args> <package-name> - // - { - step_id b (installed - ? step_id::bpkg_test_separate_installed_test - : step_id::bpkg_test_separate_test); - - step_id s (b); - - step_id f (step_id::bpkg_test); - - r.status |= run_bpkg ( - b, - envvars, - trace, r.log, wre, - bkp_step, bkp_status, last_cmd, - "-v", - "test", - "--package-cwd", // See above for details. - step_args (env_args, s, f), - step_args (tgt_args, s, f), - import, - pkg); - - if (!r.status) - return false; - } - } - - return true; + fail_operation (r, + "interactive build breakpoint " + + to_string (*bkp_step) + " cannot be reached", + result_status::abort); }; - // Test the main package. - // - b_project_info prj ( - prj_info (pkg_dir, - b_info_flags::ext_mods | b_info_flags::subprojects, - "project")); - - // Run the internal tests if the test operation is supported by the - // project but only for the target package or if the configuration is - // self-hosted. + // Note that if the bpkg.update step is disabled, we also skip all the + // test and install related steps. // - bool has_internal_tests ((target_pkg || selfhost) && - find (prj.operations.begin (), - prj.operations.end (), - "test") != prj.operations.end ()); - - if (has_internal_tests || has_runtime_tests || has_buildtime_tests) + if (!step_disabled (step_id::bpkg_update)) { - operation_result& r (add_result ("test")); - - // Run internal tests. + // Update the main package. // - if (has_internal_tests) { - // Use --package-cwd to help ported to build2 third-party packages a - // bit (see bpkg-pkg-test(1) for details). - // - // Note that internal tests that load the module itself don't make - // much sense, thus we don't pass the config.import.* variable on - // the command line for modules that require bootstrap. - // - // bpkg test <env-config-args> <tgt-config-args> <package-name> + operation_result& r (add_result ("update")); + + change_wd (trace, &r.log, rwd / main_pkg_conf); + + // bpkg update <env-config-args> <tgt-config-args> <pkg-config-args> + // <package-name> // - step_id b (step_id::bpkg_test); - step_id s (step_id::bpkg_test); + step_id b (step_id::bpkg_update); + step_id s (step_id::bpkg_update); r.status |= run_bpkg ( b, trace, r.log, wre, bkp_step, bkp_status, last_cmd, "-v", - "test", - "--package-cwd", + "update", step_args (env_args, s), step_args (tgt_args, s), + step_args (pkg_args, s), pkg); if (!r.status) break; + + rm.status |= r.status; } - // External runtime tests. + // Re-distribute if comes from a version control-based repository, + // update, and test external test packages in the bpkg configuration in + // the current working directory. Optionally pass the config.import.* + // variable override and/or set the environment variables for the bpkg + // processes. Return true if all operations for all packages succeeded. // - // Note that we assume that these packages belong to the dependent - // package's repository or its complement repositories, recursively. - // Thus, we test them in the configuration used to build the dependent - // package. + // Pass true as the installed argument to use the test separate installed + // phase step ids (bpkg.test-separate-installed.*) and the test separate + // phase step ids (bpkg.test-separate.*) otherwise. In both cases fall + // back to the main phase step ids (bpkg.*) when no environment/ + // configuration arguments are specified for them. // - if (has_runtime_tests) - { - if (!test (r, runtime_tests, dist_root, false /* installed */)) - break; - } + auto test = [&trace, &wre, + &bkp_step, &bkp_status, &last_cmd, + &step_args, &env_args, &tgt_args, &pkg_args, + &bootstrap_import, + &redist] + (operation_result& r, + const small_vector<test_dependency, 1>& tests, + const dir_path& dist_root, + bool installed, + bool update_only, + const small_vector<string, 1>& envvars = {}) + { + const optional<string>& import (!installed + ? bootstrap_import + : nullopt); - // External build-time tests. - // - if (has_buildtime_tests) - { - change_wd (trace, &r.log, rwd / target_conf); + for (const test_dependency& td: tests) + { + const string& pkg (td.name.string ()); - if (!test (r, buildtime_tests, dist_root, false /* installed */)) - break; - } + // Re-distribute. + // + if (exists (dist_root)) + { + // Note that re-distributing the test package is a bit tricky + // since we don't know its version and so cannot deduce its + // source directory name easily. We could potentially run the + // bpkg-status command after the package is configured and parse + // the output to obtain the version. Let's, however, keep it + // simple and find the source directory using the package + // directory name pattern. + // + try + { + dir_path pkg_dir; - rm.status |= r.status; - } + // Note: doesn't follow symlinks. + // + path_search (dir_path (pkg + "-*/"), + [&pkg_dir] (path&& pe, const string&, bool interm) + { + if (!interm) + pkg_dir = path_cast<dir_path> (move (pe)); + + return interm; + }, + dist_root, + path_match_flags::none); + + if (!pkg_dir.empty ()) + { + step_id b ( + installed + ? step_id::bpkg_test_separate_installed_configure_build + : step_id::bpkg_configure_build); - // Install the package, optionally test the installation and uninstall - // afterwards. - // - if (!install_root) - break; + if (!redist (b, r, dist_root, pkg_dir, import, envvars)) + return false; + } + } + catch (const system_error& e) + { + fail << "unable to scan directory " << dist_root << ": " << e; + } + } - // Now the overall plan is as follows: - // - // 1. Install the package. - // - // 2. If the package has subprojects that support the test operation, then - // configure, build, and test them out of the source tree against the - // installed package using the build system directly. - // - // 3. If any of the test packages are specified, then configure, build, - // and test them in a separate bpkg configuration(s) against the - // installed package. - // - // 4. Uninstall the package. + // Update. + // + // bpkg update <env-config-args> <tgt-config-args> <pkg-config-args> + // <package-name> + // + { + step_id b (installed + ? step_id::bpkg_test_separate_installed_update + : step_id::bpkg_test_separate_update); - install_conf = rwd / (create_install ? install_conf : main_pkg_conf); + step_id s (b); - // Install. - // - { - operation_result& r (add_result ("install")); + step_id f (step_id::bpkg_update); - change_wd (trace, &r.log, install_conf); + r.status |= run_bpkg ( + b, + envvars, + trace, r.log, wre, + bkp_step, bkp_status, last_cmd, + "-v", + "update", + step_args (env_args, s, f), + step_args (tgt_args, s, f), + step_args (pkg_args, s, f), + import, + pkg); - // Note that for a host or module package we don't need the target - // configuration anymore, if present. So let's free up the space a - // little bit. - // - if (!target_pkg && create_target) - rm_r (trace, &r.log, rwd / target_conf); + if (!r.status) + return false; + } - // bpkg install <env-config-args> <tgt-config-args> <package-name> - // - step_id b (step_id::bpkg_install); - step_id s (step_id::bpkg_install); + // Test. + // + // Note that we assume that the package supports the test operation + // since this is its main purpose. + // + // bpkg test <env-config-args> <tgt-config-args> <pkg-config-args> + // <package-name> + // + if (!update_only) + { + step_id b (installed + ? step_id::bpkg_test_separate_installed_test + : step_id::bpkg_test_separate_test); - r.status |= run_bpkg ( - b, - trace, r.log, wre, - bkp_step, bkp_status, last_cmd, - "-v", - "install", - step_args (env_args, s), - step_args (tgt_args, s), - pkg); + step_id s (b); - if (!r.status) - break; + step_id f (step_id::bpkg_test); - rm.status |= r.status; - } + r.status |= run_bpkg ( + b, + envvars, + trace, r.log, wre, + bkp_step, bkp_status, last_cmd, + "-v", + "test", + "--package-cwd", // See above for details. + step_args (env_args, s, f), + step_args (tgt_args, s, f), + step_args (pkg_args, s, f), + import, + pkg); - // Run the internal tests if the project contains "testable" subprojects, - // but not for a module. - // - has_internal_tests = false; + if (!r.status) + return false; + } + } - dir_paths subprj_dirs; // "Testable" package subprojects. + return true; + }; - if (!module_pkg) - { - // Collect the "testable" subprojects. + // Test the main package. // - for (const b_project_info::subproject& sp: prj.subprojects) - { - // Retrieve the subproject information similar to how we've done it - // for the package. - // - b_project_info si (prj_info (pkg_dir / sp.path, - b_info_flags::ext_mods, - "subproject")); - - const strings& ops (si.operations); - if (find (ops.begin (), ops.end (), "test") != ops.end ()) - subprj_dirs.push_back (sp.path); - } - - has_internal_tests = !subprj_dirs.empty (); - } - - if (has_internal_tests || has_runtime_tests || has_buildtime_tests) - { - operation_result& r (add_result ("test-installed")); - - change_wd (trace, &r.log, rwd); - - // Make sure that the installed package executables are properly - // imported when configuring and running tests, unless we are testing - // the build system module (that supposedly doesn't install any - // executables). + b_project_info prj ( + prj_info (pkg_dir, + b_info_flags::ext_mods | b_info_flags::subprojects, + "project")); + + // Run the internal tests if the test operation is supported by the + // project but only for the target package or if the configuration is + // self-hosted. // - small_vector<string, 1> envvars; + bool has_internal_tests ((target_pkg || selfhost) && + find (prj.operations.begin (), + prj.operations.end (), + "test") != prj.operations.end ()); - if (!module_pkg) + if (has_internal_tests || has_runtime_tests || has_buildtime_tests) { - // Note that we add the $config.install.root/bin directory at the - // beginning of the PATH environment variable value, so the installed - // executables are found first. - // - string paths ("PATH=" + (*install_root / "bin").string ()); + operation_result& r (add_result ("test")); - if (optional<string> s = getenv ("PATH")) - { - paths += path::traits_type::path_separator; - paths += *s; - } - - envvars.push_back (move (paths)); - } - - // Run internal tests. - // - if (has_internal_tests) - { - // Create the configuration. - // - // b create(<dir>, <env-modules>) <env-config-args> <tgt-config-args> + // Run internal tests. // - // Amalgamation directory that will contain configuration subdirectory - // for package tests out of source tree build. - // - dir_path out_dir ("build-installed"); - + if (has_internal_tests && !step_disabled (step_id::bpkg_test)) { - step_id b (step_id::b_test_installed_create); - step_id s (step_id::b_test_installed_create); - step_id f (step_id::b_create); - - string mods; // build2 create meta-operation parameters. - - for (const char* m: step_args (modules, s, f)) - { - mods += mods.empty () ? ", " : " "; - mods += m; - } + // Use --package-cwd to help ported to build2 third-party packages a + // bit (see bpkg-pkg-test(1) for details). + // + // Note that internal tests that load the module itself don't make + // much sense, thus we don't pass the config.import.* variable on + // the command line for modules that require bootstrap. + // + // bpkg test <env-config-args> <tgt-config-args> <pkg-config-args> + // <package-name> + // + step_id b (step_id::bpkg_test); + step_id s (step_id::bpkg_test); - r.status |= run_b ( + r.status |= run_bpkg ( b, trace, r.log, wre, bkp_step, bkp_status, last_cmd, - "-V", - "create('" + out_dir.representation () + '\'' + mods + ')', - step_args (env_args, s, f), - step_args (tgt_args, s, f)); + "-v", + "test", + "--package-cwd", + step_args (env_args, s), + step_args (tgt_args, s), + step_args (pkg_args, s), + pkg); if (!r.status) break; } - - // Configure testable subprojects sequentially and test/build in - // parallel afterwards. // - // It feels right to configure internal tests also passing the main - // package configuration variables, since they may need to align with - // the main package setup (enable some testscripts, etc). + // Fail if the breakpoint refers to the bpkg.test step but the package + // has no internal tests or this step is disabled. // - strings test_specs; - for (const dir_path& d: subprj_dirs) + else if (bkp_step && *bkp_step == step_id::bpkg_test) { - // b configure(<subprj-src-dir>@<subprj-out-dir>) <env-config-args> - // <tgt-config-args> - // <pkg-vars> - // - step_id b (step_id::b_test_installed_configure); - step_id s (step_id::b_test_installed_configure); - step_id f (step_id::b_configure); - - dir_path subprj_src_dir (exists (dist_src) - ? dist_src / d - : main_pkg_conf / pkg_dir / d); - - dir_path subprj_out_dir (out_dir / d); + fail_unreached_breakpoint (r); + break; + } - r.status |= run_b ( - b, - envvars, - trace, r.log, wre, - bkp_step, bkp_status, last_cmd, - "-v", - "configure('" + - subprj_src_dir.representation () + "'@'" + - subprj_out_dir.representation () + "')", - step_args (env_args, s, f), - step_args (tgt_args, s, f), - pkg_config_vars); + // External tests. + // + // Note that if the bpkg.test-separate.update step is disabled, we + // also skip bpkg.test-separate.test. + // + if ((has_runtime_tests || has_buildtime_tests) && + !step_disabled (step_id::bpkg_test_separate_update)) + { + bool update_only (step_disabled (step_id::bpkg_test_separate_test)); - if (!r.status) + // Fail if the breakpoint refers to the bpkg.test-separate.test step + // but this step is disabled. + // + if (update_only && + bkp_step && + *bkp_step == step_id::bpkg_test_separate_test) + { + fail_unreached_breakpoint (r); break; + } - test_specs.push_back ( - "test('" + subprj_out_dir.representation () + "')"); - } + // External runtime tests. + // + // Note that we assume that these packages belong to the dependent + // package's repository or its complement repositories, recursively. + // Thus, we test them in the configuration used to build the + // dependent package. + // + if (has_runtime_tests) + { + if (!test (r, + runtime_tests, + dist_root, + false /* installed */, + update_only)) + break; + } - if (!r.status) - break; + // External build-time tests. + // + if (has_buildtime_tests) + { + change_wd (trace, &r.log, rwd / target_conf); - // Build/test subprojects. + if (!test (r, + buildtime_tests, + dist_root, + false /* installed */, + update_only)) + break; + } + } // - // b test(<subprj-out-dir>)... <env-config-args> <tgt-config-args> + // Fail if the breakpoint refers to some of the bpkg.test-separate.* + // steps but the package either has no external tests or the + // bpkg.test-separate.update step is disabled. // + else if (bkp_step && + *bkp_step >= step_id::bpkg_test_separate_update && + *bkp_step <= step_id::bpkg_test_separate_test) { - step_id b (step_id::b_test_installed_test); - step_id s (step_id::b_test_installed_test); - - r.status |= run_b ( - b, - envvars, - trace, r.log, wre, - bkp_step, bkp_status, last_cmd, - "-v", - test_specs, - step_args (env_args, s), - step_args (tgt_args, s)); - - if (!r.status) - break; + fail_unreached_breakpoint (r); + break; } - } - // Run runtime and build-time tests. + rm.status |= r.status; + } // - // Note that we only build runtime tests for target packages and for - // host packages in self-hosted configurations. + // Fail if the breakpoint refers to some of the test steps but the + // package has no tests. // - if (has_runtime_tests || has_buildtime_tests) + else if (bkp_step && + *bkp_step >= step_id::bpkg_test && + *bkp_step <= step_id::bpkg_test_separate_test) { - // Create the required build configurations. - // - dir_path target_conf ("build-installed-bpkg"); - dir_path host_conf ("build-installed-bpkg-host"); - dir_path module_conf ("build-installed-bpkg-module"); + fail_unreached_breakpoint (add_result ("test")); + break; + } - // Create the target configuration if this is a target package having - // external runtime tests or a host/module package having external - // build-time tests. + // Install the package, optionally test the installation and uninstall + // afterwards. + // + // Note that if the bpkg.install step is disabled, we also skip all the + // test installed related steps up to bpkg.uninstall. + // + if (install_root && !step_disabled (step_id::bpkg_install)) + { + // Now the overall plan is as follows: // - bool create_target (target_pkg || has_buildtime_tests); - - // Note that even if there are no runtime tests for a host/module - // package, we still need to create the host/build2 configuration to - // configure the system package in. + // 1. Install the package. // - bool create_host (host_pkg || module_pkg); - bool create_module (module_pkg || (host_pkg && has_buildtime_tests)); - - // Note: a module package cannot have runtime tests and so the module - // configuration is only created to serve build-time tests. Thus, the - // host or target configuration is always created as well and the - // module configuration is never a root configuration. + // 2. If the package has subprojects that support the test operation, + // then configure, build, and test them out of the source tree + // against the installed package using the build system directly. // - assert (create_target || create_host); - - // Root configuration through which we will be configuring the - // cluster. + // 3. If any of the test packages are specified, then configure, build, + // and test them in a separate bpkg configuration(s) against the + // installed package. // - const dir_path& root_conf (create_target ? target_conf : host_conf); + // 4. Uninstall the package. - // Runtime tests configuration. Should only be used if there are any. - // - const dir_path& runtime_tests_conf (target_pkg - ? target_conf - : host_conf); + install_conf = rwd / (create_install ? install_conf : main_pkg_conf); - // Create the target configuration. - // - // bpkg create <env-modules> <env-config-args> <tgt-config-args> + // Install. // - if (create_target) { - step_id b (step_id::bpkg_test_separate_installed_create); + operation_result& r (add_result ("install")); - // Note that here and below the _for_* step ids are determined by - // the main package type (and, yes, that means we will use the same - // step ids for target and host configuration -- that, however, - // should be ok since host configuration will only be created in - // the self-hosted case). + change_wd (trace, &r.log, install_conf); + + // Note that for a host or module package we don't need the target + // configuration anymore, if present. So let's free up the space a + // little bit. // - step_id s ( - target_pkg - ? step_id::bpkg_test_separate_installed_create_for_target - : host_pkg - ? step_id::bpkg_test_separate_installed_create_for_host - : step_id::bpkg_test_separate_installed_create_for_module); - - // Note: no fallback for modules. + if (!target_pkg && create_target) + rm_r (trace, &r.log, rwd / target_conf); + + // bpkg install <env-config-args> <tgt-config-args> <pkg-config-args> + // <package-name> // - optional<step_id> f (!module_pkg - ? step_id::bpkg_test_separate_installed_create - : optional<step_id> ()); + step_id b (step_id::bpkg_install); + step_id s (step_id::bpkg_install); r.status |= run_bpkg ( b, trace, r.log, wre, bkp_step, bkp_status, last_cmd, - "-V", - "create", - "-d", target_conf, - step_args (modules, s, f), - step_args (env_args, s, f), - step_args (tgt_args, s, f)); + "-v", + "install", + step_args (env_args, s), + step_args (tgt_args, s), + step_args (pkg_args, s), + pkg); if (!r.status) break; + + rm.status |= r.status; } - // Create the host configuration. + // Run the internal tests if the project contains "testable" + // subprojects, but not for a module. // - if (create_host) - { - // bpkg create --type host <env-modules> <env-config-args> <tgt-config-args> - // - step_id b (step_id::bpkg_test_separate_installed_create); + has_internal_tests = false; - step_id s ( - host_pkg - ? step_id::bpkg_test_separate_installed_create_for_host - : step_id::bpkg_test_separate_installed_create_for_module); + dir_paths subprj_dirs; // "Testable" package subprojects. - // Note: no fallback for modules. + if (!module_pkg) + { + // Collect the "testable" subprojects. // - optional<step_id> f (!module_pkg - ? step_id::bpkg_test_separate_installed_create - : optional<step_id> ()); + for (const b_project_info::subproject& sp: prj.subprojects) + { + // Retrieve the subproject information similar to how we've done it + // for the package. + // + b_project_info si (prj_info (pkg_dir / sp.path, + b_info_flags::ext_mods, + "subproject")); - r.status |= run_bpkg ( - b, - trace, r.log, wre, - bkp_step, bkp_status, last_cmd, - "-V", - "create", - "-d", host_conf, - "--type", "host", - "--name", "host", - step_args (modules, s, f), - step_args (env_args, s, f), - step_args (tgt_args, s, f)); + const strings& ops (si.operations); + if (find (ops.begin (), ops.end (), "test") != ops.end ()) + subprj_dirs.push_back (sp.path); + } - if (!r.status) - break; + has_internal_tests = !subprj_dirs.empty (); } - // Create the module configuration. - // - // Note that we never build any tests in it but only configure the - // system package. Note, however, that the host/module package - // build-time tests can potentially build some other modules here. - // - if (create_module) + if (has_internal_tests || has_runtime_tests || has_buildtime_tests) { - // b create(<dir>) config.config.load=~build2 + operation_result& r (add_result ("test-installed")); + + change_wd (trace, &r.log, rwd); + + // Make sure that the installed package executables are properly + // imported when configuring and running tests, unless we are testing + // the build system module (that supposedly doesn't install any + // executables). // - step_id b (step_id::bpkg_test_separate_installed_create); + small_vector<string, 1> envvars; - r.status |= run_b ( - b, - trace, r.log, wre, - bkp_step, bkp_status, last_cmd, - "-V", - "create(" + module_conf.representation () + ",cc)", - "config.config.load=~build2", - "config.config.persist+='config.*'@unused=drop"); + if (!module_pkg) + { + // Note that we add the $config.install.root/bin directory at the + // beginning of the PATH environment variable value, so the + // installed executables are found first. + // + string paths ("PATH=" + (*install_root / "bin").string ()); - if (!r.status) - break; + if (optional<string> s = getenv ("PATH")) + { + paths += path::traits_type::path_separator; + paths += *s; + } - // bpkg create --existing --type build2 + envvars.push_back (move (paths)); + } + + // Run internal tests. // - r.status |= run_bpkg ( - b, - trace, r.log, wre, - bkp_step, bkp_status, last_cmd, - "-v", - "create", - "--existing", - "-d", module_conf, - "--type", "build2", - "--name", "module"); + if (has_internal_tests) + { + // Create the configuration. + // + // b create(<dir>, <env-modules>) <env-config-args> + // <tgt-config-args> + // <pkg-config-args> + // + // Amalgamation directory that will contain configuration + // subdirectory for package tests out of source tree build. + // + dir_path out_dir ("build-installed"); - if (!r.status) - break; - } + { + step_id b (step_id::b_test_installed_create); + step_id s (step_id::b_test_installed_create); + step_id f (step_id::b_create); - // Link the configurations. - // - // bpkg link -d <dir> <dir> - // - { - step_id b (step_id::bpkg_test_separate_installed_link); + string mods; // build2 create meta-operation parameters. - if (create_target) - { - if (create_host) + for (const char* m: step_args (modules, s, f)) + { + mods += mods.empty () ? ", " : " "; + mods += m; + } + + r.status |= run_b ( + b, + trace, r.log, wre, + bkp_step, bkp_status, last_cmd, + "-V", + "create('" + out_dir.representation () + '\'' + mods + ')', + step_args (env_args, s, f), + step_args (tgt_args, s, f), + step_args (pkg_args, s, f)); + + if (!r.status) + break; + } + + // Configure testable subprojects sequentially and test/build in + // parallel afterwards. + // + // It feels right to configure internal tests also passing the + // main package configuration variables, since they may need to + // align with the main package setup (enable some testscripts, + // etc). + // + strings test_specs; + for (const dir_path& d: subprj_dirs) { - r.status |= run_bpkg ( + // b configure(<subprj-src-dir>@<subprj-out-dir>) <env-config-args> + // <tgt-config-args> + // <pkg-config-args> + // <pkg-vars> + // + step_id b (step_id::b_test_installed_configure); + step_id s (step_id::b_test_installed_configure); + step_id f (step_id::b_configure); + + dir_path subprj_src_dir (exists (dist_src) + ? dist_src / d + : main_pkg_conf / pkg_dir / d); + + dir_path subprj_out_dir (out_dir / d); + + r.status |= run_b ( b, + envvars, trace, r.log, wre, bkp_step, bkp_status, last_cmd, "-v", - "link", - "-d", target_conf, - host_conf); + "configure('" + + subprj_src_dir.representation () + "'@'" + + subprj_out_dir.representation () + "')", + step_args (env_args, s, f), + step_args (tgt_args, s, f), + step_args (pkg_args, s, f), + pkg_config_vars); if (!r.status) break; + + test_specs.push_back ( + "test('" + subprj_out_dir.representation () + "')"); } - if (create_module) + if (!r.status) + break; + + // Build/test subprojects. + // + // b test(<subprj-out-dir>)... <env-config-args> + // <tgt-config-args> + // <pkg-config-args> + // + if (!step_disabled (step_id::b_test_installed_test)) { - r.status |= run_bpkg ( + step_id b (step_id::b_test_installed_test); + step_id s (step_id::b_test_installed_test); + + r.status |= run_b ( b, + envvars, trace, r.log, wre, bkp_step, bkp_status, last_cmd, "-v", - "link", - "-d", target_conf, - module_conf); + test_specs, + step_args (env_args, s), + step_args (tgt_args, s), + step_args (pkg_args, s)); if (!r.status) break; } + // + // Fail if the breakpoint refers to the b.test-installed.test step + // but this step is disabled. + // + else if (bkp_step && *bkp_step == step_id::b_test_installed_test) + { + fail_unreached_breakpoint (r); + break; + } + } + // + // Fail if the breakpoint refers to some of the b.test-installed.* + // steps but the package doesn't have any internal tests. + // + else if (bkp_step && + *bkp_step >= step_id::b_test_installed_create && + *bkp_step <= step_id::b_test_installed_test) + { + fail_unreached_breakpoint (r); + break; } - if (create_host) + // Run runtime and build-time tests. + // + // Note that we only build runtime tests for target packages and for + // host packages in self-hosted configurations. + // + if (has_runtime_tests || has_buildtime_tests) { + // Create the required build configurations. + // + dir_path target_conf ("build-installed-bpkg"); + dir_path host_conf ("build-installed-bpkg-host"); + dir_path module_conf ("build-installed-bpkg-module"); + + // Create the target configuration if this is a target package + // having external runtime tests or a host/module package having + // external build-time tests. + // + bool create_target (target_pkg || has_buildtime_tests); + + // Note that even if there are no runtime tests for a host/module + // package, we still need to create the host/build2 configuration + // to configure the system package in. + // + bool create_host (host_pkg || module_pkg); + + bool create_module (module_pkg || + (host_pkg && has_buildtime_tests)); + + // Note: a module package cannot have runtime tests and so the + // module configuration is only created to serve build-time tests. + // Thus, the host or target configuration is always created as + // well and the module configuration is never a root + // configuration. + // + assert (create_target || create_host); + + // Root configuration through which we will be configuring the + // cluster. + // + const dir_path& root_conf (create_target ? target_conf : host_conf); + + // Runtime tests configuration. Should only be used if there are + // any. + // + const dir_path& runtime_tests_conf (target_pkg + ? target_conf + : host_conf); + + // Create the target configuration. + // + // bpkg create <env-modules> <env-config-args> + // <tgt-config-args> + // <pkg-config-args> + // + if (create_target) + { + step_id b (step_id::bpkg_test_separate_installed_create); + + // Note that here and below the _for_* step ids are determined + // by the main package type (and, yes, that means we will use + // the same step ids for target and host configuration -- that, + // however, should be ok since host configuration will only be + // created in the self-hosted case). + // + step_id s ( + target_pkg + ? step_id::bpkg_test_separate_installed_create_for_target + : host_pkg + ? step_id::bpkg_test_separate_installed_create_for_host + : step_id::bpkg_test_separate_installed_create_for_module); + + // Note: no fallback for modules. + // + optional<step_id> f (!module_pkg + ? step_id::bpkg_test_separate_installed_create + : optional<step_id> ()); + + r.status |= run_bpkg ( + b, + trace, r.log, wre, + bkp_step, bkp_status, last_cmd, + "-V", + "create", + "-d", target_conf, + step_args (modules, s, f), + step_args (env_args, s, f), + step_args (tgt_args, s, f), + step_args (pkg_args, s, f)); + + if (!r.status) + break; + } + + // Create the host configuration. + // + if (create_host) + { + // bpkg create --type host <env-modules> <env-config-args> + // <tgt-config-args> + // <pkg-config-args> + // + step_id b (step_id::bpkg_test_separate_installed_create); + + step_id s (host_pkg + ? step_id::bpkg_test_separate_installed_create_for_host + : step_id::bpkg_test_separate_installed_create_for_module); + + // Note: no fallback for modules. + // + optional<step_id> f (!module_pkg + ? step_id::bpkg_test_separate_installed_create + : optional<step_id> ()); + + r.status |= run_bpkg ( + b, + trace, r.log, wre, + bkp_step, bkp_status, last_cmd, + "-V", + "create", + "-d", host_conf, + "--type", "host", + "--name", "host", + step_args (modules, s, f), + step_args (env_args, s, f), + step_args (tgt_args, s, f), + step_args (pkg_args, s, f)); + + if (!r.status) + break; + } + + // Create the module configuration. + // + // Note that we never build any tests in it but only configure the + // system package. Note, however, that the host/module package + // build-time tests can potentially build some other modules here. + // if (create_module) { + // b create(<dir>) config.config.load=~build2 + // + step_id b (step_id::bpkg_test_separate_installed_create); + + r.status |= run_b ( + b, + trace, r.log, wre, + bkp_step, bkp_status, last_cmd, + "-V", + "create(" + module_conf.representation () + ",cc)", + "config.config.load=~build2", + "config.config.persist+='config.*'@unused=drop"); + + if (!r.status) + break; + + // bpkg create --existing --type build2 + // r.status |= run_bpkg ( b, trace, r.log, wre, bkp_step, bkp_status, last_cmd, "-v", - "link", - "-d", host_conf, - module_conf); + "create", + "--existing", + "-d", module_conf, + "--type", "build2", + "--name", "module"); if (!r.status) break; } - } - } - // Add and fetch the repositories. - // - if (has_runtime_tests) - { - // bpkg add <env-config-args> <tgt-config-args> <repository-url> - // - { - step_id b (step_id::bpkg_test_separate_installed_configure_add); - step_id s (step_id::bpkg_test_separate_installed_configure_add); - step_id f (step_id::bpkg_configure_add); + // Link the configurations. + // + // bpkg link -d <dir> <dir> + // + { + step_id b (step_id::bpkg_test_separate_installed_link); - r.status |= run_bpkg ( - b, - trace, r.log, wre, - bkp_step, bkp_status, last_cmd, - "-v", - "add", - "-d", runtime_tests_conf, - step_args (env_args, s, f), - step_args (tgt_args, s, f), - repo); + if (create_target) + { + if (create_host) + { + r.status |= run_bpkg ( + b, + trace, r.log, wre, + bkp_step, bkp_status, last_cmd, + "-v", + "link", + "-d", target_conf, + host_conf); + + if (!r.status) + break; + } - if (!r.status) - break; - } + if (create_module) + { + r.status |= run_bpkg ( + b, + trace, r.log, wre, + bkp_step, bkp_status, last_cmd, + "-v", + "link", + "-d", target_conf, + module_conf); + + if (!r.status) + break; + } + } - // bpkg fetch <env-config-args> <tgt-config-args> <trust-options> - // - { - step_id b (step_id::bpkg_test_separate_installed_configure_fetch); - step_id s (step_id::bpkg_test_separate_installed_configure_fetch); - step_id f (step_id::bpkg_configure_fetch); + if (create_host) + { + if (create_module) + { + r.status |= run_bpkg ( + b, + trace, r.log, wre, + bkp_step, bkp_status, last_cmd, + "-v", + "link", + "-d", host_conf, + module_conf); + + if (!r.status) + break; + } + } + } - r.status |= run_bpkg ( - b, - trace, r.log, wre, - bkp_step, bkp_status, last_cmd, - "-v", - "fetch", - "-d", runtime_tests_conf, - step_args (env_args, s, f), - step_args (tgt_args, s, f), - trust_ops); + // Add and fetch the repositories. + // + if (has_runtime_tests) + { + // bpkg add <env-config-args> <tgt-config-args> <pkg-config-args> + // <repository-url> + // + { + step_id b (step_id::bpkg_test_separate_installed_configure_add); + step_id s (step_id::bpkg_test_separate_installed_configure_add); + step_id f (step_id::bpkg_configure_add); - if (!r.status) - break; - } - } + r.status |= run_bpkg ( + b, + trace, r.log, wre, + bkp_step, bkp_status, last_cmd, + "-v", + "add", + "-d", runtime_tests_conf, + step_args (env_args, s, f), + step_args (tgt_args, s, f), + step_args (pkg_args, s, f), + repo); + + if (!r.status) + break; + } - if (has_buildtime_tests) - { - // bpkg add <env-config-args> <tgt-config-args> <repository-url> - // - { - step_id b (step_id::bpkg_test_separate_installed_configure_add); - step_id s (step_id::bpkg_test_separate_installed_configure_add); - step_id f (step_id::bpkg_configure_add); + // bpkg fetch <env-config-args> <tgt-config-args> <pkg-config-args> + // <trust-options> + // + { + step_id b (step_id::bpkg_test_separate_installed_configure_fetch); + step_id s (step_id::bpkg_test_separate_installed_configure_fetch); + step_id f (step_id::bpkg_configure_fetch); - r.status |= run_bpkg ( - b, - trace, r.log, wre, - bkp_step, bkp_status, last_cmd, - "-v", - "add", - "-d", target_conf, - step_args (env_args, s, f), - step_args (tgt_args, s, f), - repo); + r.status |= run_bpkg ( + b, + trace, r.log, wre, + bkp_step, bkp_status, last_cmd, + "-v", + "fetch", + "-d", runtime_tests_conf, + step_args (env_args, s, f), + step_args (tgt_args, s, f), + step_args (pkg_args, s, f), + trust_ops); + + if (!r.status) + break; + } + } - if (!r.status) - break; - } + if (has_buildtime_tests) + { + // bpkg add <env-config-args> <tgt-config-args> <pkg-config-args> + // <repository-url> + // + { + step_id b (step_id::bpkg_test_separate_installed_configure_add); + step_id s (step_id::bpkg_test_separate_installed_configure_add); + step_id f (step_id::bpkg_configure_add); - // bpkg fetch <env-config-args> <tgt-config-args> <trust-options> - // - { - step_id b (step_id::bpkg_test_separate_installed_configure_fetch); - step_id s (step_id::bpkg_test_separate_installed_configure_fetch); - step_id f (step_id::bpkg_configure_fetch); + r.status |= run_bpkg ( + b, + trace, r.log, wre, + bkp_step, bkp_status, last_cmd, + "-v", + "add", + "-d", target_conf, + step_args (env_args, s, f), + step_args (tgt_args, s, f), + step_args (pkg_args, s, f), + repo); + + if (!r.status) + break; + } - r.status |= run_bpkg ( - b, - trace, r.log, wre, - bkp_step, bkp_status, last_cmd, - "-v", - "fetch", - "-d", target_conf, - step_args (env_args, s, f), - step_args (tgt_args, s, f), - trust_ops); + // bpkg fetch <env-config-args> <tgt-config-args> <pkg-config-args> + // <trust-options> + // + { + step_id b (step_id::bpkg_test_separate_installed_configure_fetch); + step_id s (step_id::bpkg_test_separate_installed_configure_fetch); + step_id f (step_id::bpkg_configure_fetch); - if (!r.status) - break; - } - } + r.status |= run_bpkg ( + b, + trace, r.log, wre, + bkp_step, bkp_status, last_cmd, + "-v", + "fetch", + "-d", target_conf, + step_args (env_args, s, f), + step_args (tgt_args, s, f), + step_args (pkg_args, s, f), + trust_ops); + + if (!r.status) + break; + } + } - // Configure all the packages using a single bpkg-pkg-build command. - // - // bpkg build --configure-only <env-config-args> <tgt-config-args> - // { <config> }+ { <runtime-test>... } - // <buildtime-test>... - // ?sys:<pkg> - // - strings pkg_args; + // Configure all the packages using a single bpkg-pkg-build command. + // + // bpkg build --configure-only <env-config-args> + // <tgt-config-args> + // <pkg-config-args> + // { <config> }+ { <runtime-test>... } + // <buildtime-test>... + // ?sys:<pkg> + // + strings pkgs; - if (has_runtime_tests) - { - // Note that only host package runtime tests can (but not - // necessarily) be configured in a linked configuration and require - // --config-name to be specified for them. - // - assert (!module_pkg); + if (has_runtime_tests) + { + // Note that only host package runtime tests can (but not + // necessarily) be configured in a linked configuration and + // require --config-name to be specified for them. + // + assert (!module_pkg); - string conf_name (runtime_tests_conf == root_conf - ? "" - : "host"); + string conf_name (runtime_tests_conf == root_conf + ? "" + : "host"); - bool og (!conf_name.empty ()); + bool og (!conf_name.empty ()); - if (og) - { - pkg_args.push_back ("{"); + if (og) + { + pkgs.push_back ("{"); - pkg_args.push_back ("--config-name"); - pkg_args.push_back (conf_name); + pkgs.push_back ("--config-name"); + pkgs.push_back (conf_name); - pkg_args.push_back ("}+"); - } + pkgs.push_back ("}+"); + } - if (og && runtime_tests.size () != 1) - pkg_args.push_back ("{"); + if (og && runtime_tests.size () != 1) + pkgs.push_back ("{"); - for (const auto& t: runtime_tests) - pkg_args.push_back (t.string ()); + for (const auto& t: runtime_tests) + pkgs.push_back (t.string ()); - if (og && runtime_tests.size () != 1) - pkg_args.push_back ("}"); - } + if (og && runtime_tests.size () != 1) + pkgs.push_back ("}"); + } - if (has_buildtime_tests) - { - // Strip the build-time mark. - // - for (const auto& t: buildtime_tests) - pkg_args.push_back (t.dependency::string ()); - } + if (has_buildtime_tests) + { + // Strip the build-time mark. + // + for (const auto& t: buildtime_tests) + pkgs.push_back (t.dependency::string ()); + } - pkg_args.push_back ("?sys:" + pkg_rev); + pkgs.push_back ("?sys:" + pkg_rev); - // Finally, configure all the test packages. - // - { - step_id b (step_id::bpkg_test_separate_installed_configure_build); + // Finally, configure all the test packages. + // + { + step_id b (step_id::bpkg_test_separate_installed_configure_build); - step_id g (step_id::bpkg_global_configure_build); // Global. + step_id g (step_id::bpkg_global_configure_build); // Global. - step_id s ( - target_pkg - ? step_id::bpkg_test_separate_installed_create_for_target - : host_pkg - ? step_id::bpkg_test_separate_installed_create_for_host - : step_id::bpkg_test_separate_installed_create_for_module); + step_id s ( + target_pkg + ? step_id::bpkg_test_separate_installed_create_for_target + : host_pkg + ? step_id::bpkg_test_separate_installed_create_for_host + : step_id::bpkg_test_separate_installed_create_for_module); - step_id f (step_id::bpkg_test_separate_installed_configure_build); + step_id f (step_id::bpkg_test_separate_installed_configure_build); - r.status |= run_bpkg ( - b, - envvars, - trace, r.log, wre, - bkp_step, bkp_status, last_cmd, - "-v", - "build", - "--configure-only", - "--checkout-root", dist_installed_root, - "--yes", - "-d", root_conf, - step_args (env_args, g), - step_args (env_args, s, f), - step_args (tgt_args, g), - step_args (tgt_args, s, f), - "--", - pkg_args); + r.status |= run_bpkg ( + b, + envvars, + trace, r.log, wre, + bkp_step, bkp_status, last_cmd, + "-v", + "build", + "--configure-only", + "--checkout-root", dist_installed_root, + "--yes", + "-d", root_conf, + step_args (env_args, g), + step_args (env_args, s, f), + step_args (tgt_args, g), + step_args (tgt_args, s, f), + step_args (pkg_args, g), + step_args (pkg_args, s, f), + "--", + pkgs); - if (!r.status) - break; - } + if (!r.status) + break; + } #ifdef _WIN32 - Sleep (5000); // See above. + Sleep (5000); // See above. #endif - // Run external runtime tests. - // - if (has_runtime_tests) - { - const dir_path& runtime_tests_conf (target_pkg - ? target_conf - : host_conf); + // Note that if bpkg.test-separate-installed.update step is + // disabled, we also skip bpkg.test-separate-installed.test. + // + if (!step_disabled (step_id::bpkg_test_separate_installed_update)) + { + bool update_only ( + step_disabled (step_id::bpkg_test_separate_installed_test)); + + // Fail if the breakpoint refers to the + // bpkg.test-separate-installed.test step but this step is + // disabled. + // + if (update_only && + bkp_step && + *bkp_step == step_id::bpkg_test_separate_installed_test) + { + fail_unreached_breakpoint (r); + break; + } + + // External runtime tests. + // + if (has_runtime_tests) + { + const dir_path& runtime_tests_conf (target_pkg + ? target_conf + : host_conf); + + change_wd (trace, &r.log, runtime_tests_conf); + + if (!test (r, + runtime_tests, + dist_installed_root, + true /* installed */, + update_only, + envvars)) + break; + } - change_wd (trace, &r.log, runtime_tests_conf); + // External build-time tests. + // + if (has_buildtime_tests) + { + change_wd (trace, &r.log, rwd / target_conf); + + if (!test (r, + buildtime_tests, + dist_installed_root, + true /* installed */, + update_only, + envvars)) + break; + } + } + // + // Fail if the breakpoint refers to some of the + // bpkg.test-separate-installed.{update,test} steps but the + // bpkg.test-separate-installed.update step is disabled. + // + else if (bkp_step && + *bkp_step >= step_id::bpkg_test_separate_installed_update && + *bkp_step <= step_id::bpkg_test_separate_installed_test) + { + fail_unreached_breakpoint (r); + break; + } - if (!test (r, - runtime_tests, - dist_installed_root, - true /* installed */, - envvars)) + rm.status |= r.status; + } + // + // Fail if the breakpoint refers to some of the + // bpkg.test-separate-installed.* steps but the package has no + // external tests. + // + else if (bkp_step && + *bkp_step >= step_id::bpkg_test_separate_installed_create && + *bkp_step <= step_id::bpkg_test_separate_installed_test) + { + fail_unreached_breakpoint (r); break; + } } - - // Run external build-time tests. // - if (has_buildtime_tests) + // Fail if the breakpoint refers to some of the test installed steps + // but the package has no tests. + // + else if (bkp_step && + *bkp_step >= step_id::b_test_installed_create && + *bkp_step <= step_id::bpkg_test_separate_installed_test) { - change_wd (trace, &r.log, rwd / target_conf); - - if (!test (r, - buildtime_tests, - dist_installed_root, - true /* installed */, - envvars)) + fail_unreached_breakpoint (add_result ("test-installed")); break; } - rm.status |= r.status; - } - } + // Uninstall. + // + { + operation_result& r (add_result ("uninstall")); - // Uninstall. - // - { - operation_result& r (add_result ("uninstall")); + change_wd (trace, &r.log, install_conf); - change_wd (trace, &r.log, install_conf); + // bpkg uninstall <env-config-args> <tgt-config-args> <pkg-config-args> + // <package-name> + // + step_id b (step_id::bpkg_uninstall); + step_id s (step_id::bpkg_uninstall); - // bpkg uninstall <env-config-args> <tgt-config-args> <package-name> - // - step_id b (step_id::bpkg_uninstall); - step_id s (step_id::bpkg_uninstall); + r.status |= run_bpkg ( + b, + trace, r.log, wre, + bkp_step, bkp_status, last_cmd, + "-v", + "uninstall", + step_args (env_args, s), + step_args (tgt_args, s), + step_args (pkg_args, s), + pkg); - r.status |= run_bpkg ( - b, - trace, r.log, wre, - bkp_step, bkp_status, last_cmd, - "-v", - "uninstall", - step_args (env_args, s), - step_args (tgt_args, s), - pkg); + if (!r.status) + break; - if (!r.status) + rm.status |= r.status; + } + } + // + // Fail if the breakpoint refers to some of the install/test installed + // steps but the package either is not supposed to be installed (the + // target configuration doesn't specify config.install.root, etc) or the + // bpkg.install step is disabled. + // + else if (bkp_step && + *bkp_step >= step_id::bpkg_install && + *bkp_step <= step_id::bpkg_uninstall) + { + fail_unreached_breakpoint (add_result ("install")); break; - - rm.status |= r.status; + } + } + // + // Fail if the breakpoint refers to bpkg.update or any dependent step but + // the bpkg.update step is disabled. + // + else if (bkp_step && + *bkp_step >= step_id::bpkg_update && + *bkp_step <= step_id::bpkg_uninstall) + { + fail_unreached_breakpoint (add_result ("update")); + break; } break; diff --git a/doc/manual.cli b/doc/manual.cli index 4e5a3c0..b50ad77 100644 --- a/doc/manual.cli +++ b/doc/manual.cli @@ -964,13 +964,15 @@ repository by executing the following commands, collectively called a \i{worker script}. Each command has a unique \i{step id} that can be used as a breakpoint and normally as a prefix in the \c{<tgt-config-args>}, \c{<env-config-args>}, and \c{<env-modules>} values as discussed in -\l{#arch-controller Controller Logic}. The \c{<>}-values are from the task -manifest and the environment though some are assigned by the worker during the -script execution (configuration directories, UUIDs, etc). In particular, the -\c{<pkg-config-opts>}, \c{<pkg-config-vars>}, \c{<dependency-name>}, -\c{<dependency-version-constraint>}, and \c{<dep-config-vars>} values result -from parsing the \l{#arch-task-package-config \c{package-config}} task -manifest value. +\l{#arch-controller Controller Logic} as well as in the \c{<pkg-config-args>} +values (see below). The \c{<>}-values are from the task manifest and the +environment though some are assigned by the worker during the script execution +(configuration directories, UUIDs, etc). In particular, the +\c{<pkg-config-args>} (prefixed global options and variables), +\c{<pkg-config-opts>} (unprefixed options), \c{<pkg-config-vars>} (unprefixed +variables), \c{<dependency-name>}, \c{<dependency-version-constraint>}, and +\c{<dep-config-vars>} values result from parsing the +\l{#arch-task-package-config \c{package-config}} task manifest value. Some prefix step ids have fallback step ids which are used in the absence of the primary step id values. If the prefix step id differs from the breakpoint @@ -1008,7 +1010,8 @@ Worker script for \c{target} packages: \ # bpkg.create (bpkg.target.create : b.create, bpkg.create) # -bpkg -V create <env-modules> <env-config-args> <tgt-config-args> +bpkg -V create <env-modules> \\ + <env-config-args> <tgt-config-args> <pkg-config-args> # bpkg.configure.add # @@ -1023,7 +1026,8 @@ bpkg -v fetch --trust <repository-fp> # (bpkg.target.configure.build : b.configure, bpkg.configure.build)) # bpkg -v build --configure-only \\ - [<pkg-config-opts>] <env-config-args> <tgt-config-args> \\ + <env-config-args> <tgt-config-args> <pkg-config-args> \\ + [<pkg-config-opts>] \\ [{ <pkg-config-vars> }+] <package-name>/<package-version> \\ [<test-package-name>[ <test-version-constraint>]...] \\ [([{ <dep-config-vars> }+] \\ @@ -1068,7 +1072,8 @@ bpkg -v update <package-name> { # b.test-installed.create ( : b.create) # - b -V create <env-modules> <env-config-args> <tgt-config-args> + b -V create <env-modules> \\ + <env-config-args> <tgt-config-args> <pkg-config-args> # For each test subproject: # @@ -1091,7 +1096,8 @@ bpkg -v update <package-name> # bpkg.test-separate-installed.create_for_target : # bpkg.test-separate-installed.create) # - bpkg -V create <env-modules> <env-config-args> <tgt-config-args> + bpkg -V create <env-modules> \\ + <env-config-args> <tgt-config-args> <pkg-config-args> # bpkg.test-separate-installed.configure.add ( # : bpkg.configure.add) @@ -1108,7 +1114,8 @@ bpkg -v update <package-name> # (bpkg.test-separate-installed.configure.build_for_target : # bpkg.test-separate-installed.configure.build)) # - bpkg -v build --configure-only <env-config-args> <tgt-config-args> \\ + bpkg -v build --configure-only \\ + <env-config-args> <tgt-config-args> <pkg-config-args> \\ <test-package-name>[ <test-version-constraint>]... \\ ?sys:<package-name>/<package-version> @@ -1144,8 +1151,8 @@ Worker script for \c{host} packages: { # bpkg.create (bpkg.host.create : b.create, bpkg.create) # - bpkg -V create --type host -d <host-conf> \\ - <env-modules> <env-config-args> <tgt-config-args> + bpkg -V create --type host -d <host-conf> <env-modules> \\ + <env-config-args> <tgt-config-args> <pkg-config-args> } # # Otherwise: @@ -1170,8 +1177,8 @@ bpkg -v fetch -d <host-conf> --trust <repository-fp> { # bpkg.create (bpkg.target.create : b.create, bpkg.create) # - bpkg -V create -d <install-conf> \\ - <env-modules> <env-config-args> <tgt-config-args> + bpkg -V create -d <install-conf> <env-modules> \\ + <env-config-args> <tgt-config-args> <pkg-config-args> # [bpkg.link] # @@ -1192,8 +1199,8 @@ bpkg -v fetch -d <host-conf> --trust <repository-fp> { # bpkg.create (bpkg.target.create : b.create, bpkg.create) # - bpkg -V create -d <target-conf> \\ - <env-modules> <env-config-args> <tgt-config-args> + bpkg -V create -d <target-conf> <env-modules> \\ + <env-config-args> <tgt-config-args> <pkg-config-args> # [bpkg.create] # @@ -1241,20 +1248,25 @@ bpkg -v fetch -d <host-conf> --trust <repository-fp> # bpkg.configure.build. # bpkg -v build --configure-only \\ -[<pkg-config-opts>] <env-config-args> <tgt-config-args> \\ +<env-config-args> <tgt-config-args> <pkg-config-args> \\ +[<pkg-config-opts>] \\ \\ { --config-uuid <host-uuid> \\ - <env-config-args> <tgt-config-args> [<pkg-config-vars>] }+ \\ + <env-config-args> <tgt-config-args> <pkg-config-args> \\ + [<pkg-config-vars>] }+ \\ <package-name>/<package-version> \\ \\ { --config-uuid <install-uuid> \\ - <env-config-args> <tgt-config-args> [<pkg-config-vars>] }+ \\ + <env-config-args> <tgt-config-args> <pkg-config-args> \\ + [<pkg-config-vars>] }+ \\ <package-name>/<package-version> \\ \\ -{ --config-uuid <host-uuid> <env-config-args> <tgt-config-args> }+ \\ +{ --config-uuid <host-uuid> \\ + <env-config-args> <tgt-config-args> <pkg-config-args> }+ \\ { <runtime-test-package-name>[ test-version-constraint>]... } \\ \\ -{ --config-uuid <target-uuid> <env-config-args> <tgt-config-args> }+ \\ +{ --config-uuid <target-uuid> \\ + <env-config-args> <tgt-config-args> <pkg-config-args> }+ \\ { <buildtime-test-package-name>[ test-version-constraint>]... } \\ \\ ({ --config-uuid <host-uuid> [--config-uuid <install-uuid>] \\ @@ -1312,7 +1324,8 @@ bpkg -v update -d <host-conf> <package-name> { # b.test-installed.create ( : b.create) # - b -V create <env-modules> <env-config-args> <tgt-config-args> + b -V create <env-modules> \\ + <env-config-args> <tgt-config-args> <pkg-config-args> # For each test subproject: # @@ -1335,8 +1348,8 @@ bpkg -v update -d <host-conf> <package-name> # bpkg.test-separate-installed.create_for_host : # bpkg.test-separate-installed.create) # - bpkg -V create --type host -d <host-conf> \\ - <env-modules> <env-config-args> <tgt-config-args> + bpkg -V create --type host -d <host-conf> <env-modules> \\ + <env-config-args> <tgt-config-args> <pkg-config-args> # If task manifest refers to any runtime tests, examples, or # benchmarks packages: @@ -1361,8 +1374,8 @@ bpkg -v update -d <host-conf> <package-name> # bpkg.test-separate-installed.create_for_host : # bpkg.test-separate-installed.create) # - bpkg -V create -d <target-conf> \\ - <env-modules> <env-config-args> <tgt-config-args> + bpkg -V create -d <target-conf> <env-modules> \\ + <env-config-args> <tgt-config-args> <pkg-config-args> # [bpkg.test-separate-installed.create] # @@ -1394,7 +1407,8 @@ bpkg -v update -d <host-conf> <package-name> # Note that any of the runtime or build-time tests related parts # (but not both) may be omitted. # - bpkg -v build --configure-only <env-config-args> <tgt-config-args> \\ + bpkg -v build --configure-only \\ + <env-config-args> <tgt-config-args> <pkg-config-args> \\ \\ { --config-name <host-conf> }+ \\ { <runtime-test-package-name>[ <test-version-constraint>]... } \\ @@ -1437,7 +1451,7 @@ Worker script for \c{module} packages: # bpkg.create (bpkg.module.create) # b -V create(<module-conf>, <env-modules>) config.config.load=~build2 \\ - <env-config-args> <tgt-config-args> + <env-config-args> <tgt-config-args> <pkg-config-args> bpkg -v create --existing --type build2 -d <module-conf> } # @@ -1464,7 +1478,8 @@ bpkg -v fetch -d <module-conf> --trust <repository-fp> # bpkg.create (bpkg.module.create) # b -V create(<install-conf>, <env-modules>) \\ - config.config.load=~build2 <env-config-args> <tgt-config-args> + config.config.load=~build2 \\ + <env-config-args> <tgt-config-args> <pkg-config-args> bpkg -v create --existing --type build2 -d <install-conf> # bpkg.configure.add @@ -1482,8 +1497,8 @@ bpkg -v fetch -d <module-conf> --trust <repository-fp> { # bpkg.create (bpkg.target.create : b.create, bpkg.create) # - bpkg -V create -d <target-conf> \\ - <env-modules> <env-config-args> <tgt-config-args> + bpkg -V create -d <target-conf> <env-modules> \\ + <env-config-args> <tgt-config-args> <pkg-config-args> # [bpkg.create] # @@ -1522,17 +1537,21 @@ bpkg -v fetch -d <module-conf> --trust <repository-fp> # bpkg.configure.build. # bpkg -v build --configure-only \\ -[<pkg-config-opts>] <env-config-args> <tgt-config-args> \\ +<env-config-args> <tgt-config-args> <pkg-config-args> \\ +[<pkg-config-opts>] \\ \\ { --config-uuid <module-uuid> \\ - <env-config-args> <tgt-config-args> [<pkg-config-vars>] }+ \\ + <env-config-args> <tgt-config-args> <pkg-config-args> \\ + [<pkg-config-vars>] }+ \\ <package-name>/<package-version> \\ \\ { --config-uuid <install-uuid> \\ - <env-config-args> <tgt-config-args> [<pkg-config-vars>] }+ \\ + <env-config-args> <tgt-config-args> <pkg-config-args> \\ + [<pkg-config-vars>] }+ \\ <package-name>/<package-version> \\ \\ -{ --config-uuid <target-uuid> <env-config-args> <tgt-config-args> }+ \\ +{ --config-uuid <target-uuid> \\ + <env-config-args> <tgt-config-args> <pkg-config-args> }+ \\ { <buildtime-test-package-name>[ test-version-constraint>]... } \\ \\ ({ --config-uuid <host-uuid> [--config-uuid <install-uuid>] \\ @@ -1584,15 +1603,15 @@ bpkg -v update -d <module-conf> <package-name> # bpkg.test-separate-installed.create_for_module : # bpkg.test-separate-installed.create) # - bpkg -V create -d <target-conf> \\ - <env-modules> <env-config-args> <tgt-config-args> + bpkg -V create -d <target-conf> <env-modules> \\ + <env-config-args> <tgt-config-args> <pkg-config-args> # bpkg.test-separate-installed.create ( # bpkg.test-separate-installed.create_for_module : # bpkg.test-separate-installed.create) # - bpkg -V create --type host -d <host-conf> \\ - <env-modules> <env-config-args> <tgt-config-args> + bpkg -V create --type host -d <host-conf> <env-modules> \\ + <env-config-args> <tgt-config-args> <pkg-config-args> # [bpkg.test-separate-installed.link] # @@ -1615,7 +1634,8 @@ bpkg -v update -d <module-conf> <package-name> # (bpkg.test-separate-installed.configure.build_for_module : # bpkg.test-separate-installed.configure.build)) # - bpkg -v build --configure-only <env-config-args> <tgt-config-args> \\ + bpkg -v build --configure-only \\ + <env-config-args> <tgt-config-args> <pkg-config-args> \\ \\ { --config-name <target-conf> }+ \\ <buildtime-test-package-name>[ <test-version-constraint>]... \\ @@ -1704,7 +1724,8 @@ to the \c{buildtab} configuration file. Blank lines and lines that start with \ <machine-pattern> <target-config> <target>[/<environment>] <classes> [<tgt-config-arg>]* [<warning-regex>]* -<tgt-config-arg> = [<prefix>:](<variable>|<option>) +<tgt-config-arg> = [[+|-]<prefix>:](<variable>|<option>) | \\ + (+|-)<prefix>: <prefix> = <tool>[.<phase>][.<operation>[.<command>]] \ @@ -1741,12 +1762,32 @@ build task manifest. Values in the \c{<tgt-config-arg>} list can be opionally prefixed with the \i{step id} or a leading portion thereof to restrict it to a specific step, operation, phase, or tool in the \i{worker script} (see \l{#arch-worker Worker -Logic}). Unprefixed values only apply to the \c{*.create[_for_*]} steps. Note -that options with values can only be specified using the single argument +Logic}). The prefix can optionally begin with the \c{+} or \c{-} character (in +this case the argument can be omitted) to enable or disable the respective +step. The steps which can be enabled or disabled are: + +\ +bpkg.update +bpkg.test +bpkg.test-separate.update +bpkg.test-separate.test +bpkg.bindist # Disabled by default. +bpkg.install # Disabled if bpkg.bindist is enabled. +bbot.sys-install # Disabled if bpkg.bindist is disabled. +b.test-installed.test +bpkg.test-separate-installed.update +bpkg.test-separate-installed.test +\ + +Unprefixed values only apply to the \c{*.create[_for_*]} steps. Note that +options with values can only be specified using the single argument notation. For example: \ -bpkg:--fetch-timeout=600 bpkg.configure.fetch:--fetch-timeout=60 b:-j1 +bpkg:--fetch-timeout=600 \\ +bpkg.configure.fetch:--fetch-timeout=60 \\ ++bpkg.bindist: \\ +b:-j1 \ Note that each machine name is matched against every pattern and all the diff --git a/tests/integration/testscript b/tests/integration/testscript index 31cf54c..1e2ebb7 100644 --- a/tests/integration/testscript +++ b/tests/integration/testscript @@ -60,7 +60,14 @@ rep_type = pkg rfp = yes #host='host: true' #dependency_checksum = 'dependency-checksum: e6f10587696020674c260669f4e7000a0139df72467bff9770aea2f2b8b57ba0' -#package_config = 'package-config: sys:libuuid-c++ --sys-install --sys-no-stub --sys-yes' +#\ +package_config = 'package-config:\ +bpkg.configure.fetch:--fetch-timeout=120 -bpkg.install: +config.libhello.develop=true +sys:libuuid-c++ --sys-install --sys-no-stub --sys-yes +\ +' +#\ #\ pkg = hello @@ -149,7 +156,7 @@ config.bpkg.tests.remote=true #\ pkg = cli -ver = 1.2.0-b.9.20230109143034.6e32dd9c26d2 +ver = 1.2.0-b.9.20230320105544.115e8dc4c504 rep_url = "https://git.codesynthesis.com/cli/cli.git#master" rep_type = git #rep_url = https://stage.build2.org/1 @@ -205,6 +212,7 @@ package_config = 'package-config: config.libxerces_c.network=true "?libcurl ~7.76.0" sys:libz/* +-bpkg.update: \' #\ @@ -256,7 +264,7 @@ config.cc.coptions=-Wall \ b.test-installed.configure:\"config.cc.loptions=-L'$~/install/lib'\" \ bpkg.test-separate-installed.create:\"config.cc.loptions=-L'$~/install/lib'\"" -#interactive="interactive: bpkg.configure.build" +#interactive="interactive: b.test-installed.configure" #interactive="interactive: warning" +cat <<"EOI" >=task |