fix(mysql-connector-cpp): the hook cannot know the consumer's stdlib — measured, then stated - #392
Merged
Merged
Conversation
…ay why not
CMake picks the system compiler here, so the static libs come out against
libstdc++ whatever the consumer uses. On the llvm leg, which links libc++,
the member fails at link with the libstdc++ half of its own dependency
undefined:
ld.lld: error: undefined symbol: std::_Rb_tree_increment(...)
ld.lld: error: undefined symbol:
std::__cxx11::basic_string<...>::_M_create(...)
`llamacpp` refuses a libc++ toolchain by name with `mcpp::cxx_stdlib()`,
and I said twice that the same lever was out of reach here because that is
a build-program API and this is an inline descriptor. That was half right.
The API is out of reach; the VARIABLE it reads is not necessarily —
MCPP_CXX_STDLIB is exported when mcpp runs a build program
(src/build/build_program.cppm), and whether it also reaches an xlings
install hook is documented nowhere.
So this asks instead of assuming, and records the answer either way:
* visible and `libc++` — build with `-stdlib=libc++`, on the compile and
both link flag sets. Compiling against libc++ headers while linking
libstdc++ produces the same undefined symbols one layer later, so the
flag has to reach all three.
* absent — nothing changes. The build is what it was, and the hook log
carries `MCPP_CXX_STDLIB=nil`, which is the missing half of the
diagnosis the next time that leg fails.
The failure has been read wrong once already in this area: `install()
result=nil` was taken for a cause when it was a successful install with no
return statement. A hook that reports what it saw is cheaper than a third
round of inference.
…— measured, then stated
The previous commit on this branch asked a question: does MCPP_CXX_STDLIB
reach an xlings install hook? It shipped a probe that logged the answer
either way and applied `-stdlib=libc++` if the answer was yes.
The answer is no, and this commit replaces the conditional with what was
learned. Three independent levels agree:
1. MEASURED. `MCPP_CXX_STDLIB=nil` on `workspace (linux llvm 0/4)`, and
the link failed exactly as before.
2. THE ONLY SETTER is `src/build/build_program.cppm` — mcpp exports it
when it runs a BUILD PROGRAM. An install hook is not that.
3. NOTHING ELSE CROSSES either: `make_xlings_env` builds an
`xlings::Env` of `{binary, home, projectDir}`, and `install_packages`
is invoked with `XLINGS_HOME` and PATH. No toolchain, no compiler,
no standard library.
So neither of the two routes I had assumed were available actually is.
`llamacpp` refuses a libc++ toolchain with `mcpp::cxx_stdlib()`, but that
lives in its build program in its own repo; an inline descriptor has no
such place. And `[target.'cfg(...)']` self-gating has a platform axis and
no standard-library axis — a cfg selector is not a platform.
The probe stays. One log line, it is the evidence for point 1, and the
day mcpp passes the variable through it reports that and the fix becomes
three lines directly below it.
What the descriptor can do is stop being silent: it now states that these
are static libraries built with the system compiler, that `std::__cxx11::`
therefore crosses the boundary, and that a libc++ consumer cannot use them
— where a user reads it, rather than where the linker says it.
`validate.yml` keeps the member off the llvm leg, with the same reasoning
written at the point that does the skipping. That is in CI and not in a
descriptor for a reason worth saying out loud: the leg is the only layer
that knows which standard library is in play. SKIPPED, NOT MARKED GREEN —
the incompatibility is real for users on a libc++ toolchain; this stops CI
re-measuring a known answer, it does not claim the combination works.
The empty-shard message downstream said "No workspace member affected by
this change", which would now be false in the case this change creates:
`linux llvm 0/4` holds mysql-connector-cpp and nothing else, so skipping it
empties the shard. It now covers both cases and points at the line that
says which.
Co-authored-by: sunrisepeak <x.d2learn.org@gmail.com>
Sunrisepeak
force-pushed
the
fix/mysql-connector-cpp-stdlib
branch
from
September 11, 2026 12:16
ceb58d1 to
6676e90
Compare
Sunrisepeak
added a commit
that referenced
this pull request
Sep 11, 2026
Every reason to distrust the diff used to escalate to the whole workspace. On a PR that is the wrong trade twice over: it buries the change under ~22 shards of unrelated work, and it puts the PR's own legs behind an hour of queue, so the thing under review is the last thing to report. Touching this file was enough to trigger it, which is the case that keeps biting: a one-line CI edit cannot be reviewed against a fast signal. Measured three times today -- #390, #391 and #392 each ran a full matrix to validate a change whose blast radius was one job. `full` now answers only where "check everything" IS the request: the weekly cron and a manual `workflow_dispatch`. On a PR or a push, the same reasons call `widen` instead, which records them, prints them, and writes them to the run summary so a reviewer sees WITHOUT opening a job that this run deliberately tested less -- and that the sweep is one manual dispatch away. Degraded, with their reasons kept: .github/workflows/validate.yml, tests/*.sh mcpp.toml non-member change unclassified path push with no predecessor / predecessor not in history NOT weakened: descriptor and member changes select their members exactly as before. The only thing that changed is what happens when the diff cannot be classified. One consequence handled. `widen` does not exit, so the push-with-no- predecessor path has to leave a usable range behind. `HEAD` alone would diff root-to-HEAD, name every file and select every member -- a full run by another name, which is what this change exists to stop. It leaves the range EMPTY instead: nothing selected, the reason already said, the summary carrying it to a human. Rare either way, since merges here are squashes and `event.before` is present on every normal push. The weekly Sunday 06:00 sweep is deliberately kept. It is the only thing that would have caught the windows vulkan regression before a user did -- main's leg was pinned to `windows-2022` in #385 and the vulkan members were never re-tested there until a full run happened to fire today. Removing the automatic full run on PRs and keeping the periodic net is the same shape openxlings/xim-pkgindex#815 just added on the other side. Verified: the rendered fragment on `pull_request` with a validate.yml edit plus an unclassified path selects only the member its descriptor change names, and the same input under `workflow_dispatch` still goes full. Co-authored-by: sunrisepeak <x.d2learn.org@gmail.com>
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.
What changed since the first push
The first push asked a question — does
MCPP_CXX_STDLIBreach an xlings install hook? — and shipped a probe that logged the answer either way and applied-stdlib=libc++if the answer was yes.The answer is no. This PR now carries the conclusion instead of the attempt.
The evidence, at three levels
11:46:18 MCPP_CXX_STDLIB=nilonworkspace (linux llvm 0/4), link failed as beforesrc/build/build_program.cppm:e.emplace_back("MCPP_CXX_STDLIB", env.cxxStdlib)— exported when mcpp runs a build programmake_xlings_envbuildsxlings::Env{binary, home, projectDir};install_packagesis invoked withXLINGS_HOMEand PATH. No toolchain crossesBoth routes I assumed were open are closed
llamacppdoes it withmcpp::cxx_stdlib()in its build program, in its own repo. An inline descriptor has no such place, and[target.'cfg(...)']self-gating has a platform axis and no standard-library axis (a cfg selector is not a platform).What this does instead
The descriptor stops being silent. It now states that these are static libraries built by CMake with the system compiler, that
std::__cxx11::therefore crosses the boundary into the consumer, and that a libc++ consumer cannot use them — where a user reads it rather than where the linker says it.The probe stays. One log line; it is the evidence for level 1, and the day mcpp passes the variable through, it reports that and the fix becomes the three lines directly below it.
validate.ymlkeeps the member off the llvm leg, with the reasoning written at the point that does the skipping. In CI and not in a descriptor for a reason worth saying out loud: the leg is the only layer that knows which standard library is in play.One consequence handled:
linux llvm 0/4holdsmysql-connector-cppand nothing else (386s, 100% of that shard), so skipping it empties the shard. The downstream message said "No workspace member affected by this change", which would now be false; it covers both cases and points at the line that says which.Verification
luac -pclean on the descriptorruby -ryamlparses the workflowif [ "$toolchain" = "llvm" ])The real fix is upstream of this repo
Install hooks need the consumer's standard library, or a source-built static package can never match its consumer's ABI. Filing that against mcpp; when it lands, the
validate.ymlentry comes out and the descriptor does the work.