aboutsummaryrefslogtreecommitdiff
path: root/bpkg/pkg-command.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'bpkg/pkg-command.cxx')
-rw-r--r--bpkg/pkg-command.cxx137
1 files changed, 115 insertions, 22 deletions
diff --git a/bpkg/pkg-command.cxx b/bpkg/pkg-command.cxx
index 11f10f0..20e5230 100644
--- a/bpkg/pkg-command.cxx
+++ b/bpkg/pkg-command.cxx
@@ -3,7 +3,10 @@
#include <bpkg/pkg-command.hxx>
-#include <libbutl/path-pattern.mxx>
+#include <libbutl/path-pattern.hxx>
+
+#include <libbuild2/file.hxx>
+#include <libbuild2/context.hxx>
#include <bpkg/package.hxx>
#include <bpkg/package-odb.hxx>
@@ -18,7 +21,6 @@ namespace bpkg
{
void
pkg_command (const string& cmd,
- const dir_path& c,
const common_options& o,
const string& cmd_v,
const strings& cvars,
@@ -55,6 +57,8 @@ namespace bpkg
}
};
+ unique_ptr<build2::context> ctx; // Create lazily.
+
for (const pkg_command_vars& pv: ps)
{
if (!pv.vars.empty () || pv.cwd)
@@ -75,12 +79,49 @@ namespace bpkg
const shared_ptr<selected_package>& p (pv.pkg);
- assert (p->state == package_state::configured);
- assert (p->out_root); // Should be present since configured.
+ assert (p->state == package_state::configured &&
+ p->substate != package_substate::system);
+ assert (p->out_root &&
+ p->src_root); // Should be present since configured, not system.
- dir_path out_root (p->effective_out_root (c));
+ dir_path out_root (p->effective_out_root (pv.config_orig));
l4 ([&]{trace << p->name << " out_root: " << out_root;});
+ // Figure out if the source directory is forwarded to this out_root. If
+ // it is, then we need to build via src_root. Failed that, backlinks
+ // won't be created.
+ //
+ if (*p->out_root != *p->src_root)
+ {
+ dir_path src_root (p->effective_src_root (pv.config_orig));
+
+ // For us to switch to src_root, it should not only be configured as
+ // forwarded, but also be forwarded to our out_root. So we actually
+ // need to first check if the build/bootstrap/out-root.build (or its
+ // alt naming equivalent) exists and, if so, extract the out_root
+ // value and compare it to ours. This is all done by bootstrap_fwd()
+ // from libbuild2 so seeing that we act as a special build system
+ // driver, we might as well use that. Note that this could potentially
+ // be improved by only creating context if the file exists.
+ //
+ try
+ {
+ if (ctx == nullptr)
+ ctx.reset (new build2::context ());
+
+ optional<bool> altn;
+ if (build2::bootstrap_fwd (*ctx, src_root, altn) == out_root)
+ {
+ out_root = move (src_root);
+ l4 ([&]{trace << p->name << " src_root: " << out_root;});
+ }
+ }
+ catch (const build2::failed&)
+ {
+ throw failed (); // Assume the diagnostics has already been issued.
+ }
+ }
+
if (bspec.back () != '(')
bspec += ' ';
@@ -115,10 +156,19 @@ namespace bpkg
collect_dependencies (const shared_ptr<selected_package>& p,
bool recursive,
bool package_cwd,
- vector<pkg_command_vars>& ps)
+ vector<pkg_command_vars>& ps,
+ bool allow_host_type)
{
for (const auto& pr: p->prerequisites)
{
+ if (!allow_host_type)
+ {
+ database& db (pr.first.database ());
+
+ if (db.type == host_config_type || db.type == build2_config_type)
+ continue;
+ }
+
shared_ptr<selected_package> d (pr.first.load ());
// The selected package can only be configured if all its dependencies
@@ -133,14 +183,24 @@ namespace bpkg
[&d] (const pkg_command_vars& i) {return i.pkg == d;}) ==
ps.end ())
{
+ database& db (pr.first.database ());
+
// Note: no package-specific variables (global ones still apply).
//
- ps.push_back (pkg_command_vars {d,
- strings () /* vars */,
- package_cwd});
+ ps.push_back (
+ pkg_command_vars {
+ db.config_orig,
+ db.main (),
+ d,
+ strings () /* vars */,
+ package_cwd});
if (recursive)
- collect_dependencies (d, recursive, package_cwd, ps);
+ collect_dependencies (d,
+ recursive,
+ package_cwd,
+ ps,
+ allow_host_type);
}
}
}
@@ -154,6 +214,7 @@ namespace bpkg
bool all,
const strings& all_patterns,
bool package_cwd,
+ bool allow_host_type,
cli::group_scanner& args)
{
tracer trace ("pkg_command");
@@ -194,7 +255,7 @@ namespace bpkg
if (args.group ().more ())
fail << "unexpected options group for variable '" << a << "'";
- cvars.push_back (move (a));
+ cvars.push_back (move (trim (a)));
}
else
{
@@ -209,7 +270,7 @@ namespace bpkg
if (a.find ('=') == string::npos)
fail << "unexpected group argument '" << a << "'";
- vars.push_back (move (a));
+ vars.push_back (move (trim (a)));
}
pkg_args.push_back (pkg_arg {move (n), move (vars)});
@@ -248,7 +309,16 @@ namespace bpkg
vector<pkg_command_vars> ps;
{
- database db (open (c, trace));
+ database db (c, trace, true /* pre_attach */);
+
+ if (!allow_host_type && (db.type == host_config_type ||
+ db.type == build2_config_type))
+ {
+ fail << "unable to " << cmd << " from " << db.type
+ << " configuration" <<
+ info << "use target configuration instead";
+ }
+
transaction t (db);
// We need to suppress duplicate dependencies for the recursive command
@@ -256,23 +326,33 @@ namespace bpkg
//
session ses;
- auto add = [&ps, recursive, immediate, package_cwd] (
+ auto add =
+ [&db, &ps, allow_host_type, recursive, immediate, package_cwd] (
const shared_ptr<selected_package>& p,
strings vars)
{
- ps.push_back (pkg_command_vars {p, move (vars), package_cwd});
+ ps.push_back (
+ pkg_command_vars {db.config_orig,
+ db.main (),
+ p,
+ move (vars),
+ package_cwd});
// Note that it can only be recursive or immediate but not both.
//
if (recursive || immediate)
- collect_dependencies (p, recursive, package_cwd, ps);
+ collect_dependencies (p,
+ recursive,
+ package_cwd,
+ ps,
+ allow_host_type);
};
if (all || !all_patterns.empty ())
{
using query = query<selected_package>;
- query q (query::hold_package &&
+ query q (query::hold_package &&
query::state == "configured" &&
query::substate != "system");
@@ -310,13 +390,13 @@ namespace bpkg
<< "configuration " << c;
if (p->state != package_state::configured)
- fail << "package " << a.name << " is " << p->state <<
+ fail << "package " << a.name << db << " is " << p->state <<
info << "expected it to be configured";
if (p->substate == package_substate::system)
- fail << "cannot " << cmd << " system package " << a.name;
+ fail << "cannot " << cmd << " system package " << a.name << db;
- l4 ([&]{trace << *p;});
+ l4 ([&]{trace << *p << db;});
add (p, move (a.vars));
}
@@ -325,14 +405,27 @@ namespace bpkg
t.commit ();
}
- pkg_command (cmd, c, o, cmd_v, cvars, ps);
+ pkg_command (cmd, o, cmd_v, cvars, ps);
if (verb && !o.no_result ())
{
for (const pkg_command_vars& pv: ps)
- text << cmd << (cmd.back () != 'e' ? "ed " : "d ") << *pv.pkg;
+ text << cmd << (cmd.back () != 'e' ? "ed " : "d ") << pv.string ();
}
return 0;
}
+
+ // pkg_command_vars
+ //
+ string pkg_command_vars::
+ string () const
+ {
+ std::string r (pkg->string ());
+
+ if (!config_main)
+ r += " [" + config_orig.representation () + ']';
+
+ return r;
+ }
}