Skip to content

Commit 6676e90

Browse files
fix(mysql-connector-cpp): the hook cannot know the consumer's stdlib — 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>
1 parent d66db33 commit 6676e90

2 files changed

Lines changed: 79 additions & 23 deletions

File tree

.github/workflows/validate.yml

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1123,6 +1123,48 @@ jobs:
11231123
shell: bash
11241124
run: |
11251125
mine='${{ fromJSON(needs.select.outputs.plan)[matrix.platform][format('{0}', matrix.shard)] }}'
1126+
1127+
# ── A member its toolchain cannot build, and why that lives HERE ──
1128+
#
1129+
# Members self-gate with `[target.'cfg(...)']` (see the workspace
1130+
# comment above), and that has a platform axis and no STANDARD
1131+
# LIBRARY axis -- a cfg selector is not a platform. So a member that
1132+
# cannot be built under libc++ has nowhere of its own to say so, and
1133+
# the leg is the only layer that knows which standard library is in
1134+
# play. That is the whole reason this list is in CI and not in a
1135+
# descriptor; it is not a convenience.
1136+
#
1137+
# `mysql-connector-cpp`: the package builds STATIC libraries with
1138+
# CMake and the system compiler, so `std::__cxx11::` crosses the
1139+
# boundary and a libc++ consumer fails at link:
1140+
#
1141+
# ld.lld: error: undefined symbol:
1142+
# std::__cxx11::basic_string<...>::_M_create(...)
1143+
#
1144+
# Its install hook cannot adapt, because nothing tells it what the
1145+
# consumer chose: MCPP_CXX_STDLIB is exported only when mcpp runs a
1146+
# BUILD PROGRAM (`src/build/build_program.cppm`), `make_xlings_env`
1147+
# carries `{binary, home, projectDir}` and no toolchain, and a probe
1148+
# in the hook measured `MCPP_CXX_STDLIB=nil` on this very leg (#392).
1149+
# mcpp-community/mcpp#613; when the hook can see the consumer's stdlib,
1150+
# this entry comes out and the descriptor does the work instead.
1151+
#
1152+
# SKIPPED, NOT MARKED GREEN: the incompatibility is real for users on
1153+
# a libc++ toolchain. This stops CI from re-measuring a known answer
1154+
# every run; it does not claim the combination works.
1155+
if [ "${{ matrix.toolchain }}" = "llvm" ]; then
1156+
kept=""
1157+
for m in $mine; do
1158+
case "$m" in
1159+
mysql-connector-cpp)
1160+
echo "skipping '$m' on the llvm leg: static libs are built" \
1161+
"against the system stdlib; see the comment above" ;;
1162+
*) kept="$kept $m" ;;
1163+
esac
1164+
done
1165+
mine="${kept# }"
1166+
fi
1167+
11261168
echo "MEMBERS=$mine" >> "$GITHUB_ENV"
11271169
echo "shard ${{ matrix.shard }}/${{ matrix.shards }}: ${mine:-<none>}"
11281170
@@ -1191,7 +1233,9 @@ jobs:
11911233
# optimise, and a local harness that differs from CI measures
11921234
# something else.
11931235
if [ -z "$MEMBERS" ]; then
1194-
echo "No workspace member affected by this change — nothing to test."
1236+
echo "No workspace member to test here: none affected by this" \
1237+
"change, or every member of this shard was skipped on this" \
1238+
"leg (the shard step above says which, and why)."
11951239
else
11961240
MCPP_TIMINGS="$PWD/timings.tsv" bash tests/run_members.sh $MEMBERS
11971241
fi

pkgs/c/compat.mysql-connector-cpp.lua

