From 1c28876c1357d332951b27a1db09a5fc37f7abea Mon Sep 17 00:00:00 2001 From: Karen Arutyunov Date: Tue, 6 Dec 2022 20:57:09 +0300 Subject: Add support for *-build-config override --- libbpkg/manifest.cxx | 95 +++++++++++++++++++++++++++++----------------- libbpkg/manifest.hxx | 9 +++++ tests/overrides/driver.cxx | 2 +- tests/overrides/testscript | 43 ++++++++++++++++++++- 4 files changed, 111 insertions(+), 38 deletions(-) diff --git a/libbpkg/manifest.cxx b/libbpkg/manifest.cxx index b5a654c..03aef34 100644 --- a/libbpkg/manifest.cxx +++ b/libbpkg/manifest.cxx @@ -4497,17 +4497,53 @@ namespace bpkg } }; - // Return the reference to the package build configuration matching the - // build config-specific builds group value override, if exists. If no - // configuration matches, then throw manifest_parsing, except for the - // validate-only mode in which case just add an empty configuration with - // this name and return the reference to it. + // Return the reference to the package build configuration which matches + // the build config value override, if exists. If no configuration + // matches, then create one, if requested, and throw manifest_parsing + // otherwise. // // The n argument specifies the length of the configuration name in - // {*-builds, *-build-{include,exclude}} values. + // *-build-config, *-builds, and *-build-{include,exclude} values. + // + auto build_conf = + [&nv, &bad_name, &m] (size_t n, bool create) -> build_package_config& + { + const string& nm (nv.name); + small_vector& cs (m.build_configs); + + // Find the build package configuration. If no configuration is found, + // then create one, if requested, and throw otherwise. + // + auto i (find_if (cs.begin (), cs.end (), + [&nm, n] (const build_package_config& c) + {return nm.compare (0, n, c.name) == 0;})); + + if (i == cs.end ()) + { + string cn (nm, 0, n); + + if (create) + { + cs.emplace_back (move (cn)); + return cs.back (); + } + else + bad_name ("cannot override '" + nm + "' value: no build " + + "package configuration '" + cn + '\''); + } + + return *i; + }; + + // Return the reference to the package build configuration which matches + // the build config-specific builds group value override, if exists. If + // no configuration matches, then throw manifest_parsing, except for the + // validate-only mode in which case just add an empty configuration with + // this name and return the reference to it. // - auto build_conf = [&pbc, &cbc, &nv, &obcs, &bad_name, &m, validate_only] - (size_t n) -> build_package_config& + auto build_conf_constr = + [&pbc, &cbc, &nv, &obcs, &bad_name, &build_conf, &m, validate_only] + (size_t n) -> build_package_config& { const string& nm (nv.name); @@ -4533,30 +4569,8 @@ namespace bpkg // Note that we are using indexes rather then configuration addresses // due to potential reallocations. // - size_t ci (0); // Silence Clang's 'uninitialized use' warning. - { - auto i (find_if (cs.begin (), cs.end (), - [&nm, n] (const build_package_config& c) - {return nm.compare (0, n, c.name) == 0;})); - - if (i == cs.end ()) - { - string cn (nm, 0, n); - - if (validate_only) - { - ci = cs.size (); - cs.emplace_back (move (cn)); - } - else - bad_name ("cannot override '" + nm + "' value: no build " + - "package configuration '" + cn + '\''); - } - else - ci = i - cs.begin (); - } - - build_package_config& r (cs[ci]); + build_package_config& r (build_conf (n, validate_only)); + size_t ci (&r - cs.data ()); bool bv (nm.compare (n, nm.size () - n, "-builds") == 0); // If this is the first encountered @@ -4626,9 +4640,20 @@ namespace bpkg m.build_constraints.push_back ( parse_build_constraint (nv, true /* exclusion */, name)); } + else if ((n.size () > 13 && + n.compare (n.size () - 13, 13, "-build-config") == 0)) + { + build_package_config& bc ( + build_conf (n.size () - 13, true /* create */)); + + auto vc (parser::split_comment (nv.value)); + + bc.arguments = move (vc.first); + bc.comment = move (vc.second); + } else if (n.size () > 7 && n.compare (n.size () - 7, 7, "-builds") == 0) { - build_package_config& bc (build_conf (n.size () - 7)); + build_package_config& bc (build_conf_constr (n.size () - 7)); bc.builds.push_back ( parse_build_class_expr (nv, bc.builds.empty (), name)); @@ -4636,7 +4661,7 @@ namespace bpkg else if (n.size () > 14 && n.compare (n.size () - 14, 14, "-build-include") == 0) { - build_package_config& bc (build_conf (n.size () - 14)); + build_package_config& bc (build_conf_constr (n.size () - 14)); bc.constraints.push_back ( parse_build_constraint (nv, false /* exclusion */, name)); @@ -4644,7 +4669,7 @@ namespace bpkg else if (n.size () > 14 && n.compare (n.size () - 14, 14, "-build-exclude") == 0) { - build_package_config& bc (build_conf (n.size () - 14)); + build_package_config& bc (build_conf_constr (n.size () - 14)); bc.constraints.push_back ( parse_build_constraint (nv, true /* exclusion */, name)); diff --git a/libbpkg/manifest.hxx b/libbpkg/manifest.hxx index 3b75830..35bf915 100644 --- a/libbpkg/manifest.hxx +++ b/libbpkg/manifest.hxx @@ -1292,6 +1292,15 @@ namespace bpkg // {build-*email} // {builds, build-{include,exclude}} // {*-builds, *-build-{include,exclude}} + // {*-build-config} + // + // Throw manifest_parsing if the configuration specified by the build + // package configuration-specific build constraints group value overrides + // doesn't exists. In contrast, for the build config override add a new + // configuration if it doesn't exist and update the arguments of the + // existing configuration otherwise. In the former case, all the potential + // build constraints overrides for such a newly added configuration must + // follow the respective *-build-config override. // // Note that the build constraints group values (both common and build // config-specific) are overridden hierarchically so that the diff --git a/tests/overrides/driver.cxx b/tests/overrides/driver.cxx index 62ac7f8..c4a09ef 100644 --- a/tests/overrides/driver.cxx +++ b/tests/overrides/driver.cxx @@ -86,7 +86,7 @@ main (int argc, char* argv[]) { package_manifest::validate_overrides (overrides, name); } - catch (const manifest_parsing& e) + catch (const manifest_parsing&) { assert (false); // Validation must never fail if override succeeds. } diff --git a/tests/overrides/testscript b/tests/overrides/testscript index 95a5593..07c1451 100644 --- a/tests/overrides/testscript +++ b/tests/overrides/testscript @@ -100,6 +100,9 @@ : $* 'network-builds: all' 'network-build-include: windows*' 'network-build-exclude: *' \ 'cache-build-include: freebsd*' 'cache-build-exclude: *' 'cache-builds: legacy' \ + 'cache-build-config: config.libfoo.cache=true config.libfoo.buffer=1028' \ + 'deprecated-api-build-config: config.libfoo.deprecated_api=true' 'deprecated-api-builds: windows' \ + 'experimental-api-build-config: config.libfoo.experimental_api=true' \ 'sys-build-include: linux*' 'sys-build-exclude: *' \ 'fancy-builds: gcc' <>EOO : 1 @@ -148,7 +151,7 @@ network-builds: all network-build-include: windows* network-build-exclude: * - cache-build-config: config.libfoo.cache=true + cache-build-config: config.libfoo.cache=true config.libfoo.buffer=1028 cache-builds: legacy cache-build-include: freebsd* cache-build-exclude: * @@ -160,9 +163,12 @@ older-builds: none fancy-build-config: config.libfoo.fancy=true fancy-builds: gcc + deprecated-api-build-config: config.libfoo.deprecated_api=true + deprecated-api-builds: windows + experimental-api-build-config: config.libfoo.experimental_api=true + experimental-api-builds: none EOO - : build-config-default : $* 'default-builds: all' 'default-build-include: windows*' 'default-build-exclude: *' <>EOO @@ -186,6 +192,27 @@ network-builds: none EOO + : add-build-config + : + $* 'experimental-api-build-config: config.libfoo.experimental_api=true' <>EOO + : 1 + name: libfoo + version: 2.0.0 + summary: Modern C++ parser + license: LGPLv2 + network-build-config: config.libfoo.network=true + network-builds: all + EOI + : 1 + name: libfoo + version: 2.0.0 + summary: Modern C++ parser + license: LGPLv2 + network-build-config: config.libfoo.network=true + network-builds: all + experimental-api-build-config: config.libfoo.experimental_api=true + EOO + : none : $* <>EOO @@ -306,4 +333,16 @@ EOI 'build-exclude' override specified together with 'network-builds' override EOE + + : build-config-after-config-builds + : + $* 'deprecated-api-builds: windows' 'deprecated-api-build-config: config.libfoo.deprecated-api=true' <>EOE != 0 + : 1 + name: libfoo + version: 2.0.0 + summary: Modern C++ parser + license: LGPLv2 + EOI + cannot override 'deprecated-api-builds' value: no build package configuration 'deprecated-api' + EOE } -- cgit v1.1