fix: make the build.mcpp host helper self-contained on musl and MinGW - #298
Merged
Sunrisepeak merged 3 commits intoJul 28, 2026
Merged
Conversation
Sunrisepeak
force-pushed
the
fix/musl-build-mcpp-helper
branch
from
July 28, 2026 12:49
876792d to
6225db0
Compare
… (2026.7.28.2)
The compiled build.mcpp helper is exec'd by the host OS, outside anything
mcpp controls — no wrapper, no injected LD_LIBRARY_PATH, no PATH guarantee.
Whether it is actually runnable is a per-platform mechanism, and only two of
the four were closed:
Linux + glibc payload ok — host_base_flags bakes absolute payload paths
into -Wl,-rpath
Linux + musl (mcpp-community#295) bad — rpath cannot reach PT_INTERP, an absolute
/lib/ld-musl-<arch>.so.1 no payload installs
and no glibc distro ships -> execve ENOENT,
surfacing as a bare exit 127
Windows PE (mcpp-community#299) bad — PE has no rpath at all, so the helper resolves
libstdc++-6 / libgcc_s / libwinpthread via the
process PATH -> STATUS_DLL_NOT_FOUND
macOS ok — the system libc++ is always present
Both gaps are the same defect (build_program.cppm re-derives the helper link
policy instead of reusing the main build's, cf. prepare.cppm's musl ->
linkage="static" default), so they get ONE decision point rather than two
parallel predicates: a single staticHostHelper in run_build_program, with the
chosen policy folded into the build-program cache identity so pre-fix helpers
are rebuilt instead of reused. `-static` is appended to the final link argv
only — never to `base`, which also feeds the bundled module's compile and
precompile commands.
Also:
- process.cppm: keep the posix_spawnp error code and message in the captured
output instead of collapsing to an unexplained exit 127 (both capture_exec
and capture_exec_deadline). All three consumers of RunResult::output gate on
exit_code first, so nothing downstream changes.
- host_base_flags: stop emitting -Wl,-rpath on PE, where it is inert.
- tests/e2e/168 (was 167 — taken on main by 167_build_defines_module_scan):
discovers the installed musl-gcc payload instead of hardcoding 15.1.0, so it
runs on the aarch64 host where the regression actually lives; asserts static
+ no PT_INTERP. Verified by negative control: reverting the -static push
reproduces the exact mcpp-community#295 failure.
- tests/e2e/97: hold the build.mcpp helper to the same standalone bar as the
produced exe (import table + run with the toolchain bin off PATH). This runs
under the real MinGW GCC 16.1.0 on Windows CI, which is mcpp-community#299's configuration.
- ci-aarch64-fresh-install: append a PR regression gate that builds this source
and runs e2e 168 against it. The checkout must come AFTER the fresh-install
steps: .xlings.json declares an `mcpp` workspace pin, so a checkout present
in $GITHUB_WORKSPACE makes `xlings install mcpp` workspace-scoped — which
both voids the fresh-install charter (validating the pinned version, not the
published one) and leaves bare `mcpp` unresolvable outside the workspace.
Dropped the duplicated inline assertions, including
`! readelf … | grep -q …`, which bash exempts from errexit and which could
therefore never fail.
Closes mcpp-community#295
Closes mcpp-community#299
Supersedes mcpp-community#300
Co-authored-by: Zhe Feng <zhefeng7110@outlook.com>
Sunrisepeak
force-pushed
the
fix/musl-build-mcpp-helper
branch
from
July 28, 2026 12:56
6225db0 to
44f012a
Compare
3 tasks
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.
Summary
The compiled
build.mcpphelper is exec'd by the host OS, outside anything mcpp controls — no wrapper, no injectedLD_LIBRARY_PATH, no PATH guarantee. Whether it is actually runnable is a per-platform mechanism, and only two of the four were closed:-Wl,-rpathPT_INTERP(/lib/ld-musl-<arch>.so.1)libstdc++-6/libgcc_s/libwinpthreadresolve via process PATHBoth gaps are the same defect —
build_program.cppmre-derives the helper link policy instead of reusing the main build's (cf.prepare.cppm's musl →linkage = "static"default) — so they get one decision point rather than two parallel predicates.staticHostHelperinrun_build_program, with the chosen policy folded into the build-program cache identity so pre-fix helpers are rebuilt, not reused-staticgoes on the final link argv only, never intobase(which also feeds the bundled module's compile/precompile commands)host_base_flagsstops emitting-Wl,-rpathon PE, where it is inertposix_spawnpfailures keep their error code and message in the captured output instead of collapsing to an unexplained exit 127Test plan
-staticpush reproduces fix: statically link build.mcpp host helpers with musl toolchains #295 exactly —posix_spawnp(...) failed (error 2): No such file or directory, helper carriesPT_INTERP=/lib/ld-musl-x86_64.so.1RUNPATH— the rpath mechanism is untouchedmcpp test(37 binaries, incl. the newCaptureExec.MissingProgramReportsSpawnFailure)tests/e2e/89_build_mcpp.sh,tests/e2e/92_build_mcpp_import.shtests/e2e/168_build_mcpp_musl_host_static.sh— discovers the installed musl-gcc payload rather than hardcoding a version, so it runs on the aarch64 host where the regression lives (renamed from 167, whichmainnow uses for167_build_defines_module_scan)tests/e2e/97_mingw_toolchain.shextended to hold the helper to the same standalone bar as the produced exe (import table + run with the toolchain bin off PATH) — runs under real MinGW GCC 16.1.0 on Windows CI, which is fix: build.mcpp binary fails at runtime with missing DLL on Windows #299's configurationci-aarch64-fresh-installbuilds the PR source and runs e2e 168 against it; the published-asset validation steps keep using the installed mcpp. Dropped the duplicated inline assertions, including! readelf … | grep -q …, which bash exempts from errexit and which therefore could never fail.Closes #295
Closes #299
Supersedes #300 (same
-staticidea, narrowed to the two platforms that need it and keeping the Linux rpath path intact) — thanks @ZheFeng7110, credited viaCo-authored-by.