Skip to content

QVAC-25104 fix: assert addons pin fabric's C++ runtime and narrow exports - #4519

Merged
jpgaribotti merged 6 commits into
mainfrom
fix/qvac-25104-addon-template-cxx-pin
Sep 17, 2026
Merged

jpgaribotti merged 6 commits into
mainfrom
fix/qvac-25104-addon-template-cxx-pin

Conversation

@jpgaribotti

@jpgaribotti jpgaribotti commented Sep 16, 2026

Copy link
Copy Markdown
Contributor

Part 2 of 2 — the consumer half of #4514, which landed and shipped as @qvac/fabric 0.16.0. Rebased onto main, so this diff is now only this half: the template guards, plus the commit that moves the six npm_runtime consumers onto the pinned runtime. Rationale: arch/qips/linux-fabric-libcxx-ownership.md.

🎯 What problem does this PR solve?

  • QVAC-25104 fix: pin consumers' C++ runtime with a named ELF version node #4514 makes fabric's C++ runtime pinnable, but nothing checks that an addon actually pinned it, and both halves of getting that wrong are silent. -nostdlib++ links cleanly whether or not fabric ends up providing the runtime, and a module that resolves it from the host's libstdc++ instead loads and runs — it just stops matching typed catches on any exception that crossed the seam, which surfaces as a package-level "Unknown error" a long way from the link that caused it. That is exactly how fabric 0.15.0 shipped a fix that never reached its consumers.
  • A workspace can also fall back to a registry fabric without saying so: pnpm-workspace.yaml sets linkWorkspacePackages: true and resolves from npm when the local version does not satisfy the range, so an addon can silently build against a published fabric that predates the node. This is not hypothetical — it is the state main is in right now. QVAC-25104 fix: pin consumers' C++ runtime with a named ELF version node #4514 bumped fabric to 0.16.0 while the six consumers still asked for ^0.15.0, and because a caret on a 0.x version locks the minor, all six stopped linking the workspace copy and resolved the published 0.15.0 instead.
  • Addon modules export far more than the two C entry points bare resolves by name — around 1985 symbols, including their own and nlohmann's typeinfo and the whole of inference-addon-cpp. bare loads modules RTLD_LOCAL, so those exports are unreachable rather than actively harmful, but it leaves the addon/fabric pair closed by the loader flags of whichever host loads it rather than by construction.

📝 How does it solve it?

Template guards (cmake/qvac-addon, template 0.2.00.3.0):

  • qvac_addon_finalize runs the new assert-fabric-cxx-runtime.cmake on every fabric-linked module as a POST_BUILD step. readelf --dyn-syms must show no undefined __cxa_* / __gxx_personality_v0 / _ZT* / _ZNSt* / operator-new symbol without a QVAC_FABRIC_ABI_1 requirement — __cxa_atexit, __cxa_finalize and _Unwind_* excepted, since glibc and libgcc_s own those rather than fabric. The built ELF is the only place the invariant is directly observable.
  • Configure fails outright when the installed fabric publishes no QVAC_FABRIC_OWNS_CXX_RUNTIME, which is what catches the registry fallback above. The assertion is skipped where fabric deliberately shares a libc++ by other means (Android's libc++_shared.so, the ASan build's libc++.so.1), which is what that flag distinguishes.
  • New addon-symbols.map narrows every ELF addon module to bare_* and napi_*, generalising what packages/asr-ggml/symbols.map applies by hand for the same reason. Exports drop from 1985 to 2, so an addon and fabric form one closed unit exposing plain C by construction. Imports are unaffected: local: *; constrains what the module defines, not what it resolves from fabric.
  • Documented in docs/architecture/ADDON-CMAKE-TEMPLATE.md, with the build-time guard recorded in the QIP's verification section.

Consumer floor (second commit, now that 0.16.0 is on npm):

  • @qvac/fabric ^0.15.0^0.16.0 for all six npm_runtime consumers in .github/fabric-consumers.json, which both satisfies the new configure guard and restores link:../fabric in the regenerated pnpm-lock.yaml.
  • All six take a patch bump with a changelog entry, the shape QVAC-25104 fix: let Linux addons catch exceptions thrown by fabric #4477 used for the 0.15.0 floor: each already has its current version published, so none can fold this into an unreleased entry, and a patch lets anyone tracking the current line pick the fix up without editing a range. model-fit joins them at 0.12.1 now that its 0.12.0 backmerge (#4511) has landed and main matches npm again; the fit-stub entry already sitting under its [Unreleased] heading stays there, being documentation and tests rather than shipped behaviour.
  • The entries state plainly that the typed-catch behaviour their 0.15.0-floor predecessors described never took effect, since with the runtime unpinned those handlers still saw a fabric throw as foreign. Changelogs are append-only here, so the correction is recorded in the new entry rather than rewritten into the old one.

🧪 How was it tested?

Locally on linux-x64, with fabric built from #4514 and llm-llamacpp built against it:

  • The assertion was checked in both directions: it reports 226 unpinned symbols on the pre-fix prebuild, and passes on the rebuilt module with 378 imports pinned to QVAC_FABRIC_ABI_1.
  • The configure guard was checked against a fabric whose config predates the ABI variables, which fails with the intended message rather than building something subtly wrong.
  • Exports on the rebuilt module drop to 2 (bare_register_module_v0, bare_get_module_name_v0), and dlsym on the plain names still resolves them, which is how bare locates a module.
  • Under bare, the three previously failing llm-llamacpp config scenarios and a genuine load failure all surface their real messages.

@qvac/fabric@0.16.0 resolves from npm, so the standalone npm install in pr-head-ts-checks no longer hits ETARGET on the new ranges. The prebuilds label is still needed: the six consumers have to be rebuilt against 0.16.0 for the new guards to be exercised at all.

