You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Commit 112aef1
Browse filesBrowse the repository at this point in the historyBrowse files
feat(deps): multi-version mangling — Level 1 fallback for cross-major coexistence
When SemVer merge fails (typically two non-overlapping pins like
=0.0.1 ⨯ =0.0.2 across two consumers of the same package), instead of
hard-erroring the resolver now stages the secondary version's source
under `target/.mangled/<consumer>/...` and rewrites its module
declarations to a mangled name (`<X>__v<M>_<m>_<p>__mcpp`). The
direct consumer's source is staged + rewritten too so its `import X;`
points at the mangled secondary BMI. Both BMIs coexist in the build
graph at distinct module names; C++23 module attachment isolates
their internal symbols, so no namespace mangling is needed.
Touches:
- `src/pm/mangle.cppm` (new) — pure helper: name format + a regex-free
source rewriter that handles `(export )?module X;`,
`(export )?module X:Y;`, `(export )?import X;`, `import X:Y;`. Bare
partition imports (`import :Y;`) and the global module fragment
(`module ;`) are left intact. 11 new unit tests in
`tests/unit/test_mangle.cpp`.
- `src/cli.cppm` — resolver conflict branch: when `try_merge_semver`
fails, run mangling instead of returning. WorkItem gains a
`consumerDepIndex` field so the fallback can locate the consumer
manifest for staging. Resolved record uses the mangled module name
as `[package].name` so the modgraph validator's "module must be
prefixed by package name" check passes.
- `src/build/plan.cppm` + `ninja_backend.cppm` — when two compile
units share a basename across packages (e.g. cmdline 0.0.1 and
staged-mangled 0.0.2 both have `parse.cppm`), the colliding object
paths get a per-package subdirectory (`obj/<sanitized-pkg>/<file>`).
`.ddi` placement follows. Single-package builds keep the original
`obj/<file>` layout so cache hashes don't churn.
- `tests/e2e/33_multi_version_mangling.sh` (new) — Y-shape graph:
libA pinned to cmdline 0.0.1, libB pinned to cmdline 0.0.2; the
build succeeds with both BMIs (`mcpplibs.cmdline.gcm` +
`mcpplibs.cmdline__v0_0_2__mcpp.gcm`) on disk and the runtime
output matches.
- `tests/e2e/32_semver_merge.sh` — drop the previously-irreconcilable
case; that's now Level 1's territory and is covered by test 33.
MVP scope (clear errors out of bounds):
- Conflicting consumer must be a dep, not the main package.
- Secondary version must be a leaf (no own transitive deps).
Both surfaces are documented in the error message so users know
which limit they hit and have a workaround (pin one version).
CHANGELOG 0.0.3 entry: covers all three resolution levels (transitive
walker / SemVer merge / mangling) and the obj-path-namespacing
side-fix to the build backend.
0 commit comments