aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2023-02-21 07:23:13 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2023-02-21 07:23:13 +0200
commit7e46e1fd6fa31de4a3f7ff013d2d1a4be225f45f (patch)
treeb1ec756138c3b477a95ee34764a280700cb4ed75
parentec8d4b6a49549447cead39a2a4bf84c03d5636ab (diff)
Collect languages for recursive dependencies
-rw-r--r--bpkg/pkg-bindist.cxx97
-rw-r--r--bpkg/system-package-manager-debian.cxx18
-rw-r--r--bpkg/system-package-manager-debian.hxx2
-rw-r--r--bpkg/system-package-manager-fedora.cxx2
-rw-r--r--bpkg/system-package-manager-fedora.hxx2
-rw-r--r--bpkg/system-package-manager.hxx12
6 files changed, 105 insertions, 28 deletions
diff --git a/bpkg/pkg-bindist.cxx b/bpkg/pkg-bindist.cxx
index ac774b1..e191996 100644
--- a/bpkg/pkg-bindist.cxx
+++ b/bpkg/pkg-bindist.cxx
@@ -55,15 +55,56 @@ namespace bpkg
return r;
}
+ // Merge dependency languages for the (ultimate) dependent of the specified
+ // type.
+ //
+ static void
+ merge_languages (const string& type,
+ small_vector<language, 1>& langs,
+ const available_package& ap)
+ {
+ for (const language& l: ap.effective_languages ())
+ {
+ // Unless both the dependent and dependency types are libraries, the
+ // interface/implementation distinction does not apply.
+ //
+ bool lib (type == "lib" && ap.effective_type () == "lib");
+
+ auto i (find_if (langs.begin (), langs.end (),
+ [&l] (const language& x)
+ {
+ return x.name == l.name;
+ }));
+
+ if (i == langs.end ())
+ {
+ // If this is an implementation language for a dependency, then it is
+ // also an implementation language for a dependent. The converse,
+ // howevere, depends on whether this dependency is an interface or
+ // imlementation of this dependent, which we do not know. So we have
+ // to assume it's interface.
+ //
+ langs.push_back (language {l.name, lib && l.impl});
+ }
+ else
+ {
+ i->impl = i->impl && (lib && l.impl); // Merge.
+ }
+ }
+ }
+
// Collect dependencies of the specified package, potentially recursively.
// System dependencies go to deps, non-system -- to pkgs, which could be the
// same as deps or NULL, depending on the desired semantics (see the call
- // site for details). Find available packages for deps.
+ // site for details). Find available packages for pkgs and deps and merge
+ // languages.
//
static void
collect_dependencies (const common_options& co,
packages* pkgs,
packages& deps,
+ const string& type,
+ small_vector<language, 1>& langs,
const selected_package& p,
bool recursive)
{
@@ -98,17 +139,27 @@ namespace bpkg
return p.first == d;
}) == ps->end ())
{
- available_packages aps;
- if (ps == &deps) // Note: covers the (pkgs == &deps) case.
- aps = find_available_packages (co, db, d);
-
const selected_package& p (*d);
- if (ps != nullptr)
- ps->push_back (make_pair (move (d), move (aps)));
+ if (ps != nullptr || (recursive && !sys))
+ {
+ available_packages aps (find_available_packages (co, db, d));
+
+ // Load and merge languages.
+ //
+ if (recursive && !sys)
+ {
+ const shared_ptr<available_package>& ap (aps.front ().first);
+ db.load (*ap, ap->languages_section);
+ merge_languages (type, langs, *ap);
+ }
+
+ if (ps != nullptr)
+ ps->push_back (make_pair (move (d), move (aps)));
+ }
if (recursive && !sys)
- collect_dependencies (co, pkgs, deps, p, recursive);
+ collect_dependencies (co, pkgs, deps, type, langs, p, recursive);
}
}
}
@@ -221,9 +272,11 @@ namespace bpkg
// Resolve package names to selected packages and verify they are all
// configured. While at it collect their available packages and
- // dependencies.
+ // dependencies as well as figure out type and languages.
//
packages pkgs, deps;
+ string type;
+ small_vector<language, 1> langs;
for (const package_name& n: pns)
{
@@ -239,12 +292,20 @@ namespace bpkg
if (p->substate == package_substate::system)
fail << "package " << n << " is configured as system";
- // If this is the first package, load its available package for the
- // mapping information. We don't need it for any additional packages.
+ // Load the available package for type/languages as well as the mapping
+ // information.
//
- available_packages aps;
- if (pkgs.empty ())
- aps = find_available_packages (o, db, p);
+ available_packages aps (find_available_packages (o, db, p));
+ const shared_ptr<available_package>& ap (aps.front ().first);
+ db.load (*ap, ap->languages_section);
+
+ if (pkgs.empty ()) // First.
+ {
+ type = ap->effective_type ();
+ langs = ap->effective_languages ();
+ }
+ else
+ merge_languages (type, langs, *ap);
const selected_package& r (*p);
pkgs.push_back (make_pair (move (p), move (aps)));
@@ -264,6 +325,8 @@ namespace bpkg
? *rec == recursive_mode::full ? &pkgs : nullptr
: &deps),
deps,
+ type,
+ langs,
r,
rec.has_value ());
}
@@ -301,7 +364,11 @@ namespace bpkg
// @@ TODO: pass/handle --private.
- spm->generate (pkgs, deps, vars, pm, out, rec);
+ // Note that we pass type from here in case one day we want to provide an
+ // option to specify/override it (along with languages). Note that there
+ // will probably be no way to override type for dependencies.
+ //
+ spm->generate (pkgs, deps, vars, pm, type, langs, out, rec);
// @@ TODO: change the output, maybe to something returned by spm?
//
diff --git a/bpkg/system-package-manager-debian.cxx b/bpkg/system-package-manager-debian.cxx
index 4d9c77d..2856fdf 100644
--- a/bpkg/system-package-manager-debian.cxx
+++ b/bpkg/system-package-manager-debian.cxx
@@ -1850,31 +1850,27 @@ namespace bpkg
const packages& deps,
const strings&,
const package_manifest& pm,
+ const string& pt,
+ const small_vector<language, 1>& langs,
const dir_path& out,
optional<recursive_mode>)
{
+ assert (!langs.empty ()); // Should be effective.
+
const shared_ptr<selected_package>& sp (pkgs.front ().first);
const package_name& pn (sp->name);
const version& pv (sp->version);
const available_packages& aps (pkgs.front ().second);
- const shared_ptr<available_package>& ap (aps.front ().first);
-
- bool lib (ap->effective_type () == "lib");
- struct package_lang
- {
- string name;
- bool impl; // True if implementation-only.
- };
- small_vector<package_lang, 1> langs {{"cc", false}};
+ bool lib (pt == "lib");
// For now we only know how to handle libraries with C-common interface
// languages. But we allow other implementation languages.
//
if (lib)
{
- for (const package_lang& l: langs)
+ for (const language& l: langs)
if (!l.impl && l.name != "c" && l.name != "c++" && l.name != "cc")
fail << l.name << " libraries are not yet supported";
}
@@ -1885,7 +1881,7 @@ namespace bpkg
auto lang = [&langs] (const char* n, bool intf_only = false) -> bool
{
return find_if (langs.begin (), langs.end (),
- [n, intf_only] (const package_lang& l)
+ [n, intf_only] (const language& l)
{
return (!intf_only || !l.impl) && l.name == n;
}) != langs.end ();
diff --git a/bpkg/system-package-manager-debian.hxx b/bpkg/system-package-manager-debian.hxx
index 9400a53..8398b70 100644
--- a/bpkg/system-package-manager-debian.hxx
+++ b/bpkg/system-package-manager-debian.hxx
@@ -134,6 +134,8 @@ namespace bpkg
const packages&,
const strings&,
const package_manifest&,
+ const string&,
+ const small_vector<language, 1>&,
const dir_path&,
optional<recursive_mode>) override;
diff --git a/bpkg/system-package-manager-fedora.cxx b/bpkg/system-package-manager-fedora.cxx
index 381ebfe..5a81dbf 100644
--- a/bpkg/system-package-manager-fedora.cxx
+++ b/bpkg/system-package-manager-fedora.cxx
@@ -1787,6 +1787,8 @@ namespace bpkg
const packages&,
const strings&,
const package_manifest&,
+ const string&,
+ const small_vector<language, 1>&,
const dir_path&,
optional<recursive_mode>)
{
diff --git a/bpkg/system-package-manager-fedora.hxx b/bpkg/system-package-manager-fedora.hxx
index df0e4f6..b4a2c2f 100644
--- a/bpkg/system-package-manager-fedora.hxx
+++ b/bpkg/system-package-manager-fedora.hxx
@@ -201,6 +201,8 @@ namespace bpkg
const packages&,
const strings&,
const package_manifest&,
+ const string&,
+ const small_vector<language, 1>&,
const dir_path&,
optional<recursive_mode>) override;
diff --git a/bpkg/system-package-manager.hxx b/bpkg/system-package-manager.hxx
index ad41174..29449f6 100644
--- a/bpkg/system-package-manager.hxx
+++ b/bpkg/system-package-manager.hxx
@@ -154,14 +154,20 @@ namespace bpkg
// Generate a binary distribution package. @@ TODO: doc more
//
- // The available packages are loaded for the first package in pkgs and for
- // all the packages in deps. For non-system packages there is always a
+ // The available packages are loaded for all the packages in pkgs and
+ // deps. For non-system packages (so for all in pkgs) there is always a
// single available package that corresponds to the selected package.
//
// The passed package manifest corresponds to the first package in pkgs
// (normally used as a source of additional package metadata such as
// summary, emails, urls, etc).
//
+ // The passed package type corresponds to the first package in pkgs while
+ // the languages -- to all the packages in pkgs plus, in the recursive
+ // mode, to all the non-system dependencies. In other words, the languages
+ // list contains every language that is used by anything that ends up in
+ // the package.
+ //
// See the pkg-bindist(1) man page and the pkg_bindist() function
// implementation for background and details.
//
@@ -175,6 +181,8 @@ namespace bpkg
const packages& deps,
const strings& vars,
const package_manifest&,
+ const string& type,
+ const small_vector<language, 1>&,
const dir_path& out,
optional<recursive_mode>) = 0;