Skip to content

Commit ba5f1a6

Browse files
committed
fix(pm): de-inline resolver functions to satisfy musl-gcc 15.1 link
The release.yml musl-static build of v0.0.2 failed at the link step: obj/cli.m.o: in function `std::_Vector_base<mcpp::version_req::Version>::~_Vector_base()': undefined reference to `std::_Vector_base<...>::_Vector_impl::~_Vector_impl()' `pm/resolver.cppm` declared `resolve_semver` `inline`, so every importer (currently `cli.cppm`) wound up locally instantiating the destructor of `std::_Vector_base<vr::Version>`. With musl-gcc 15.1's libstdc++ that specific instantiation is missing the corresponding `_Vector_impl` destructor symbol, and the linker rejects. Move the function bodies out of the `export` block in `pm/resolver.cppm` (declarations only there, definitions in a non-export `mcpp::pm` block later in the same module unit). Single definition point, single instantiation site — the cross-module duplicate goes away and musl-gcc links cleanly. Reproduced and verified locally with `mcpp build --target x86_64-linux-musl` on the same musl-gcc 15.1 toolchain CI uses. `mcpp build` (glibc) + `mcpp test` (9/9 unit) still pass.
1 parent 2a603e0 commit ba5f1a6

1 file changed

Lines changed: 24 additions & 6 deletions

File tree

src/pm/resolver.cppm

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,13 @@
55
// `.agents/docs/2026-05-08-pm-subsystem-architecture.md`). Strictly
66
// pulled out of `cli.cppm` with no behavior change; the same
77
// signatures, the same error strings, the same platform key picking.
8+
//
9+
// Implementation note: `resolve_semver` is **not** declared inline on
10+
// purpose. Inlining it across modules makes every importer
11+
// (cli.cppm, ...) instantiate `std::_Vector_base<vr::Version>`'s
12+
// destructor locally. With musl-gcc 15.1's libstdc++ that triggers
13+
// `undefined reference to std::_Vector_base<...>::_Vector_impl::~_Vector_impl()`
14+
// at link time. Single-definition-point sidesteps the bug.
815

916
export module mcpp.pm.resolver;
1017

@@ -34,7 +41,22 @@ inline constexpr std::string_view kXpkgPlatform =
3441
// "constraint" so callers re-resolve via the index — bare `1.2.3` is
3542
// treated as exact for back-compat with pre-SemVer pinning workflows;
3643
// users opt into resolution by writing `^1.2.3` etc.
37-
inline bool is_version_constraint(std::string_view v) {
44+
bool is_version_constraint(std::string_view v);
45+
46+
// Resolve a SemVer constraint against the index entry's available
47+
// versions. Returns the chosen exact version string, or an error
48+
// message. The fetcher is used to read the lua descriptor for the
49+
// requested package name.
50+
std::expected<std::string, std::string>
51+
resolve_semver(std::string_view name,
52+
std::string_view constraint,
53+
mcpp::pm::Fetcher& fetcher);
54+
55+
} // namespace mcpp::pm
56+
57+
namespace mcpp::pm {
58+
59+
bool is_version_constraint(std::string_view v) {
3860
if (v.empty()) return true;
3961
if (v == "*") return true;
4062
char c = v.front();
@@ -43,11 +65,7 @@ inline bool is_version_constraint(std::string_view v) {
4365
return false;
4466
}
4567

46-
// Resolve a SemVer constraint against the index entry's available
47-
// versions. Returns the chosen exact version string, or an error
48-
// message. The fetcher is used to read the lua descriptor for the
49-
// requested package name.
50-
inline std::expected<std::string, std::string>
68+
std::expected<std::string, std::string>
5169
resolve_semver(std::string_view name,
5270
std::string_view constraint,
5371
mcpp::pm::Fetcher& fetcher)

0 commit comments

Comments
 (0)