Before this can merge

  • QVAC-25104 fix: pin consumers' C++ runtime with a named ELF version node #4514 merged
  • @qvac/fabric 0.16.0 released to npm
  • bump @qvac/fabric to ^0.16.0 for the six npm_runtime consumers, each with a changelog entry and its own version bump
  • regenerate pnpm-lock.yaml in the same commit, per CONTRIBUTING.md
  • rebase onto main — the rebased diff touches packages/**, so on-pr-nx still triggers (its paths: filter would skip a template-only diff and merge it with no native CI at all)
  • undraft

💥 Breaking Changes

No JS/TypeScript API change. Build-level: any target using qvac_addon_import_fabric_cxx_runtime requires a fabric that stamps QVAC_FABRIC_ABI_1, i.e. 0.16.0 or later, which the range bumps above enforce. Because the template is shared, the six ranges have to move together — a partial migration would leave the unmigrated addons failing the new configure guard.

@jpgaribotti jpgaribotti added prebuilds CI: run only prebuild/cache stage (requires verified) run-cpp-addon-tests CI: run C++ addon tests (requires verified) run-desktop-addon-tests CI: run desktop integration tests (requires verified) labels Sep 16, 2026
@github-actions

Copy link
Copy Markdown
Contributor

License compliance — clean

No new dependency license findings in this PR.

Warn-only (shadow) mode — this check does not block merges yet.

Updated automatically by the canonical license compliance workflow.

NOTICE presence (advisory)

Missing NOTICE (advisory, does not block):

  • ./docs/website
  • ./packages/fabric/test/integration
  • ./packages/llm-llamacpp/benchmarks/server
  • ./packages/llm-llamacpp/benchmarks/performance
  • ./packages/inference-addon-cpp/mobile
  • ./packages/asr-ggml/benchmarks/server
  • ./packages/embed-llamacpp/benchmarks/server
  • ./packages/embed-llamacpp/benchmarks/performance
  • ./packages/sdk/e2e
  • ./packages/vla-ggml/sim/server
  • ./.github/actions/release-merge-guard

jpgaribotti added a commit that referenced this pull request Sep 16, 2026
…hips

The six consumer ranges cannot move in the same commit as the bump after
all. The pr-head-ts-checks jobs run a standalone npm install per package
rather than through the pnpm workspace, so an unpublished ^0.16.0 fails
resolution outright -- ETARGET, no matching version -- and took six jobs
down with it. #4477 hit the same ordering constraint for the 0.15.0 floor:
ranges move once the release is on npm, which is what #4519 does.

The cost is that pnpm stops linking the workspace fabric into the six
consumers, because 0.16.0 no longer satisfies ^0.15.0, so the regenerated
lockfile records the published 0.15.0 for them. That is the same in-between
state main sat in after #4481 and before #4477, and it is content-identical
for those builds: the published 0.15.0 is the fabric they link today.
Native CI is unaffected either way, since overlay-local-fabric stages this
branch's own fabric into consumer node_modules when the fabric stack
changes, which is what the prebuilds label drives. The window closes when
#4519 lands.
jpgaribotti added a commit that referenced this pull request Sep 16, 2026
…hips

The six consumer ranges cannot move in the same commit as the bump after
all. The pr-head-ts-checks jobs run a standalone npm install per package
rather than through the pnpm workspace, so an unpublished ^0.16.0 fails
resolution outright -- ETARGET, no matching version -- and took six jobs
down with it. #4477 hit the same ordering constraint for the 0.15.0 floor:
ranges move once the release is on npm, which is what #4519 does.

The cost is that pnpm stops linking the workspace fabric into the six
consumers, because 0.16.0 no longer satisfies ^0.15.0, so the regenerated
lockfile records the published 0.15.0 for them. That is the same in-between
state main sat in after #4481 and before #4477, and it is content-identical
for those builds: the published 0.15.0 is the fabric they link today.
Native CI is unaffected either way, since overlay-local-fabric stages this
branch's own fabric into consumer node_modules when the fabric stack
changes, which is what the prebuilds label drives. The window closes when
jpgaribotti added a commit that referenced this pull request Sep 17, 2026
…ode (#4514)

* QVAC-25104 fix: pin consumers' C++ runtime with a named ELF version node

0.15.0 gave fabric the C++ runtime to export, but nothing reached it.
bare's executable links GNU libstdc++.so.6, so libstdc++ sits in the
process' global lookup scope, which the dynamic linker searches before a
dlopen'd module's own DT_NEEDED chain. A consumer linked with -nostdlib++
resolved __cxa_throw, the personality routine and the std:: typeinfo
objects from libstdc++ while taking only the libc++-only names from
fabric, and std::exception_ptr split down that seam: a captured exception
was re-raised with a foreign exception class that GNU's personality
routine can only match against catch (...). Every native error from load
reached JS as "Unknown error", not only the three config-validation cases.

Name the version node QVAC_FABRIC_ABI_1, so consumers record a DT_VERNEED
that libstdc++ cannot satisfy. The node covers the whole export surface:
an anonymous node cannot coexist with a named one, and the spliced C++ ABI
block has to stay inside the same global list to keep its precedence over
`local: *;`. It pins fabric's own internal references too, which were
being interposed the same way.

Publish QVAC_FABRIC_ABI_VERSION and QVAC_FABRIC_OWNS_CXX_RUNTIME through
the package config, so a consumer's build can assert it pinned the runtime
instead of trusting its link line, and can tell a deliberately shared
libc++ (Android, ASan) from a fabric too old to pin at all. Configure
fails if symbols.map and the declared node name drift apart.

Consumers must be rebuilt, and a mixed pairing is worse than either half
and silent: pinning fabric's internal references removes the accident that
both sides previously resolved the runtime from libstdc++ and so agreed on
one, so a consumer that is not rebuilt loses the typed catch it used to
get -- and still loads, because an unversioned reference binds to a
default-versioned definition. Ship as a minor; a caret on 0.x locks the
minor, so ^0.15.0 keeps already-published consumers away from it.

Verified on linux-x64 against a locally built fabric: a rebuilt
llm-llamacpp pins 378 imports to QVAC_FABRIC_ABI_1, and the load-mode,
repeat-penalty and device errors surface their real messages under bare.
The addon-template half, which asserts the pin at build time and narrows
addon exports to the bare C entry points, lands separately after this is
released to npm.

* QVAC-25104 chore: release @qvac/fabric v0.16.0

Folds the version bump into the fix PR so the release can be cut straight
from a release-fabric-0.16.0 branch: release-merge-guard only requires
package.json to match the branch version, and create-github-release reads
the [0.16.0] section out of the changelog.

Minor, not patch: a consumer that is not rebuilt against the version node
loses a typed catch it used to get and still loads, so ^0.15.0 has to keep
already-published consumers away from this release.

The six in-tree consumer ranges move in the same commit. pnpm-workspace's
linkWorkspacePackages resolves from the registry once the workspace
version stops satisfying the range, so bumping fabric alone flips all six
from link:../fabric to the published 0.15.0 -- which is both a lockfile
change and a silent downgrade of what CI builds them against. Their own
versions are untouched; nothing here releases a consumer.

pnpm-lock.yaml is regenerated with the pinned pnpm 11.17.0 rather than
hand-edited, so it also drops two orphaned @qvac/diffusion-cpp@0.23.0
entries that nothing has referenced since #4439 moved sdk and inference to
the workspace copy.

* QVAC-25104 fix: hold consumer fabric ranges at ^0.15.0 until 0.16.0 ships

The six consumer ranges cannot move in the same commit as the bump after
all. The pr-head-ts-checks jobs run a standalone npm install per package
rather than through the pnpm workspace, so an unpublished ^0.16.0 fails
resolution outright -- ETARGET, no matching version -- and took six jobs
down with it. #4477 hit the same ordering constraint for the 0.15.0 floor:
ranges move once the release is on npm, which is what #4519 does.

The cost is that pnpm stops linking the workspace fabric into the six
consumers, because 0.16.0 no longer satisfies ^0.15.0, so the regenerated
lockfile records the published 0.15.0 for them. That is the same in-between
state main sat in after #4481 and before #4477, and it is content-identical
for those builds: the published 0.15.0 is the fabric they link today.
Native CI is unaffected either way, since overlay-local-fabric stages this
branch's own fabric into consumer node_modules when the fabric stack
changes, which is what the prebuilds label drives. The window closes when

* QVAC-25104 docs: correct the 0.16.0 changelog on when consumer ranges move
@jpgaribotti
jpgaribotti force-pushed the fix/qvac-25104-addon-template-cxx-pin branch from bb5f885 to 8ded317 Compare September 17, 2026 08:38
@jpgaribotti
jpgaribotti marked this pull request as ready for review September 17, 2026 08:48
@jpgaribotti
jpgaribotti requested review from a team as code owners September 17, 2026 08:48
@github-actions

github-actions Bot commented Sep 17, 2026

Copy link
Copy Markdown
Contributor

Review Status

Current Status: ❌ PENDING
Approvals so far: Team Lead: 1

Pending reviews: Needs 1 more from Management, Team Lead, or Member.

@github-actions

Copy link
Copy Markdown
Contributor

🧪 C++ Test Coverage Report

Coverage:

📊 Detailed Coverage
Filename                         Regions    Missed Regions     Cover   Functions  Missed Functions  Executed       Lines      Missed Lines     Cover    Branches   Missed Branches     Cover
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
NmtLazyInitializeBackend.cpp          99                19    80.81%          11                 1    90.91%         157                34    78.34%          66                20    69.70%
NmtLazyInitializeBackend.hpp           2                 0   100.00%           1                 0   100.00%           1                 0   100.00%           0                 0         -
TranslationModel.cpp                 296               168    43.24%          28                 8    71.43%         506               213    57.91%         181               122    32.60%
TranslationModel.hpp                   1                 0   100.00%           1                 0   100.00%           1                 0   100.00%           0                 0         -
nmt.cpp                               72                22    69.44%           9                 1    88.89%         137                28    79.56%          44                16    63.64%
nmt.hpp                               51                 4    92.16%          11                 2    81.82%          53                 4    92.45%          28                 0   100.00%
nmt_beam_search.cpp                  116                25    78.45%          10                 3    70.00%         254                32    87.40%          76                19    75.00%
nmt_graph_decoder.cpp                164                78    52.44%          15                 7    53.33%         540               161    70.19%         112                69    38.39%
nmt_graph_encoder.cpp                 54                13    75.93%           3                 0   100.00%         268                33    87.69%          37                16    56.76%
nmt_loader.cpp                       270                67    75.19%          14                 0   100.00%         774                97    87.47%         161                67    58.39%
nmt_state_backend.cpp                188                46    75.53%          20                 0   100.00%         424                79    81.37%         121                51    57.85%
nmt_tokenization.cpp                  88                21    76.14%           8                 0   100.00%         135                36    73.33%          61                26    57.38%
nmt_utils.cpp                        211                34    83.89%          21                 0   100.00%         314                38    87.90%         143                45    68.53%
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
TOTAL                               1612               497    69.17%         152                22    85.53%        3564               755    78.82%        1030               451    56.21%

1 similar comment
@github-actions

Copy link
Copy Markdown
Contributor

🧪 C++ Test Coverage Report

Coverage:

📊 Detailed Coverage
Filename                         Regions    Missed Regions     Cover   Functions  Missed Functions  Executed       Lines      Missed Lines     Cover    Branches   Missed Branches     Cover
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
NmtLazyInitializeBackend.cpp          99                19    80.81%          11                 1    90.91%         157                34    78.34%          66                20    69.70%
NmtLazyInitializeBackend.hpp           2                 0   100.00%           1                 0   100.00%           1                 0   100.00%           0                 0         -
TranslationModel.cpp                 296               168    43.24%          28                 8    71.43%         506               213    57.91%         181               122    32.60%
TranslationModel.hpp                   1                 0   100.00%           1                 0   100.00%           1                 0   100.00%           0                 0         -
nmt.cpp                               72                22    69.44%           9                 1    88.89%         137                28    79.56%          44                16    63.64%
nmt.hpp                               51                 4    92.16%          11                 2    81.82%          53                 4    92.45%          28                 0   100.00%
nmt_beam_search.cpp                  116                25    78.45%          10                 3    70.00%         254                32    87.40%          76                19    75.00%
nmt_graph_decoder.cpp                164                78    52.44%          15                 7    53.33%         540               161    70.19%         112                69    38.39%
nmt_graph_encoder.cpp                 54                13    75.93%           3                 0   100.00%         268                33    87.69%          37                16    56.76%
nmt_loader.cpp                       270                67    75.19%          14                 0   100.00%         774                97    87.47%         161                67    58.39%
nmt_state_backend.cpp                188                46    75.53%          20                 0   100.00%         424                79    81.37%         121                51    57.85%
nmt_tokenization.cpp                  88                21    76.14%           8                 0   100.00%         135                36    73.33%          61                26    57.38%
nmt_utils.cpp                        211                34    83.89%          21                 0   100.00%         314                38    87.90%         143                45    68.53%
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
TOTAL                               1612               497    69.17%         152                22    85.53%        3564               755    78.82%        1030               451    56.21%

…orts

Consumer half of the fabric version-node change, and it lands after that
is released to npm.

Both halves of getting the pin wrong are silent. -nostdlib++ links
cleanly whether or not fabric ends up providing the runtime, and a module
that resolves it from the host's libstdc++ instead loads and runs -- it
just stops matching typed catches on any exception that crossed the seam,
surfacing as a package-level "Unknown error" a long way from the link
that caused it. The built ELF is the only place the invariant is directly
observable, so qvac_addon_finalize (template 0.2.0 -> 0.3.0) now runs
assert-fabric-cxx-runtime.cmake on every fabric-linked module: no
undefined C++ runtime symbol may lack a QVAC_FABRIC_ABI_1 requirement,
excepting the __cxa_atexit / __cxa_finalize / _Unwind_* entries that
glibc and libgcc_s own rather than fabric. Configure fails outright when
the installed fabric publishes no QVAC_FABRIC_OWNS_CXX_RUNTIME, which is
what catches a workspace that has fallen back to a registry fabric
predating the node, and the check is skipped where fabric deliberately
shares a libc++ by other means (Android, the ASan build).

Also narrow addon modules to the bare C entry points with a version
script, generalizing what packages/asr-ggml applies by hand: exports drop
from 1985 to 2. bare loads modules RTLD_LOCAL, so the wider set was
unreachable rather than actively harmful; declaring the interface makes
the addon/fabric pair a closed unit exposing plain C by construction,
rather than by the loader flags of whichever host loads it.

Verified on linux-x64 against a locally built fabric: llm-llamacpp pins
378 imports to QVAC_FABRIC_ABI_1, exports 2 symbols, the assertion fails
the build when the pin is removed, and the load-mode, repeat-penalty and
device errors surface their real messages under bare.
…runtime

@qvac/fabric 0.16.0 is published, so the consumer ranges can move to the
version that actually pins the C++ runtime. ^0.15.0 -> ^0.16.0 across the
npm_runtime roster restores link:../fabric in the lockfile as well: the
0.16.0 bump on main had pushed pnpm onto the published 0.15.0 for all six,
because a caret on 0.x locks the minor.

All six take a patch bump with a changelog entry, the same shape #4477
used for the 0.15.0 floor: every one already has its current version
published, so none can fold the change into an unreleased entry, and a
patch lets anyone tracking the current line pick the fix up without
editing a range. model-fit joins them at 0.12.1 now that the 0.12.0
backmerge (#4511) has landed and main matches npm again; the fit-stub
entry already sitting under its [Unreleased] heading stays there, being
documentation and tests rather than shipped behaviour.

The entries say plainly that the typed-catch behaviour their 0.15.0-floor
predecessors described never took effect: with the runtime unpinned those
handlers still saw a fabric throw as foreign. Changelogs are append-only
here, so the correction is recorded in the new entry instead of rewritten
into the old one.
@github-actions

Copy link
Copy Markdown
Contributor

🧪 C++ Test Coverage Report

Coverage:

📊 Detailed Coverage
Filename                         Regions    Missed Regions     Cover   Functions  Missed Functions  Executed       Lines      Missed Lines     Cover    Branches   Missed Branches     Cover
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
NmtLazyInitializeBackend.cpp          99                19    80.81%          11                 1    90.91%         157                34    78.34%          66                20    69.70%
NmtLazyInitializeBackend.hpp           2                 0   100.00%           1                 0   100.00%           1                 0   100.00%           0                 0         -
TranslationModel.cpp                 296               168    43.24%          28                 8    71.43%         506               213    57.91%         181               122    32.60%
TranslationModel.hpp                   1                 0   100.00%           1                 0   100.00%           1                 0   100.00%           0                 0         -
nmt.cpp                               72                22    69.44%           9                 1    88.89%         137                28    79.56%          44                16    63.64%
nmt.hpp                               51                 4    92.16%          11                 2    81.82%          53                 4    92.45%          28                 0   100.00%
nmt_beam_search.cpp                  116                25    78.45%          10                 3    70.00%         254                32    87.40%          76                19    75.00%
nmt_graph_decoder.cpp                164                78    52.44%          15                 7    53.33%         540               161    70.19%         112                69    38.39%
nmt_graph_encoder.cpp                 54                13    75.93%           3                 0   100.00%         268                33    87.69%          37                16    56.76%
nmt_loader.cpp                       270                67    75.19%          14                 0   100.00%         774                97    87.47%         161                67    58.39%
nmt_state_backend.cpp                188                46    75.53%          20                 0   100.00%         424                79    81.37%         121                51    57.85%
nmt_tokenization.cpp                  88                21    76.14%           8                 0   100.00%         135                36    73.33%          61                26    57.38%
nmt_utils.cpp                        211                34    83.89%          21                 0   100.00%         314                38    87.90%         143                45    68.53%
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
TOTAL                               1612               497    69.17%         152                22    85.53%        3564               755    78.82%        1030               451    56.21%

Comment thread cmake/qvac-addon/qvac-addon.cmake Outdated
@github-actions

Copy link
Copy Markdown
Contributor

🧪 C++ Test Coverage Report

Coverage:

📊 Detailed Coverage
Filename                         Regions    Missed Regions     Cover   Functions  Missed Functions  Executed       Lines      Missed Lines     Cover    Branches   Missed Branches     Cover
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
NmtLazyInitializeBackend.cpp          99                99     0.00%          11                11     0.00%         157               157     0.00%          66                66     0.00%
NmtLazyInitializeBackend.hpp           2                 2     0.00%           1                 1     0.00%           1                 1     0.00%           0                 0         -
TranslationModel.cpp                 296               296     0.00%          28                28     0.00%         506               506     0.00%         181               181     0.00%
TranslationModel.hpp                   1                 1     0.00%           1                 1     0.00%           1                 1     0.00%           0                 0         -
nmt.cpp                               72                72     0.00%           9                 9     0.00%         137               137     0.00%          44                44     0.00%
nmt.hpp                               51                51     0.00%          11                11     0.00%          53                53     0.00%          28                28     0.00%
nmt_beam_search.cpp                  116               116     0.00%          10                10     0.00%         254               254     0.00%          76                76     0.00%
nmt_graph_decoder.cpp                164               164     0.00%          15                15     0.00%         540               540     0.00%         112               112     0.00%
nmt_graph_encoder.cpp                 54                54     0.00%           3                 3     0.00%         268               268     0.00%          37                37     0.00%
nmt_loader.cpp                       270               270     0.00%          14                14     0.00%         774               774     0.00%         161               161     0.00%
nmt_state_backend.cpp                188               188     0.00%          20                20     0.00%         424               424     0.00%         121               121     0.00%
nmt_tokenization.cpp                  88                88     0.00%           8                 8     0.00%         135               135     0.00%          61                61     0.00%
nmt_utils.cpp                        211               211     0.00%          21                21     0.00%         314               314     0.00%         143               143     0.00%
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
TOTAL                               1612              1612     0.00%         152               152     0.00%        3564              3564     0.00%        1030              1030     0.00%

find_program() skips its search when the result variable already holds a
value, and the empty string copied from an unset CMAKE_READELF counts, so
the PATH fallback never ran: it reported that nothing was on PATH without
having looked. Measured rather than reasoned from policy -- a bare
find_program resolves the tool, the same call preceded by set(VAR "")
returns nothing and writes no cache entry, and that holds under CMP0125
and CMP0126 at both OLD and NEW, so it is not tied to the 3.25 floor.

Searching under QVAC_ADDON_READELF keeps the search reachable and gives
the resolved tool a documented cache entry to override. The genuine
absence path is unchanged: find_program yields -NOTFOUND, which is false,
so the fatal error still fires when no readelf exists.

Reported in review on #4519.
@github-actions

Copy link
Copy Markdown
Contributor

🧪 C++ Test Coverage Report

Coverage:

📊 Detailed Coverage
Filename                         Regions    Missed Regions     Cover   Functions  Missed Functions  Executed       Lines      Missed Lines     Cover    Branches   Missed Branches     Cover
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
NmtLazyInitializeBackend.cpp          99                19    80.81%          11                 1    90.91%         157                34    78.34%          66                20    69.70%
NmtLazyInitializeBackend.hpp           2                 0   100.00%           1                 0   100.00%           1                 0   100.00%           0                 0         -
TranslationModel.cpp                 296               168    43.24%          28                 8    71.43%         506               213    57.91%         181               122    32.60%
TranslationModel.hpp                   1                 0   100.00%           1                 0   100.00%           1                 0   100.00%           0                 0         -
nmt.cpp                               72                22    69.44%           9                 1    88.89%         137                28    79.56%          44                16    63.64%
nmt.hpp                               51                 4    92.16%          11                 2    81.82%          53                 4    92.45%          28                 0   100.00%
nmt_beam_search.cpp                  116                25    78.45%          10                 3    70.00%         254                32    87.40%          76                19    75.00%
nmt_graph_decoder.cpp                164                78    52.44%          15                 7    53.33%         540               161    70.19%         112                69    38.39%
nmt_graph_encoder.cpp                 54                13    75.93%           3                 0   100.00%         268                33    87.69%          37                16    56.76%
nmt_loader.cpp                       270                67    75.19%          14                 0   100.00%         774                97    87.47%         161                67    58.39%
nmt_state_backend.cpp                188                46    75.53%          20                 0   100.00%         424                79    81.37%         121                51    57.85%
nmt_tokenization.cpp                  88                21    76.14%           8                 0   100.00%         135                36    73.33%          61                26    57.38%
nmt_utils.cpp                        211                34    83.89%          21                 0   100.00%         314                38    87.90%         143                45    68.53%
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
TOTAL                               1612               497    69.17%         152                22    85.53%        3564               755    78.82%        1030               451    56.21%

gianni-cor
gianni-cor previously approved these changes Sep 17, 2026
Comment thread cmake/qvac-addon/qvac-addon.cmake Outdated
@github-actions

Copy link
Copy Markdown
Contributor

🧪 C++ Test Coverage Report

Coverage:

📊 Detailed Coverage
Filename                         Regions    Missed Regions     Cover   Functions  Missed Functions  Executed       Lines      Missed Lines     Cover    Branches   Missed Branches     Cover
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
NmtLazyInitializeBackend.cpp          99                19    80.81%          11                 1    90.91%         157                34    78.34%          66                20    69.70%
NmtLazyInitializeBackend.hpp           2                 0   100.00%           1                 0   100.00%           1                 0   100.00%           0                 0         -
TranslationModel.cpp                 296               168    43.24%          28                 8    71.43%         506               213    57.91%         181               122    32.60%
TranslationModel.hpp                   1                 0   100.00%           1                 0   100.00%           1                 0   100.00%           0                 0         -
nmt.cpp                               72                22    69.44%           9                 1    88.89%         137                28    79.56%          44                16    63.64%
nmt.hpp                               51                 4    92.16%          11                 2    81.82%          53                 4    92.45%          28                 0   100.00%
nmt_beam_search.cpp                  116                25    78.45%          10                 3    70.00%         254                32    87.40%          76                19    75.00%
nmt_graph_decoder.cpp                164                78    52.44%          15                 7    53.33%         540               161    70.19%         112                69    38.39%
nmt_graph_encoder.cpp                 54                13    75.93%           3                 0   100.00%         268                33    87.69%          37                16    56.76%
nmt_loader.cpp                       270                67    75.19%          14                 0   100.00%         774                97    87.47%         161                67    58.39%
nmt_state_backend.cpp                188                46    75.53%          20                 0   100.00%         424                79    81.37%         121                51    57.85%
nmt_tokenization.cpp                  88                21    76.14%           8                 0   100.00%         135                36    73.33%          61                26    57.38%
nmt_utils.cpp                        211                34    83.89%          21                 0   100.00%         314                38    87.90%         143                45    68.53%
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
TOTAL                               1612               497    69.17%         152                22    85.53%        3564               755    78.82%        1030               451    56.21%

Comment thread cmake/qvac-addon/assert-fabric-cxx-runtime.cmake
Comment thread cmake/qvac-addon/assert-fabric-cxx-runtime.cmake
GustavoA1604
GustavoA1604 previously approved these changes Sep 17, 2026
…s config

QVAC_FABRIC_OWNS_CXX_RUNTIME and QVAC_FABRIC_ABI_VERSION reach consumers
through a config that fabric installs to share/qvac-fabric/cmake, a
platform-shared path every prebuild leg writes and the artifact merge
collapses to one file, so their values are whichever leg finished last.
Only the two Linux legs of nine produce ON; a darwin leg publishes the
variable empty and Android publishes OFF, and either one walks the old
elseif into its silent skip -- no configure error, no POST_BUILD step, no
message. The guard this PR exists to add would simply not be there, and
which way it goes is re-rolled on every fabric release. The published
0.16.0 happens to carry ON.

So the check now asks fabric's own module, which is per-triplet and cannot
be the wrong platform's: __cxa_throw defined under a version node means
assert against that node, defined without one means fail (a workspace that
has fallen back to a registry fabric predating the scheme), and not
defined at all means fabric shares libc++ through a shared library and
there is nothing to pin to. That last case is the only legitimate skip and
it is now observed rather than declared.

Closes the mirror-image hole while here: a module that kept a runtime of
its own imports nothing from fabric, and a check that only inspects
imports passes it. It must now import at least one symbol under the node.

The skip comment named Android as a reason, but the enclosing block is
CMAKE_SYSTEM_NAME STREQUAL "Linux" and the NDK sets that to Android, so
the ASan build was always the only case that could reach it.

Reported in review on #4519.
The readelf parse was trusted to have produced something. It is now
checked: keep the numbered symbol entries, drop the table header, and fail
when none survive. Both files read here are dynamic objects that certainly
have entries, so an empty parse means the output was not understood -- a
readelf variant printing another format, a wrapper on PATH printing
something else -- and every question below answers itself the permissive
way. A stand-in printing "There is no dynamic symbol information in this
file." and exiting 0, or printing nothing at all, made fabric look like it
exports no runtime and the check skip with a status message; measured
before and after.

The module side of this was closed by the previous commit, which requires
at least one import under the node, so a module whose runtime came from a
bundled libc++.a or -static-libstdc++ -- contributing no undefined entries
and, under --exclude-libs,ALL plus local: *, no visible defined ones either
-- no longer arrives as silence. What was left was the fabric probe, where
an unread file is indistinguishable from the one legitimate skip.

Reported in review on #4519.
@github-actions

Copy link
Copy Markdown
Contributor

🧪 C++ Test Coverage Report

Coverage:

📊 Detailed Coverage
Filename                         Regions    Missed Regions     Cover   Functions  Missed Functions  Executed       Lines      Missed Lines     Cover    Branches   Missed Branches     Cover
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
NmtLazyInitializeBackend.cpp          99                99     0.00%          11                11     0.00%         157               157     0.00%          66                66     0.00%
NmtLazyInitializeBackend.hpp           2                 2     0.00%           1                 1     0.00%           1                 1     0.00%           0                 0         -
TranslationModel.cpp                 296               296     0.00%          28                28     0.00%         506               506     0.00%         181               181     0.00%
TranslationModel.hpp                   1                 1     0.00%           1                 1     0.00%           1                 1     0.00%           0                 0         -
nmt.cpp                               72                72     0.00%           9                 9     0.00%         137               137     0.00%          44                44     0.00%
nmt.hpp                               51                51     0.00%          11                11     0.00%          53                53     0.00%          28                28     0.00%
nmt_beam_search.cpp                  116               116     0.00%          10                10     0.00%         254               254     0.00%          76                76     0.00%
nmt_graph_decoder.cpp                164               164     0.00%          15                15     0.00%         540               540     0.00%         112               112     0.00%
nmt_graph_encoder.cpp                 54                54     0.00%           3                 3     0.00%         268               268     0.00%          37                37     0.00%
nmt_loader.cpp                       270               270     0.00%          14                14     0.00%         774               774     0.00%         161               161     0.00%
nmt_state_backend.cpp                188               188     0.00%          20                20     0.00%         424               424     0.00%         121               121     0.00%
nmt_tokenization.cpp                  88                88     0.00%           8                 8     0.00%         135               135     0.00%          61                61     0.00%
nmt_utils.cpp                        211               211     0.00%          21                21     0.00%         314               314     0.00%         143               143     0.00%
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
TOTAL                               1612              1612     0.00%         152               152     0.00%        3564              3564     0.00%        1030              1030     0.00%

1 similar comment
@github-actions

Copy link
Copy Markdown
Contributor

🧪 C++ Test Coverage Report

Coverage:

📊 Detailed Coverage
Filename                         Regions    Missed Regions     Cover   Functions  Missed Functions  Executed       Lines      Missed Lines     Cover    Branches   Missed Branches     Cover
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
NmtLazyInitializeBackend.cpp          99                99     0.00%          11                11     0.00%         157               157     0.00%          66                66     0.00%
NmtLazyInitializeBackend.hpp           2                 2     0.00%           1                 1     0.00%           1                 1     0.00%           0                 0         -
TranslationModel.cpp                 296               296     0.00%          28                28     0.00%         506               506     0.00%         181               181     0.00%
TranslationModel.hpp                   1                 1     0.00%           1                 1     0.00%           1                 1     0.00%           0                 0         -
nmt.cpp                               72                72     0.00%           9                 9     0.00%         137               137     0.00%          44                44     0.00%
nmt.hpp                               51                51     0.00%          11                11     0.00%          53                53     0.00%          28                28     0.00%
nmt_beam_search.cpp                  116               116     0.00%          10                10     0.00%         254               254     0.00%          76                76     0.00%
nmt_graph_decoder.cpp                164               164     0.00%          15                15     0.00%         540               540     0.00%         112               112     0.00%
nmt_graph_encoder.cpp                 54                54     0.00%           3                 3     0.00%         268               268     0.00%          37                37     0.00%
nmt_loader.cpp                       270               270     0.00%          14                14     0.00%         774               774     0.00%         161               161     0.00%
nmt_state_backend.cpp                188               188     0.00%          20                20     0.00%         424               424     0.00%         121               121     0.00%
nmt_tokenization.cpp                  88                88     0.00%           8                 8     0.00%         135               135     0.00%          61                61     0.00%
nmt_utils.cpp                        211               211     0.00%          21                21     0.00%         314               314     0.00%         143               143     0.00%
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
TOTAL                               1612              1612     0.00%         152               152     0.00%        3564              3564     0.00%        1030              1030     0.00%

@github-actions

Copy link
Copy Markdown
Contributor

🧪 C++ Test Coverage Report

Coverage:

📊 Detailed Coverage
Filename                         Regions    Missed Regions     Cover   Functions  Missed Functions  Executed       Lines      Missed Lines     Cover    Branches   Missed Branches     Cover
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
NmtLazyInitializeBackend.cpp          99                19    80.81%          11                 1    90.91%         157                34    78.34%          66                20    69.70%
NmtLazyInitializeBackend.hpp           2                 0   100.00%           1                 0   100.00%           1                 0   100.00%           0                 0         -
TranslationModel.cpp                 296               168    43.24%          28                 8    71.43%         506               213    57.91%         181               122    32.60%
TranslationModel.hpp                   1                 0   100.00%           1                 0   100.00%           1                 0   100.00%           0                 0         -
nmt.cpp                               72                22    69.44%           9                 1    88.89%         137                28    79.56%          44                16    63.64%
nmt.hpp                               51                 4    92.16%          11                 2    81.82%          53                 4    92.45%          28                 0   100.00%
nmt_beam_search.cpp                  116                25    78.45%          10                 3    70.00%         254                32    87.40%          76                19    75.00%
nmt_graph_decoder.cpp                164                78    52.44%          15                 7    53.33%         540               161    70.19%         112                69    38.39%
nmt_graph_encoder.cpp                 54                13    75.93%           3                 0   100.00%         268                33    87.69%          37                16    56.76%
nmt_loader.cpp                       270                67    75.19%          14                 0   100.00%         774                97    87.47%         161                67    58.39%
nmt_state_backend.cpp                188                46    75.53%          20                 0   100.00%         424                79    81.37%         121                51    57.85%
nmt_tokenization.cpp                  88                21    76.14%           8                 0   100.00%         135                36    73.33%          61                26    57.38%
nmt_utils.cpp                        211                34    83.89%          21                 0   100.00%         314                38    87.90%         143                45    68.53%
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
TOTAL                               1612               497    69.17%         152                22    85.53%        3564               755    78.82%        1030               451    56.21%

@github-actions

Copy link
Copy Markdown
Contributor

🧪 C++ Test Coverage Report

Coverage:

📊 Detailed Coverage
Filename                         Regions    Missed Regions     Cover   Functions  Missed Functions  Executed       Lines      Missed Lines     Cover    Branches   Missed Branches     Cover
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
NmtLazyInitializeBackend.cpp          99                99     0.00%          11                11     0.00%         157               157     0.00%          66                66     0.00%
NmtLazyInitializeBackend.hpp           2                 2     0.00%           1                 1     0.00%           1                 1     0.00%           0                 0         -
TranslationModel.cpp                 296               296     0.00%          28                28     0.00%         506               506     0.00%         181               181     0.00%
TranslationModel.hpp                   1                 1     0.00%           1                 1     0.00%           1                 1     0.00%           0                 0         -
nmt.cpp                               72                72     0.00%           9                 9     0.00%         137               137     0.00%          44                44     0.00%
nmt.hpp                               51                51     0.00%          11                11     0.00%          53                53     0.00%          28                28     0.00%
nmt_beam_search.cpp                  116               116     0.00%          10                10     0.00%         254               254     0.00%          76                76     0.00%
nmt_graph_decoder.cpp                164               164     0.00%          15                15     0.00%         540               540     0.00%         112               112     0.00%
nmt_graph_encoder.cpp                 54                54     0.00%           3                 3     0.00%         268               268     0.00%          37                37     0.00%
nmt_loader.cpp                       270               270     0.00%          14                14     0.00%         774               774     0.00%         161               161     0.00%
nmt_state_backend.cpp                188               188     0.00%          20                20     0.00%         424               424     0.00%         121               121     0.00%
nmt_tokenization.cpp                  88                88     0.00%           8                 8     0.00%         135               135     0.00%          61                61     0.00%
nmt_utils.cpp                        211               211     0.00%          21                21     0.00%         314               314     0.00%         143               143     0.00%
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
TOTAL                               1612              1612     0.00%         152               152     0.00%        3564              3564     0.00%        1030              1030     0.00%

@github-actions

Copy link
Copy Markdown
Contributor

🧪 C++ Test Coverage Report

Coverage:

📊 Detailed Coverage
Filename                         Regions    Missed Regions     Cover   Functions  Missed Functions  Executed       Lines      Missed Lines     Cover    Branches   Missed Branches     Cover
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
NmtLazyInitializeBackend.cpp          99                19    80.81%          11                 1    90.91%         157                34    78.34%          66                20    69.70%
NmtLazyInitializeBackend.hpp           2                 0   100.00%           1                 0   100.00%           1                 0   100.00%           0                 0         -
TranslationModel.cpp                 296               168    43.24%          28                 8    71.43%         506               213    57.91%         181               122    32.60%
TranslationModel.hpp                   1                 0   100.00%           1                 0   100.00%           1                 0   100.00%           0                 0         -
nmt.cpp                               72                22    69.44%           9                 1    88.89%         137                28    79.56%          44                16    63.64%
nmt.hpp                               51                 4    92.16%          11                 2    81.82%          53                 4    92.45%          28                 0   100.00%
nmt_beam_search.cpp                  116                25    78.45%          10                 3    70.00%         254                32    87.40%          76                19    75.00%
nmt_graph_decoder.cpp                164                78    52.44%          15                 7    53.33%         540               161    70.19%         112                69    38.39%
nmt_graph_encoder.cpp                 54                13    75.93%           3                 0   100.00%         268                33    87.69%          37                16    56.76%
nmt_loader.cpp                       270                67    75.19%          14                 0   100.00%         774                97    87.47%         161                67    58.39%
nmt_state_backend.cpp                188                46    75.53%          20                 0   100.00%         424                79    81.37%         121                51    57.85%
nmt_tokenization.cpp                  88                21    76.14%           8                 0   100.00%         135                36    73.33%          61                26    57.38%
nmt_utils.cpp                        211                34    83.89%          21                 0   100.00%         314                38    87.90%         143                45    68.53%
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
TOTAL                               1612               497    69.17%         152                22    85.53%        3564               755    78.82%        1030               451    56.21%

1 similar comment
@github-actions

Copy link
Copy Markdown
Contributor

🧪 C++ Test Coverage Report

Coverage:

📊 Detailed Coverage
Filename                         Regions    Missed Regions     Cover   Functions  Missed Functions  Executed       Lines      Missed Lines     Cover    Branches   Missed Branches     Cover
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
NmtLazyInitializeBackend.cpp          99                19    80.81%          11                 1    90.91%         157                34    78.34%          66                20    69.70%
NmtLazyInitializeBackend.hpp           2                 0   100.00%           1                 0   100.00%           1                 0   100.00%           0                 0         -
TranslationModel.cpp                 296               168    43.24%          28                 8    71.43%         506               213    57.91%         181               122    32.60%
TranslationModel.hpp                   1                 0   100.00%           1                 0   100.00%           1                 0   100.00%           0                 0         -
nmt.cpp                               72                22    69.44%           9                 1    88.89%         137                28    79.56%          44                16    63.64%
nmt.hpp                               51                 4    92.16%          11                 2    81.82%          53                 4    92.45%          28                 0   100.00%
nmt_beam_search.cpp                  116                25    78.45%          10                 3    70.00%         254                32    87.40%          76                19    75.00%
nmt_graph_decoder.cpp                164                78    52.44%          15                 7    53.33%         540               161    70.19%         112                69    38.39%
nmt_graph_encoder.cpp                 54                13    75.93%           3                 0   100.00%         268                33    87.69%          37                16    56.76%
nmt_loader.cpp                       270                67    75.19%          14                 0   100.00%         774                97    87.47%         161                67    58.39%
nmt_state_backend.cpp                188                46    75.53%          20                 0   100.00%         424                79    81.37%         121                51    57.85%
nmt_tokenization.cpp                  88                21    76.14%           8                 0   100.00%         135                36    73.33%          61                26    57.38%
nmt_utils.cpp                        211                34    83.89%          21                 0   100.00%         314                38    87.90%         143                45    68.53%
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
TOTAL                               1612               497    69.17%         152                22    85.53%        3564               755    78.82%        1030               451    56.21%

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

prebuilds CI: run only prebuild/cache stage (requires verified) run-cpp-addon-tests CI: run C++ addon tests (requires verified) run-desktop-addon-tests CI: run desktop integration tests (requires verified)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants