diff options
-rw-r--r-- | bpkg/package-skeleton.cxx | 2 | ||||
-rw-r--r-- | bpkg/package.hxx | 13 | ||||
-rw-r--r-- | bpkg/pkg-command.cxx | 46 |
3 files changed, 51 insertions, 10 deletions
diff --git a/bpkg/package-skeleton.cxx b/bpkg/package-skeleton.cxx index c3015da..899fb48 100644 --- a/bpkg/package-skeleton.cxx +++ b/bpkg/package-skeleton.cxx @@ -31,7 +31,7 @@ using namespace butl; namespace bpkg { - // These are defined in bpkg.cxx and initialized in main(). + // These are defined in bpkg.cxx and initialized by build2_init(). // extern strings build2_cmd_vars; extern build2::scheduler build2_sched; diff --git a/bpkg/package.hxx b/bpkg/package.hxx index 1c70676..3283be5 100644 --- a/bpkg/package.hxx +++ b/bpkg/package.hxx @@ -1261,13 +1261,12 @@ namespace bpkg // optional<std::string> buildfiles_checksum; - // Path to the output directory of this package, if any. It is - // always relative to the configuration directory, and is <name> - // for external packages and <name>-<version> for others. It is - // only set once the package is configured and its main purse is - // to keep track of what needs to be cleaned by the user before - // a broken package can be purged. Note that it could be the - // same as src_root. + // Path to the output directory of this package, if any. It is always + // relative to the configuration directory, and is <name> for external + // packages and <name>-<version> for others. It is only set once the + // package is configured and its main purpose is to keep track of what + // needs to be cleaned by the user before a broken package can be + // purged. Note that it could be the same as src_root. // optional<dir_path> out_root; diff --git a/bpkg/pkg-command.cxx b/bpkg/pkg-command.cxx index 5788e11..20e5230 100644 --- a/bpkg/pkg-command.cxx +++ b/bpkg/pkg-command.cxx @@ -5,6 +5,9 @@ #include <libbutl/path-pattern.hxx> +#include <libbuild2/file.hxx> +#include <libbuild2/context.hxx> + #include <bpkg/package.hxx> #include <bpkg/package-odb.hxx> #include <bpkg/database.hxx> @@ -54,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) @@ -74,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 (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 += ' '; |