Runtime closure: bake dep runtime_dirs into RUNPATH; default Linux toolchain to glibc#109
Open
Sunrisepeak wants to merge 18 commits into
Open
Runtime closure: bake dep runtime_dirs into RUNPATH; default Linux toolchain to glibc#109Sunrisepeak wants to merge 18 commits into
Sunrisepeak wants to merge 18 commits into
Conversation
…ux toolchain to glibc R2: flags.cppm emitted -Wl,-rpath only from toolchain.linkRuntimeDirs, dropping dependency packages' [runtime] library_dirs (already collected into plan.runtimeLibraryDirs by plan.cppm). So host-GL passthrough dirs (e.g. compat.glx-runtime) never reached the binary RUNPATH and dlopen()'d libGL/libGLX failed at run time (GLX: Failed to load GLX). Iterate plan.runtimeLibraryDirs (superset) instead. R1: cli.cppm first-run default on Linux was gcc-musl-static, which cannot link the glibc world (X11/GL/system libs). Default to platform-native glibc gcc; musl-static stays opt-in via --target x86_64-linux-musl (Cargo-style).
…design Adds a builtin gui scaffold to `mcpp new` (Tier-0 imgui.app window starter, deps imgui 0.0.2, no toolchain pin). Verified: new --template gui -> build -> window renders. Also documents the long-term package-based template model (mcpp new name --template pkg@ver:tmpl, libraries ship templates/) as TODO.
mcpp why [toolchain|runtime|deps] (alias: resolve --explain) explains the resolved toolchain (incl. abi), the runtime library dirs baked into RUNPATH (surfacing the compat.glx-runtime host-GL closure), and locked deps — so defaults are inspectable, not magic (I4). self doctor: add a runtime-capabilities section probing x11/wayland display and the host GLVND opengl.glx.driver (libGLX + vendor), reporting the provider — capability-level, not just env health.
Aggregate dependency providers' [runtime] dlopen_libs/capabilities into the BuildPlan (with capability->provider mapping). doctor now reports each required host capability + its provider and verifies each provider-declared dlopen soname against the resolved runtime library_dirs — fully data-driven. Removes the previous #ifdef __APPLE__/_WIN32 + hardcoded /usr/lib paths: platform knowledge belongs in provider packages, not in mcpp core. why also surfaces capability->provider.
A dependency may declare an abi:<x> capability (e.g. compat.glfw -> abi:glibc). prepare_build now verifies the resolved toolchain's ABI satisfies every such requirement and fails fast with an actionable message on mismatch — turning a cryptic deep musl build error (libXdmcp arc4random_buf) into an upfront capability error. Enforces/diagnoses; abi-driven reselection (toolchain is resolved before the dep graph) is a resolution-ordering follow-up.
Writes a machine-readable resolution manifest (toolchain/abi, runtime closure library_dirs, dlopen_libs, capability->provider) next to build outputs — the serialized capability->plan, same data as `mcpp why`, usable by CI/tooling.
…oncat Use the existing json module for safe serialization/escaping instead of hand-built JSON.
Adds bundled build settings: built-in release (-O2) / dev (-O0 -g) / dist (-O3 -flto -s), overridable/extendable via [profile.<name>] (opt/debug/lto/ strip) in mcpp.toml. --profile selects; flags.cppm applies opt/debug/lto to compile and lto/strip to link. Verified: release/dev/dist emit distinct flags.
R2 precision: baking ALL of plan.runtimeLibraryDirs into -L/-rpath pulled the glibc payload dir into musl/static links (undefined _DYNAMIC; broke e2e 28/30). Split out plan.depRuntimeLibraryDirs (dependency [runtime] library_dirs only, e.g. compat.glx-runtime) and emit toolchain.linkRuntimeDirs + dep dirs, as before plus the dep closure. e2e 29 updated for the intentional glibc first-run default (musl-static is opt-in via --target).
…..]) [features] declares feature -> implied-features (with a 'default' set); long-form dep specs' features=[...] is now stored (was accepted-but-ignored) and requests features of that dependency. Activation = default ∪ requested, expanded transitively; each active feature becomes -DMCPP_FEATURE_<NAME> on that package's compile flags. Root activation via --features a,b. Verified: default set, --features, and implication closure all observable via #ifdef. Transitive dep->dep feature propagation is a follow-up.
…] 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.
…headers) The glibc first-run default (R1) needs the sysroot payloads exactly like `mcpp toolchain install` provides; the old musl-static default was self-contained, which masked this. Fixes fresh-home e2e 29/31 in CI (std module precompile: stdlib.h not found).
Extract gcc_post_install_fixup (patchelf PT_INTERP/RUNPATH for gcc/binutils + linker-specs wiring against sandbox glibc) out of `toolchain install` and run it from the first-run auto-install too. A fresh-sandbox glibc default previously skipped the fixup and could not find the C library (stdlib.h: No such file or directory — e2e 29/31 on CI). One shared pipeline, no duplicate.
gcc_post_install_fixup now skips payloads whose canonical path resolves outside this MCPP_HOME's registry: inherited (symlinked) payloads belong to their owner home, whose fixup is already valid; patching through the symlink rewrote the canonical binaries against ephemeral paths and bricked the owner's toolchain. Verified: fresh-home e2e (26/28/29/31) pass and the owner toolchain stays intact.
probe_payload_paths found glibc/linux-headers only as compiler SIBLINGS. With an inherited (symlinked) compiler the binary resolves into its owner home, so sysroot payloads freshly installed into the ACTIVE home (first-run default path) were invisible -> std module precompile failed with stdlib.h not found (CI fresh-home e2e 29/31). Add paths::active_home_xpkgs()/find_home_tool() and consult them after sibling search: discovery = compiler siblings ∪ active home registry.
…pile error A probed/remapped sysroot that exists but lacks stdlib.h (e.g. a partially-bootstrapped sandbox subos in a fresh MCPP_HOME) silently shadowed the payload -isystem fallback in both stdmod and flags, failing deep in the std module build. probe_sysroot now only returns a sysroot that actually contains the C headers (glibc usr/include or musl include layout) so all consumers uniformly fall through to payload paths. std-precompile failures now include the full compile command for actionable diagnosis.
…ity) Ground truth from CI (command now in the error): -isystem'd payload glibc include was present yet #include_next <stdlib.h> still failed. GCC's libstdc++ wraps libc headers with #include_next, which only searches directories AFTER the current header's dir — gcc's built-in dirs are last, so -isystem (inserted before them) is unreachable. Use -idirafter (appended to the very end) for GCC payload headers in both the std-module precompile and per-TU flags; clang keeps -isystem. Verified with a faithful fresh-home repro (no subos => invalid sysroot): first-run installs glibc default and builds clean.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Two general fixes that let native + GUI packages work out of the box
R2 — dependency
[runtime] library_dirswere dropped from binary RUNPATHsrc/build/plan.cppmalready collects every dependency package'sruntime.library_dirsintoplan.runtimeLibraryDirs(absolute). Butsrc/build/flags.cppmbuilt the produced binary's RUNPATH fromplan.toolchain.linkRuntimeDirsonly, so dependency runtime dirs were never emitted as-Wl,-rpath. Result: host-GL passthrough dirs (e.g.compat.glx-runtime's GLVND symlinks) weren't on the binary RUNPATH, so dlopen'dlibGL.so.1/libGLX.so.0failed →GLX: Failed to load GLX. Fix: iterateplan.runtimeLibraryDirs(a superset that includes toolchain dirs).R1 — fresh-machine Linux default was musl-static
src/cli.cppmfirst-run default on Linux wasgcc@15.1.0-musl(static), which cannot link the glibc world (X11/GL/system libs) — e.g.libXdmcparc4random_buf. Default to platform-native glibc gcc; musl-static stays opt-in viamcpp build --target x86_64-linux-musl(Cargo-style: default-gnu,-muslexplicit).Verified end-to-end (no special-casing)
Built mcpp with these changes; a fresh consumer
mcpp new app && mcpp add imgui && mcpp run:compat.glx-runtimedir (readelf -d).consumer demo okafter 120 frames) — previouslyGLX: Failed to load GLX.mcpp testunaffected.Design notes:
.agents/docs/2026-06-03-runtime-closure-and-toolchain-defaults.md. Part of the mcpp ecosystem打通 plan.