From 5d513688ae07d96910dd1eef83bdad4e9d780373 Mon Sep 17 00:00:00 2001 From: Karen Arutyunov Date: Thu, 22 Apr 2021 21:57:13 +0300 Subject: Add support for linked configurations --- bpkg/pkg-configure.cxx | 134 ++++++++++++++++++++++++++++++++++--------------- 1 file changed, 93 insertions(+), 41 deletions(-) (limited to 'bpkg/pkg-configure.cxx') diff --git a/bpkg/pkg-configure.cxx b/bpkg/pkg-configure.cxx index cd55575..aaf9033 100644 --- a/bpkg/pkg-configure.cxx +++ b/bpkg/pkg-configure.cxx @@ -20,14 +20,14 @@ namespace bpkg { package_prerequisites pkg_configure_prerequisites (const common_options& o, - transaction& t, + database& db, + transaction&, const dependencies& deps, - const package_name& package) + const package_name& package, + const function& fdb) { package_prerequisites r; - database& db (t.database ()); - for (const dependency_alternatives_ex& da: deps) { assert (!da.conditional); //@@ TODO @@ -57,13 +57,16 @@ namespace bpkg satisfied = true; break; } - // else - // - // @@ TODO: in the future we would need to at least make sure the - // build and target machines are the same. See also pkg-build. } - if (shared_ptr dp = db.find (n)) + database* ddb (fdb ? fdb (db, n, da.buildtime) : nullptr); + + pair, database*> spd ( + ddb != nullptr + ? make_pair (ddb->find (n), ddb) + : find_dependency (db, n, da.buildtime)); + + if (const shared_ptr& dp = spd.first) { if (dp->state != package_state::configured) continue; @@ -71,27 +74,32 @@ namespace bpkg if (!satisfies (dp->version, d.constraint)) continue; - auto p (r.emplace (dp, d.constraint)); - - // Currently we can only capture a single constraint, so if we - // already have a dependency on this package and one constraint is - // not a subset of the other, complain. + // See the package_prerequisites definition for details on creating + // the map keys with the database passed. // - if (!p.second) - { - auto& c (p.first->second); - - bool s1 (satisfies (c, d.constraint)); - bool s2 (satisfies (d.constraint, c)); - - if (!s1 && !s2) - fail << "multiple dependencies on package " << n << - info << n << " " << *c << - info << n << " " << *d.constraint; - - if (s2 && !s1) - c = d.constraint; - } + auto p ( + r.emplace (lazy_shared_ptr (*spd.second, dp), + d.constraint)); + + // Currently we can only capture a single constraint, so if we + // already have a dependency on this package and one constraint is + // not a subset of the other, complain. + // + if (!p.second) + { + auto& c (p.first->second); + + bool s1 (satisfies (c, d.constraint)); + bool s2 (satisfies (d.constraint, c)); + + if (!s1 && !s2) + fail << "multiple dependencies on package " << n << + info << n << " " << *c << + info << n << " " << *d.constraint; + + if (s2 && !s1) + c = d.constraint; + } satisfied = true; break; @@ -106,22 +114,23 @@ namespace bpkg } void - pkg_configure (const dir_path& c, - const common_options& o, + pkg_configure (const common_options& o, + database& db, transaction& t, const shared_ptr& p, const dependencies& deps, const strings& vars, - bool simulate) + bool simulate, + const function& fdb) { tracer trace ("pkg_configure"); assert (p->state == package_state::unpacked); assert (p->src_root); // Must be set since unpacked. - database& db (t.database ()); tracer_guard tg (db, trace); + const dir_path& c (db.config_orig); dir_path src_root (p->effective_src_root (c)); // Calculate package's out_root. @@ -139,10 +148,53 @@ namespace bpkg // assert (p->prerequisites.empty ()); - p->prerequisites = pkg_configure_prerequisites (o, t, deps, p->name); + p->prerequisites = pkg_configure_prerequisites (o, + db, + t, + deps, + p->name, + fdb); if (!simulate) { + // Add the config.import.* variables for prerequisites from the linked + // configurations. + // + strings imports; + + for (const auto& pp: p->prerequisites) + { + database& pdb (pp.first.database ()); + + if (pdb != db) + { + shared_ptr sp (pp.first.load ()); + + if (!sp->system ()) + { + // @@ Note that this doesn't work for build2 modules that require + // bootstrap. For their dependents we need to specify the + // import variable as a global override, whenever required + // (configure, update, etc). + // + // This, in particular, means that if we build a package that + // doesn't have direct build2 module dependencies but some of + // its (potentially indirect) dependencies do, then we still + // need to specify the !config.import.* global overrides for + // all of the involved build2 modules. Implementation of that + // feels too hairy at the moment, so let's handle all the + // build2 modules uniformly for now. + // + // Also note that such modules are marked with `requires: + // bootstrap` in their manifest. + // + dir_path od (sp->effective_out_root (pdb.config)); + imports.push_back ("config.import." + sp->name.variable () + + "='" + od.representation () + "'"); + } + } + } + // Form the buildspec. // string bspec; @@ -162,7 +214,7 @@ namespace bpkg // try { - run_b (o, verb_b::quiet, vars, bspec); + run_b (o, verb_b::quiet, imports, vars, bspec); } catch (const failed&) { @@ -180,7 +232,7 @@ namespace bpkg // Commits the transaction. // - pkg_disfigure (c, o, t, p, true /* clean */, false /* simulate */); + pkg_disfigure (o, db, t, p, true /* clean */, false /* simulate */); throw; } } @@ -195,11 +247,11 @@ namespace bpkg shared_ptr pkg_configure_system (const package_name& n, const version& v, + database& db, transaction& t) { tracer trace ("pkg_configure_system"); - database& db (t.database ()); tracer_guard tg (db, trace); shared_ptr p ( @@ -269,7 +321,7 @@ namespace bpkg if (ps == package_scheme::sys && !vars.empty ()) fail << "configuration variables specified for a system package"; - database db (open (c, trace)); + database db (c, trace, true /* pre_attach */); transaction t (db); session s; @@ -297,7 +349,7 @@ namespace bpkg if (filter_one (root, db.query (q)).first == nullptr) fail << "unknown package " << n; - p = pkg_configure_system (n, v.empty () ? wildcard_version : v, t); + p = pkg_configure_system (n, v.empty () ? wildcard_version : v, db, t); } else { @@ -319,8 +371,8 @@ namespace bpkg true /* ignore_unknown */, [&p] (version& v) {v = p->version;})); - pkg_configure (c, - o, + pkg_configure (o, + db, t, p, convert (move (m.dependencies)), -- cgit v1.1