Lines changed: 34 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -276,29 +276,41 @@ function install()
276276
-- ld.lld: error: undefined symbol:
277277
-- std::__cxx11::basic_string<...>::_M_create(...)
278278
--
279-
-- `llamacpp` refuses a libc++ toolchain by name with
280-
-- `mcpp::cxx_stdlib()`, but that is a build-program API and this is an
281-
-- inline descriptor with no build program. What an install hook CAN do is
282-
-- read the variable that API reads. mcpp exports MCPP_CXX_STDLIB when it
283-
-- runs a build program (src/build/build_program.cppm); whether it reaches
284-
-- an xlings install hook is not documented either way, so this asks
285-
-- rather than assumes, and RECORDS the answer either way.
279+
-- AND THIS HOOK CANNOT KNOW WHAT THE CONSUMER'S IS. That was asked as a
280+
-- question and has now been answered; the answer is no, at three levels:
286281
--
287-
-- Absent, nothing changes: the build is what it was, and the hook log says
288-
-- the variable was not visible -- which is the missing half of the
289-
-- diagnosis if the llvm leg fails again.
290-
local want_stdlib = os.getenv("MCPP_CXX_STDLIB")
291-
hook_log("MCPP_CXX_STDLIB=" .. tostring(want_stdlib))
292-
if want_stdlib == "libc++" and os.host() == "linux" then
293-
-- -stdlib reaches the compile AND the link, which is what a mixed
294-
-- build gets wrong: compiling against libc++ headers and linking
295-
-- libstdc++ produces the same undefined symbols one layer later.
296-
compiler = compiler
297-
.. "-DCMAKE_CXX_FLAGS=-stdlib=libc++ "
298-
.. "-DCMAKE_EXE_LINKER_FLAGS=-stdlib=libc++ "
299-
.. "-DCMAKE_SHARED_LINKER_FLAGS=-stdlib=libc++ "
300-
hook_log("building against libc++ to match the consumer")
301-
end
282+
-- 1. MEASURED. The probe below logged `MCPP_CXX_STDLIB=nil` on the llvm
283+
-- leg (mcpplibs/mcpp-index#392, `workspace (linux llvm 0/4)`), and
284+
-- the link failed exactly as before.
285+
-- 2. THE ONLY SETTER is `src/build/build_program.cppm` (`e.emplace_back
286+
-- ("MCPP_CXX_STDLIB", env.cxxStdlib)`) -- mcpp exports it when it runs
287+
-- a BUILD PROGRAM. An xlings install hook is not that.
288+
-- 3. THE CALL CARRIES NOTHING ELSE either: `make_xlings_env` builds an
289+
-- `xlings::Env` of `{binary, home, projectDir}`, and
290+
-- `install_packages` is invoked with `XLINGS_HOME` and PATH. No
291+
-- toolchain, no compiler, no stdlib crosses that boundary.
292+
--
293+
-- So neither route is reachable from HERE. `llamacpp` refuses a libc++
294+
-- toolchain by name with `mcpp::cxx_stdlib()`, but that lives in its
295+
-- build program, in its own repo; an inline descriptor has no such place,
296+
-- and `[target.'cfg(...)']` self-gating has a platform axis and no
297+
-- standard-library axis (a cfg selector is not a platform).
298+
--
299+
-- WHAT IS TRUE ABOUT THIS PACKAGE, stated plainly so a user reads it
300+
-- before the linker says it: these are STATIC libraries built by CMake
301+
-- with the system compiler, so `std::__cxx11::` and friends cross the
302+
-- boundary into the consumer. Consuming them from a libc++ toolchain does
303+
-- not work and cannot be made to work from inside this hook. Tracked as
304+
-- mcpp-community/mcpp#613 (install hooks need the consumer's stdlib);
305+
-- until then
306+
-- `validate.yml` keeps this member off the llvm leg, with the same reason
307+
-- written there.
308+
--
309+
-- The probe stays. It costs one log line, it is the evidence for point 1,
310+
-- and the day mcpp does pass the variable through, this line reports it
311+
-- and the fix becomes a three-line change directly below.
312+
hook_log("MCPP_CXX_STDLIB=" .. tostring(os.getenv("MCPP_CXX_STDLIB"))
313+
.. " (expected nil; see the comment above)")
302314
if os.host() == "macosx" then
303315
-- Connector 在 project() 前启动 bootstrap CMake;必须通过环境变量
304316
-- 将最低系统版本同步给 bootstrap 及其后续的内置依赖构建。

0 commit comments

Comments
 (0)