diff options
author | Karen Arutyunov <karen@codesynthesis.com> | 2022-06-20 20:59:53 +0300 |
---|---|---|
committer | Karen Arutyunov <karen@codesynthesis.com> | 2022-06-23 12:35:42 +0300 |
commit | c0ca17391c41048cd1db19f0aa08e060624f4bd1 (patch) | |
tree | 4037ed4be1abf8f4b85e7e5420c3cac2d2f10503 | |
parent | 2ee693000ff6ea44cfd4fc51c7b058258056610a (diff) |
Add support for additional *-build package manifest values and alternative buildfile naming
-rw-r--r-- | bpkg/manifest-utility.cxx | 224 | ||||
-rw-r--r-- | bpkg/manifest-utility.hxx | 23 | ||||
-rw-r--r-- | bpkg/package-skeleton.cxx | 22 | ||||
-rw-r--r-- | bpkg/package.cxx | 1 | ||||
-rw-r--r-- | bpkg/package.hxx | 40 | ||||
-rw-r--r-- | bpkg/package.xml | 44 | ||||
-rw-r--r-- | bpkg/pkg-checkout.cxx | 5 | ||||
-rw-r--r-- | bpkg/pkg-unpack.cxx | 10 | ||||
-rw-r--r-- | bpkg/pkg-verify.cxx | 153 | ||||
-rw-r--r-- | bpkg/pkg-verify.hxx | 5 | ||||
-rw-r--r-- | bpkg/rep-fetch.cxx | 72 | ||||
-rw-r--r-- | bpkg/rep-fetch.hxx | 6 | ||||
-rw-r--r-- | bpkg/utility.cxx | 10 | ||||
-rw-r--r-- | bpkg/utility.hxx | 4 | ||||
-rw-r--r-- | doc/manual.cli | 49 | ||||
-rw-r--r-- | tests/common/dependency-alternatives/t11a/libbar-1.0.0.tar.gz | bin | 406 -> 465 bytes | |||
-rw-r--r-- | tests/common/dependency-alternatives/t11a/libfoo-1.0.0.tar.gz | bin | 409 -> 480 bytes | |||
-rw-r--r-- | tests/pkg-build.testscript | 10 |
18 files changed, 523 insertions, 155 deletions
diff --git a/bpkg/manifest-utility.cxx b/bpkg/manifest-utility.cxx index d205c2d..56da715 100644 --- a/bpkg/manifest-utility.cxx +++ b/bpkg/manifest-utility.cxx @@ -3,9 +3,11 @@ #include <bpkg/manifest-utility.hxx> +#include <sstream> #include <cstring> // strcspn() #include <libbutl/b.hxx> +#include <libbutl/filesystem.hxx> // dir_iterator #include <bpkg/package.hxx> // wildcard_version #include <bpkg/diagnostics.hxx> @@ -357,19 +359,73 @@ namespace bpkg } } + // Return the sorted list of *.build files (first) which are present in the + // package's build/config/ subdirectory (or their alternatives) together + // with the *-build manifest value names they correspond to (second). Skip + // files which are already present in the specified list. Note: throws + // system_error on filesystem errors. + // + static vector<pair<path, path>> + find_buildfiles (const dir_path& config, + const string& ext, + const vector<buildfile>& bs) + { + vector<pair<path, path>> r; + + for (const dir_entry& de: + dir_iterator (config, false /* ignore_dangling */)) + { + if (de.type () == entry_type::regular) + { + const path& p (de.path ()); + const char* e (p.extension_cstring ()); + + if (e != nullptr && ext == e) + { + path f (config.leaf () / p.base ()); // Relative to build/. + + if (find_if (bs.begin (), bs.end (), + [&f] (const auto& v) {return v.path == f;}) == + bs.end ()) + { + r.emplace_back (config / p, move (f)); + } + } + } + } + + sort (r.begin (), r.end (), + [] (const auto& x, const auto& y) {return x.second < y.second;}); + + return r; + } + string package_buildfiles_checksum (const optional<string>& bb, const optional<string>& rb, - const dir_path& d) + const vector<buildfile>& bs, + const dir_path& d, + optional<bool> an) { - if (bb && rb) + if (d.empty ()) { + assert (bb); + sha256 cs (*bb); - cs.append (*rb); + + if (rb) + cs.append (*rb); + + for (const buildfile& b: bs) + cs.append (b.content); + return cs.string (); } - auto checksum = [&bb, &rb] (const path& b, const path& r) + auto checksum = [&bb, &rb, &bs] (const path& b, + const path& r, + const dir_path& c, + const string& e) { sha256 cs; @@ -396,24 +452,176 @@ namespace bpkg else append_file (b); + bool root (true); + if (rb) cs.append (*rb); else if (exists (r)) append_file (r); + else + root = false; + + for (const buildfile& b: bs) + cs.append (b.content); + + if (root && exists (c)) + try + { + for (auto& f: find_buildfiles (c, e, bs)) + append_file (f.first); + } + catch (const system_error& e) + { + fail << "unable to scan directory " << c << ": " << e; + } return string (cs.string ()); }; - // Check the alternative bootstrap file first since it is more - // specific. + // Verify that the deduced naming scheme matches the specified one and + // fail if that's not the case. + // + auto verify = [an, &d] (bool alt_naming) + { + assert (an); + + if (*an != alt_naming) + fail << "buildfile naming scheme mismatch between manifest and " + << "package directory " << d; + }; + + // Check the alternative bootstrap file first since it is more specific. // path bf; if (exists (bf = d / alt_bootstrap_file)) - return checksum (bf, d / alt_root_file); + { + if (an) + verify (true /* alt_naming */); + + return checksum (bf, + d / alt_root_file, + d / alt_config_dir, + alt_build_ext); + } else if (exists (bf = d / std_bootstrap_file)) - return checksum (bf, d / std_root_file); + { + if (an) + verify (false /* alt_naming */); + + return checksum (bf, + d / std_root_file, + d / std_config_dir, + std_build_ext); + } else fail << "unable to find bootstrap.build file in package directory " << d << endf; } + + void + load_package_buildfiles (package_manifest& m, const dir_path& d, bool erp) + { + auto load_buildfiles = [&m, &d, erp] (const path& b, + const path& r, + const dir_path& c, + const string& ext) + { + auto diag_path = [&d, erp] (const path& p) + { + return !erp ? p : p.leaf (d); + }; + + auto load = [&diag_path] (const path& f) + { + try + { + ifdstream ifs (f); + string r (ifs.read_text ()); + ifs.close (); + return r; + } + catch (const io_error& e) + { + // Sanitize the exception description. + // + ostringstream os; + os << "unable to read from " << diag_path (f) << ": " << e; + throw runtime_error (os.str ()); + } + }; + + if (!m.bootstrap_build) + m.bootstrap_build = load (b); + + if (!m.root_build && exists (r)) + m.root_build = load (r); + + if (m.root_build && exists (c)) + try + { + for (auto& f: find_buildfiles (c, ext, m.buildfiles)) + m.buildfiles.emplace_back (move (f.second), load (f.first)); + } + catch (const system_error& e) + { + // Sanitize the exception description. + // + ostringstream os; + os << "unable to scan directory " << diag_path (c) << ": " << e; + throw runtime_error (os.str ()); + } + }; + + // Set the manifest's alt_naming flag to the deduced value if absent and + // verify that it matches otherwise. + // + auto alt_naming = [&m, &d, erp] (bool v) + { + if (!m.alt_naming) + { + m.alt_naming = v; + } + else if (*m.alt_naming != v) + { + string e ("buildfile naming scheme mismatch between manifest and " + "package directory"); + + if (!erp) + e += " " + d.string (); + + throw runtime_error (e); + } + }; + + // Check the alternative bootstrap file first since it is more specific. + // + path bf; + if (exists (bf = d / alt_bootstrap_file)) + { + alt_naming (true); + + load_buildfiles (bf, + d / alt_root_file, + d / alt_config_dir, + alt_build_ext); + } + else if (exists (bf = d / std_bootstrap_file)) + { + alt_naming (false); + + load_buildfiles (bf, + d / std_root_file, + d / std_config_dir, + std_build_ext); + } + else + { + string e ("unable to find bootstrap.build file in package directory"); + + if (!erp) + e += " " + d.string (); + + throw runtime_error (e); + } + } } diff --git a/bpkg/manifest-utility.hxx b/bpkg/manifest-utility.hxx index 8701b65..abb85ab 100644 --- a/bpkg/manifest-utility.hxx +++ b/bpkg/manifest-utility.hxx @@ -154,14 +154,29 @@ namespace bpkg const dir_path& src_dir, const package_info*); - // Caclulate the checksum of the buildfiles using the *-build manifest - // values, unless unspecified in which case use the files in the package - // source directory. + // Calculate the checksum of the buildfiles using the *-build manifest + // values. If the package source directory is specified (not empty), then + // use the files it contains for unspecified values. If the alt_naming flag + // is also specified for the latter case, then verify the package's + // buildfile naming scheme against its value and fail on mismatch. // string package_buildfiles_checksum (const optional<string>& bootstrap_build, const optional<string>& root_build, - const dir_path& src_dir); + const vector<buildfile>& buildfiles, + const dir_path& src_dir = {}, + optional<bool> alt_naming = nullopt); + + // Load the package's buildfiles for unspecified manifest values. Throw + // std::runtime_error for underlying errors (unable to find bootstrap.build, + // unable to read from file, etc). Optionally convert paths used in the + // potential error description to be relative to the package source + // directory. + // + void + load_package_buildfiles (package_manifest&, + const dir_path& src_dir, + bool err_path_relative = false); } #endif // BPKG_MANIFEST_UTILITY_HXX diff --git a/bpkg/package-skeleton.cxx b/bpkg/package-skeleton.cxx index d58c846..a3e0b5a 100644 --- a/bpkg/package-skeleton.cxx +++ b/bpkg/package-skeleton.cxx @@ -2501,7 +2501,10 @@ namespace bpkg // additional files. // { - path bf (skl.src_root_ / std_bootstrap_file); + bool an (*ap.alt_naming); + + path bf (skl.src_root_ / + (an ? alt_bootstrap_file : std_bootstrap_file)); mk_p (bf.directory ()); @@ -2524,7 +2527,22 @@ namespace bpkg save (*ap.bootstrap_build, bf); if (ap.root_build) - save (*ap.root_build, skl.src_root_ / std_root_file); + save (*ap.root_build, + skl.src_root_ / (an ? alt_root_file : std_root_file)); + + for (const buildfile& f: ap.buildfiles) + { + path p (skl.src_root_ / + (an ? alt_build_dir : std_build_dir) / + f.path); + + p += "."; + p += (an ? alt_build_ext : std_build_ext); + + mk_p (p.directory ()); + + save (f.content, p); + } } // Create the manifest file containing the bare minimum of values diff --git a/bpkg/package.cxx b/bpkg/package.cxx index c02bdf4..a7282c5 100644 --- a/bpkg/package.cxx +++ b/bpkg/package.cxx @@ -676,6 +676,7 @@ namespace bpkg changed = package_buildfiles_checksum ( nullopt /* bootstrap_build */, nullopt /* root_build */, + {} /* buildfiles */, d) != *p->buildfiles_checksum; } diff --git a/bpkg/package.hxx b/bpkg/package.hxx index dc5031c..694d068 100644 --- a/bpkg/package.hxx +++ b/bpkg/package.hxx @@ -27,7 +27,7 @@ // #define DB_SCHEMA_VERSION_BASE 7 -#pragma db model version(DB_SCHEMA_VERSION_BASE, 19, closed) +#pragma db model version(DB_SCHEMA_VERSION_BASE, 20, closed) namespace bpkg { @@ -653,6 +653,10 @@ namespace bpkg available_package_id (package_name, const bpkg::version&); }; + // buildfile + // + #pragma db value(buildfile) definition + #pragma db object pointer(shared_ptr) session class available_package { @@ -690,12 +694,14 @@ namespace bpkg small_vector<test_dependency, 1> tests; // Note that while the bootstrap buildfile is always present for stub - // packages, we don't save bootstrap/root buildfiles for stubs of any kind - // (can come from repository, be based on system selected package, etc), - // leaving *_build as nullopt. + // packages, we don't save buildfiles for stubs of any kind (can come from + // repository, be based on system selected package, etc), leaving *_build + // as nullopt and buildfiles empty. // - optional<string> bootstrap_build; - optional<string> root_build; + optional<bool> alt_naming; + optional<string> bootstrap_build; + optional<string> root_build; + vector<buildfile> buildfiles; // Present for non-transient objects only (and only for certain repository // types). @@ -719,10 +725,12 @@ namespace bpkg { if (!stub ()) { - assert (m.bootstrap_build.has_value ()); + assert (m.bootstrap_build.has_value () && m.alt_naming.has_value ()); + alt_naming = m.alt_naming; bootstrap_build = move (m.bootstrap_build); root_build = move (m.root_build); + buildfiles = move (m.buildfiles); } } @@ -813,6 +821,20 @@ namespace bpkg // #pragma db member(tests) id_column("") value_column("test_") + // alt_naming + // + // @@ TMP Drop when database migration to the schema version 20 is no + // longer supported. + // + // Note that since no real packages with alternative buildfile naming + // use conditional dependencies yet, we can just set alt_naming to + // false during migration to the database schema version 20. Also we + // never rely on alt_naming to be nullopt for the stub packages, so + // let's not complicate things and set alt_naming to false for them + // either. + // + #pragma db member(alt_naming) default(false) + // *_build // // @@ TMP Drop when database migration to the schema version 15 is no @@ -827,6 +849,10 @@ namespace bpkg // #pragma db member(bootstrap_build) default("") + // buildfiles + // + #pragma db member(buildfiles) id_column("") value_column("") + private: friend class odb::access; available_package () = default; diff --git a/bpkg/package.xml b/bpkg/package.xml index 8959529..3fa1bc0 100644 --- a/bpkg/package.xml +++ b/bpkg/package.xml @@ -1,4 +1,48 @@ <changelog xmlns="http://www.codesynthesis.com/xmlns/odb/changelog" database="sqlite" version="1"> + <changeset version="20"> + <alter-table name="main.available_package"> + <add-column name="alt_naming" type="INTEGER" null="true" default="0"/> + </alter-table> + <add-table name="main.available_package_buildfiles" kind="container"> + <column name="name" type="TEXT" null="true" options="COLLATE NOCASE"/> + <column name="version_epoch" type="INTEGER" null="true"/> + <column name="version_canonical_upstream" type="TEXT" null="true"/> + <column name="version_canonical_release" type="TEXT" null="true" options="COLLATE BINARY"/> + <column name="version_revision" type="INTEGER" null="true"/> + <column name="version_iteration" type="INTEGER" null="true"/> + <column name="index" type="INTEGER" null="true"/> + <column name="path" type="TEXT" null="true"/> + <column name="content" type="TEXT" null="true"/> + <foreign-key name="object_id_fk" on-delete="CASCADE"> + <column name="name"/> + <column name="version_epoch"/> + <column name="version_canonical_upstream"/> + <column name="version_canonical_release"/> + <column name="version_revision"/> + <column name="version_iteration"/> + <references table="main.available_package"> + <column name="name"/> + <column name="version_epoch"/> + <column name="version_canonical_upstream"/> + <column name="version_canonical_release"/> + <column name="version_revision"/> + <column name="version_iteration"/> + </references> + </foreign-key> + <index name="available_package_buildfiles_object_id_i"> + <column name="name"/> + <column name="version_epoch"/> + <column name="version_canonical_upstream"/> + <column name="version_canonical_release"/> + <column name="version_revision"/> + <column name="version_iteration"/> + </index> + <index name="available_package_buildfiles_index_i"> + <column name="index"/> + </index> + </add-table> + </changeset> + <changeset version="19"> <alter-table name="main.selected_package_prerequisites"> <add-column name="config_dependency_index" type="INTEGER" null="true" default="0"/> diff --git a/bpkg/pkg-checkout.cxx b/bpkg/pkg-checkout.cxx index 6c6dcf8..2a3f508 100644 --- a/bpkg/pkg-checkout.cxx +++ b/bpkg/pkg-checkout.cxx @@ -319,12 +319,15 @@ namespace bpkg // Calculate the buildfiles checksum if the package has any buildfile // clauses in the dependencies. // + // Note that the available package already has all the buildfiles + // loaded. + // if ((p != nullptr && p->manifest_checksum == mc) ? p->buildfiles_checksum.has_value () : has_buildfile_clause (ap->dependencies)) bc = package_buildfiles_checksum (ap->bootstrap_build, ap->root_build, - d); + ap->buildfiles); } if (p != nullptr) diff --git a/bpkg/pkg-unpack.cxx b/bpkg/pkg-unpack.cxx index b38a750..2e21c70 100644 --- a/bpkg/pkg-unpack.cxx +++ b/bpkg/pkg-unpack.cxx @@ -175,6 +175,7 @@ namespace bpkg : has_buildfile_clause (deps)) bc = package_buildfiles_checksum (nullopt /* bootstrap_build */, nullopt /* root_build */, + {} /* buildfiles */, d); } @@ -414,10 +415,13 @@ namespace bpkg if (ap != nullptr) { + // Note that the available package already has all the buildfiles + // loaded. + // if (has_buildfile_clause (ap->dependencies)) bc = package_buildfiles_checksum (ap->bootstrap_build, ap->root_build, - d); + ap->buildfiles); } else { @@ -435,7 +439,9 @@ namespace bpkg if (has_buildfile_clause (m.dependencies)) bc = package_buildfiles_checksum (m.bootstrap_build, m.root_build, - d); + m.buildfiles, + d, + m.alt_naming); } } diff --git a/bpkg/pkg-verify.cxx b/bpkg/pkg-verify.cxx index b0dbf65..229b73d 100644 --- a/bpkg/pkg-verify.cxx +++ b/bpkg/pkg-verify.cxx @@ -226,12 +226,13 @@ namespace bpkg iu); } - // Extract the bootstrap/root buildfiles into the respective *-build - // values, if requested and are not already specified in the manifest. + // Extract the bootstrap, root, and config/*.build buildfiles into the + // respective *-build values, if requested and are not already + // specified in the manifest. // // Note that we don't verify that the files are not empty. // - if (lb && (!m.bootstrap_build || !m.root_build)) + if (lb) { paths ps (archive_contents (co, af, diag_level != 0)); @@ -240,14 +241,80 @@ namespace bpkg return find (ps.begin (), ps.end (), p) != ps.end (); }; - auto extract_buildfiles = [&m, &co, &af, diag_level, &contains] - (const path& b, const path& r) + auto extract_buildfiles = [&m, &co, &af, &ps, diag_level, &contains] + (const path& b, + const path& r, + const dir_path& c, + const string& ext) { if (!m.bootstrap_build) m.bootstrap_build = extract (co, af, b, diag_level != 0); if (!m.root_build && contains (r)) m.root_build = extract (co, af, r, diag_level != 0); + + // Extract build/config/*.build files. + // + if (m.root_build) + { + vector<buildfile>& bs (m.buildfiles); + size_t n (bs.size ()); + + for (const path& ap: ps) + { + if (!ap.to_directory () && ap.sub (c)) + { + path p (ap.leaf (c)); + const char* e (p.extension_cstring ()); + + // Only consider immediate sub-entries of the config/ + // subdirectory. + // + if (e != nullptr && ext == e && p.simple ()) + { + path f (c.leaf () / p.base ()); // Relative to build/. + + if (find_if (bs.begin (), bs.end (), + [&f] (const auto& v) {return v.path == f;}) == + bs.end ()) + { + bs.emplace_back (move (f), + extract (co, af, ap, diag_level != 0)); + } + } + } + } + + // To produce a stable result sort the appended *-build values. + // + if (bs.size () != n) + { + sort (bs.begin () + n, bs.end (), + [] (const auto& x, const auto& y) + { + return x.path < y.path; + }); + } + } + }; + + // Set the manifest's alt_naming flag to the deduced value if absent + // and verify that it matches otherwise. + // + auto alt_naming = [&m, diag_level, &af] (bool v) + { + if (!m.alt_naming) + { + m.alt_naming = v; + } + else if (*m.alt_naming != v) + { + if (diag_level != 0) + error << "buildfile naming scheme mismatch between manifest " + << "and package archive " << af; + + throw failed (); + } }; // Check the alternative bootstrap file first since it is more @@ -256,11 +323,21 @@ namespace bpkg path bf; if (contains (bf = pd / alt_bootstrap_file)) { - extract_buildfiles (bf, pd / alt_root_file); + alt_naming (true); + + extract_buildfiles (bf, + pd / alt_root_file, + pd / alt_config_dir, + alt_build_ext); } else if (contains (bf = pd / std_bootstrap_file)) { - extract_buildfiles (bf, pd / std_root_file); + alt_naming (false); + + extract_buildfiles (bf, + pd / std_root_file, + pd / std_config_dir, + std_build_ext); } else { @@ -354,61 +431,23 @@ namespace bpkg tf, iu); - // Load the bootstrap/root buildfiles into the respective *-build - // values, if requested and if they are not already specified in the - // manifest. + // Load the bootstrap, root, and config/*.build buildfiles into the + // respective *-build values, if requested and if they are not already + // specified in the manifest. // // Note that we don't verify that the files are not empty. // - if (lb && (!m.bootstrap_build || !m.root_build)) + if (lb) + try { - auto load_buildfiles = [&m, diag_level] (const path& b, const path& r) - { - auto load = [diag_level] (const path& f) - { - try - { - ifdstream ifs (f); - string r (ifs.read_text ()); - ifs.close (); - return r; - } - catch (const io_error& e) - { - if (diag_level != 0) - error << "unable to read from " << f << ": " << e; - - throw failed (); - } - }; - - if (!m.bootstrap_build) - m.bootstrap_build = load (b); - - if (!m.root_build && exists (r)) - m.root_build = load (r); - }; - - // Check the alternative bootstrap file first since it is more - // specific. - // - path bf; - if (exists (bf = d / alt_bootstrap_file)) - { - load_buildfiles (bf, d / alt_root_file); - } - else if (exists (bf = d / std_bootstrap_file)) - { - load_buildfiles (bf, d / std_root_file); - } - else - { - if (diag_level != 0) - error << "unable to find bootstrap.build file in package " - << "directory " << d; + load_package_buildfiles (m, d); + } + catch (const runtime_error& e) + { + if (diag_level != 0) + error << e; - throw failed (); - } + throw failed (); } // We used to verify package directory is <name>-<version> but it is diff --git a/bpkg/pkg-verify.hxx b/bpkg/pkg-verify.hxx index 8c0b555..b4b536b 100644 --- a/bpkg/pkg-verify.hxx +++ b/bpkg/pkg-verify.hxx @@ -22,8 +22,9 @@ namespace bpkg // expand the file-referencing manifest values (description, changes, etc), // setting them to the contents of files they refer to, set the potentially // absent description-type value to the effective description type (see - // libbpkg/manifest.hxx), load the bootstrap and root buildfiles into the - // respective *-build values, and complete the dependency constraints. + // libbpkg/manifest.hxx), load the bootstrap, root, and config/*.build + // buildfiles into the respective *-build values, and complete the + // dependency constraints. // // Throw not_package (derived from failed) if this doesn't look like a // package. Throw plain failed if this does looks like a package but diff --git a/bpkg/rep-fetch.cxx b/bpkg/rep-fetch.cxx index e9cacd0..038d54e 100644 --- a/bpkg/rep-fetch.cxx +++ b/bpkg/rep-fetch.cxx @@ -323,67 +323,21 @@ namespace bpkg // m.location = move (*pm.location); - // Load the bootstrap/root buildfiles into the respective *-build - // values, if requested and if they are not already specified in the - // manifest. + // Load the bootstrap, root, and config/*.build buildfiles into the + // respective *-build values, if requested and if they are not already + // specified in the manifest. // - if (lb && (!m.bootstrap_build || !m.root_build)) + if (lb) + try { - const dir_path& d (pds[i]); - - // Note that the paths relative to the package directory (last two - // arguments) are used for diagnostics only. - // - auto load_buildfiles = [&m, &add_package_info] (const path& bf, - const path& rf, - const path& bfr, - const path& rfr) - { - auto load = [&m, &add_package_info] (const path& f, const path& fr) - { - try - { - ifdstream ifs (f); - string r (ifs.read_text ()); - ifs.close (); - return r; - } - catch (const io_error& e) - { - diag_record dr (fail); - dr << "unable to read from " << fr << ": " << e; - add_package_info (m, dr); - dr << endf; - } - }; - - if (!m.bootstrap_build) - m.bootstrap_build = load (bf, bfr); - - if (!m.root_build && exists (rf)) - m.root_build = load (rf, rfr); - }; - - // Check the alternative bootstrap file first since it is more - // specific. - // - path bf; - if (exists (bf = d / alt_bootstrap_file)) - { - load_buildfiles (bf, d / alt_root_file, - alt_bootstrap_file, alt_root_file); - } - else if (exists (bf = d / std_bootstrap_file)) - { - load_buildfiles (bf, d / std_root_file, - std_bootstrap_file, std_root_file); - } - else - { - diag_record dr (fail); - dr << "unable to find bootstrap.build file"; - add_package_info (m, dr); - } + load_package_buildfiles (m, pds[i], true /* err_path_relative */); + } + catch (const runtime_error& e) + { + diag_record dr (fail); + dr << e << info; + add_package_info (m, dr); + dr << endf; } pm = move (m); diff --git a/bpkg/rep-fetch.hxx b/bpkg/rep-fetch.hxx index b9d458f..7e03999 100644 --- a/bpkg/rep-fetch.hxx +++ b/bpkg/rep-fetch.hxx @@ -54,9 +54,9 @@ namespace bpkg // (description, changes, etc), setting them to the contents of files they // refer to and set the potentially absent description-type value to the // effective description type (see libbpkg/manifest.hxx) and load the - // bootstrap and root buildfiles into the respective *-build values. Note - // that for pkg repositories such values are expanded/loaded at the - // repository creation time. + // bootstrap, root, and config/*.build buildfiles into the respective *-build + // values. Note that for pkg repositories such values are expanded/loaded at + // the repository creation time. // rep_fetch_data rep_fetch (const common_options&, diff --git a/bpkg/utility.cxx b/bpkg/utility.cxx index d229205..68d79ad 100644 --- a/bpkg/utility.cxx +++ b/bpkg/utility.cxx @@ -26,13 +26,23 @@ namespace bpkg const dir_path certs_dir (dir_path (bpkg_dir) /= "certs"); const dir_path repos_dir (dir_path (bpkg_dir) /= "repos"); + // Standard and alternative build file/directory naming schemes. + // + // build: + // const dir_path std_build_dir ("build"); + const dir_path std_config_dir (dir_path (std_build_dir) /= "config"); const path std_bootstrap_file (dir_path (std_build_dir) /= "bootstrap.build"); const path std_root_file (dir_path (std_build_dir) /= "root.build"); + const string std_build_ext ("build"); + // build2: + // const dir_path alt_build_dir ("build2"); + const dir_path alt_config_dir (dir_path (alt_build_dir) /= "config"); const path alt_bootstrap_file (dir_path (alt_build_dir) /= "bootstrap.build2"); const path alt_root_file (dir_path (alt_build_dir) /= "root.build2"); + const string alt_build_ext ("build2"); const dir_path current_dir ("."); diff --git a/bpkg/utility.hxx b/bpkg/utility.hxx index 597800c..342d608 100644 --- a/bpkg/utility.hxx +++ b/bpkg/utility.hxx @@ -86,12 +86,16 @@ namespace bpkg extern const dir_path repos_dir; // .bpkg/repos/ extern const dir_path std_build_dir; // build/ + extern const dir_path std_config_dir; // build/config/ extern const path std_bootstrap_file; // build/bootstrap.build extern const path std_root_file; // build/root.build + extern const string std_build_ext; // build extern const dir_path alt_build_dir; // build2/ + extern const dir_path alt_config_dir; // build2/config/ extern const path alt_bootstrap_file; // build2/bootstrap.build2 extern const path alt_root_file; // build2/root.build2 + extern const string alt_build_ext; // build2 extern const dir_path current_dir; // ./ diff --git a/doc/manual.cli b/doc/manual.cli index b00430a..ec0a535 100644 --- a/doc/manual.cli +++ b/doc/manual.cli @@ -623,6 +623,11 @@ license: <licenses> [; <comment>] [bootstrap-build]: <text> [root-build]: <text> +[*-build]: <text> + +[bootstrap-build2]: <text> +[root-build2]: <text> +[*-build2]: <text> \ \h2#manifest-package-name|\c{name}| @@ -1437,17 +1442,51 @@ Note that the comment of the matching exclusion is used by the web interface (\c{brep}) to display the reason for the build configuration exclusion. -\h2#manifest-package-bootstrap-root-build|\c{{bootstrap,root\}-build}| +\h2#manifest-package-x-build|\c{{bootstrap,root,*\}-build[2]}| \ [bootstrap-build]: <text> [root-build]: <text> +[*-build]: <text> + +[bootstrap-build2]: <text> +[root-build2]: <text> +[*-build2]: <text> +\ + +The contents of the mandatory \c{bootstrap.build} file, optional +\c{root.build} file, and additional files included by \c{root.build}, or their +alternative naming scheme variants (\c{bootstrap.build2}, etc). Packages with +the alternative naming scheme should use the \c{*-build2} values instead of +\c{*-build}. + +These files must reside in the package's \c{build/} subdirectory and have the +\c{.build} extension (or their alternative names). The respective manifest +value name prefix must be the file path relative to this subdirectory with the +extension stripped. + +As an example, the following value corresponds to the +\c{build/config/common.build} file: + +\ +config/common-build:\ +config [bool] config.libhello.fancy ?= false +\\ +\ + +And the following value corresponds to the \c{build2/config/common.build2} +file in a package with the alternative naming scheme: + +\ +config/common-build2:\ +config [bool] config.libhello.fancy ?= false +\\ \ -The contents of the mandatory \c{bootstrap.build} and optional \c{root.build} -files in the package's \c{build/} (or their alternative names) subdirectory. -If unspecified, then they will be automatically added, for example, when the -\l{#manifest-package-list-pkg package list manifest} is created. +If unspecified, then the package's \c{bootstrap.build}, \c{root.build}, and +\c{build/config/*.build} files (or their alternative names) will be +automatically added, for example, when the \l{#manifest-package-list-pkg +package list manifest} is created. \h#manifest-package-list-pkg|Package List Manifest for \cb{pkg} Repositories| diff --git a/tests/common/dependency-alternatives/t11a/libbar-1.0.0.tar.gz b/tests/common/dependency-alternatives/t11a/libbar-1.0.0.tar.gz Binary files differindex 7c5a840..aacf8d7 100644 --- a/tests/common/dependency-alternatives/t11a/libbar-1.0.0.tar.gz +++ b/tests/common/dependency-alternatives/t11a/libbar-1.0.0.tar.gz diff --git a/tests/common/dependency-alternatives/t11a/libfoo-1.0.0.tar.gz b/tests/common/dependency-alternatives/t11a/libfoo-1.0.0.tar.gz Binary files differindex 52ba91b..da545c1 100644 --- a/tests/common/dependency-alternatives/t11a/libfoo-1.0.0.tar.gz +++ b/tests/common/dependency-alternatives/t11a/libfoo-1.0.0.tar.gz diff --git a/tests/pkg-build.testscript b/tests/pkg-build.testscript index 86a63f1..bf39949 100644 --- a/tests/pkg-build.testscript +++ b/tests/pkg-build.testscript @@ -4932,7 +4932,7 @@ test.options += --no-progress } } - : configuration-negotiation-order + : config-negotiation-order : { +$clone_root_cfg && $rep_add $rep/t11a && $rep_fetch @@ -5520,7 +5520,7 @@ test.options += --no-progress $pkg_drop foo libfoo } - : dependent-single-position + : dependent-single-pos : { +$clone_cfg @@ -5831,7 +5831,7 @@ test.options += --no-progress } } - : dependent-multiple-positions + : dependent-mult-pos : { +$clone_cfg @@ -6151,7 +6151,7 @@ test.options += --no-progress $pkg_drop tex baz } - : replace-re-evaluation + : replace-reeval : { +$clone_cfg @@ -11272,7 +11272,7 @@ test.options += --no-progress } } - : configuration-negotiation + : config-negotiation : { test.arguments += --yes --plan 'build plan:' |