Skip to content

Commit 9c61fcc

Browse files
committed
feat: backend= dep knob, [runtime.<cap>] provider= override, [package] platforms
- dep spec backend = "<impl>" — sugar for requesting the dependency's backend-<impl> feature (library backend selection knob; verified the dep compiles with -DMCPP_FEATURE_BACKEND_<IMPL>). - [runtime.<capability>] provider = "<pkg>" — explicit provider selection: prefers the named provider for matching capabilities (surfaced by why/ doctor/resolution.json), warns when the provider isn't in the graph. - [package] platforms = [...] — declared platform support, surfaced by mcpp why as the CI matrix hint.
1 parent acf2d5c commit 9c61fcc

2 files changed

Lines changed: 48 additions & 1 deletion

File tree

src/cli.cppm

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3211,6 +3211,25 @@ prepare_build(bool print_fingerprint,
32113211
}
32123212
}
32133213

3214+
// Apply [runtime.<capability>] provider = "<pkg>" overrides: prefer the
3215+
// named provider for matching capabilities (capability name prefix match).
3216+
// Warn if the named provider isn't in the dependency graph.
3217+
for (auto& [capKey, prov] : ctx.manifest.runtimeConfig.providerOverrides) {
3218+
bool found = false;
3219+
std::stable_partition(ctx.plan.runtimeProviders.begin(),
3220+
ctx.plan.runtimeProviders.end(),
3221+
[&](const std::pair<std::string, std::string>& pr) {
3222+
bool match = pr.first.rfind(capKey, 0) == 0 && pr.second == prov;
3223+
found = found || match;
3224+
return match;
3225+
});
3226+
if (!found) {
3227+
std::println(stderr,
3228+
"warning: [runtime.{}] provider = \"{}\" — no such provider in the "
3229+
"dependency graph for that capability", capKey, prov);
3230+
}
3231+
}
3232+
32143233
// Capability-driven ABI enforcement: if any dependency declares an
32153234
// `abi:<x>` capability, the resolved toolchain must satisfy it. (Toolchain
32163235
// is resolved before the dep graph, so this enforces/diagnoses rather than
@@ -4484,6 +4503,14 @@ int cmd_why(const mcpplibs::cmdline::ParsedArgs& parsed) {
44844503
std::println("toolchain: {}", tc.label());
44854504
std::println(" abi={} stdlib={} triple={}", abi_of(tc), tc.stdlibId, tc.targetTriple);
44864505
std::println(" reason: [toolchain] in mcpp.toml if set, else platform-native default");
4506+
if (!ctx->manifest.package.platforms.empty()) {
4507+
std::string ps;
4508+
for (auto& p : ctx->manifest.package.platforms) {
4509+
if (!ps.empty()) ps += ", ";
4510+
ps += p;
4511+
}
4512+
std::println(" declared platforms: {} (CI matrix hint)", ps);
4513+
}
44874514
}
44884515
if (all || topic == "runtime") {
44894516
std::println("runtime library dirs (baked into binary RUNPATH):");

src/manifest.cppm

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ struct Package {
3737
std::string license;
3838
std::vector<std::string> authors;
3939
std::string repo;
40+
std::vector<std::string> platforms; // declared supported platforms (CI matrix hint)
4041
};
4142

4243
struct Language {
@@ -115,6 +116,9 @@ struct RuntimeConfig {
115116
std::vector<std::filesystem::path> libraryDirs; // relative to package root
116117
std::vector<std::string> dlopenLibs; // runtime-loaded sonames
117118
std::vector<std::string> capabilities; // host/system capabilities
119+
// [runtime.<capability>] provider = "<pkg>" — explicit provider selection
120+
// (the three-tier knob: default/auto → explicit override).
121+
std::map<std::string, std::string> providerOverrides;
118122
};
119123

120124
// `[target.<triple>]` — per-target overrides.
@@ -437,6 +441,7 @@ std::expected<Manifest, ManifestError> parse_string(std::string_view content,
437441
if (auto v = doc->get_string("package.license")) m.package.license = *v;
438442
if (auto v = doc->get_string("package.repo")) m.package.repo = *v;
439443
if (auto v = doc->get_string_array("package.authors")) m.package.authors = *v;
444+
if (auto v = doc->get_string_array("package.platforms")) m.package.platforms = *v;
440445

441446
// [package].standard (M5.0 new home)
442447
if (auto v = doc->get_string("package.standard")) m.package.standard = *v;
@@ -588,7 +593,8 @@ std::expected<Manifest, ManifestError> parse_string(std::string_view content,
588593
auto is_dep_spec_key = [](std::string_view k) {
589594
return k == "path" || k == "version" || k == "git"
590595
|| k == "rev" || k == "tag" || k == "branch"
591-
|| k == "features" || k == "workspace" || k == "visibility";
596+
|| k == "features" || k == "workspace" || k == "visibility"
597+
|| k == "backend";
592598
};
593599
auto looks_like_inline_dep_spec = [&](const t::Table& sub) {
594600
if (sub.empty()) return false;
@@ -620,6 +626,11 @@ std::expected<Manifest, ManifestError> parse_string(std::string_view content,
620626
for (auto& fv : it->second.as_array())
621627
if (fv.is_string()) spec.features.push_back(fv.as_string());
622628
}
629+
// `backend = "<impl>"` — sugar for requesting the dependency's
630+
// `backend-<impl>` feature (library-level backend selection knob).
631+
if (auto it = sub.find("backend"); it != sub.end() && it->second.is_string()) {
632+
spec.features.push_back("backend-" + it->second.as_string());
633+
}
623634
if (auto it = sub.find("rev"); it != sub.end() && it->second.is_string()) {
624635
spec.gitRev = it->second.as_string();
625636
spec.gitRefKind = "rev";
@@ -877,6 +888,15 @@ std::expected<Manifest, ManifestError> parse_string(std::string_view content,
877888
m.runtimeConfig.dlopenLibs = *v;
878889
if (auto v = doc->get_string_array("runtime.capabilities"))
879890
m.runtimeConfig.capabilities = *v;
891+
// [runtime.<capability>] provider = "<pkg>" — explicit provider override.
892+
if (auto* rt = doc->get_table("runtime"); rt && !rt->empty()) {
893+
for (auto& [rk, rv] : *rt) {
894+
if (!rv.is_table()) continue; // flat keys handled above
895+
auto& tt = rv.as_table();
896+
if (auto it = tt.find("provider"); it != tt.end() && it->second.is_string())
897+
m.runtimeConfig.providerOverrides[rk] = it->second.as_string();
898+
}
899+
}
880900

881901
// [lib] — library root convention (cargo-style).
882902
if (auto v = doc->get_string("lib.path")) {

0 commit comments

Comments
 (0)