mirror of
https://github.com/logos-co/logos-plugin-qt.git
synced 2026-08-27 08:51:07 +00:00
* feat(qt-host): add logos_qt_host_shared, and assert its layering
PR-3 of the shared-runtime migration. Requires logos-protocol#65, which exports
logos_protocol_shared from the CMake package; without it this build hard-fails
by design rather than falling back.
WHY. LogosAPI (here) and TokenManager / LogosAPIClient / StoreRegistry (in
logos-protocol) must exist EXACTLY ONCE per process. Every image linking a
static archive gets its own copy of every function-local static inside it, so
the host writes a capability token into one store and another in-process image
reads an empty one -- with no build diagnostic. Linking ONE shared library is
what replaces the whole-archive + generated-.def scheme in which liblogos_core
absorbed both archives and re-exported them.
THE STATIC ARCHIVE STAYS, and not transitionally. Module plugins and ui_qml
backends run in their OWN processes, so their own copy is the CORRECT
per-process singleton; staying static also keeps a .lgx self-contained, since a
.lgx records an empty nix closure and a shared library would not travel with it.
In-process images link the shared target; out-of-process images link the archive.
THE ONE LINE THAT MATTERS is that logos_qt_host_shared PUBLIC-links
${LP_SHARED_TARGET}, not ${LP_TARGET}. Linking the static archive there would
embed a second TokenManager INSIDE liblogos_qt_host itself -- the same bug one
layer down, and invisible to the consumer-side symbol gate, which would treat
this library as a provider and pass. It is a one-word mistake that builds,
links, installs and loads, and surfaces only as refused calls at runtime in a
different repo. So this PR carries its own check:
checks.<system>.shared-runtime-layering
asserting liblogos_qt_host.{dylib,so} DEFINES LogosAPI, DEFINES NEITHER
TokenManager NOR LogosAPIClient, IMPORTS TokenManager, and has
liblogos_protocol on its link line. The positive assertion doubles as the
validity control: if nm or c++filt were broken it reports 0 for LogosAPI and
fails, rather than reporting a reassuring zero for the other two.
LogosAPI switches from LOGOS_SHARED_API to LOGOS_QT_HOST_API (logos-protocol#64)
because the two are not the same choice in one translation unit: building this
library, LogosAPI must be EXPORTED while TokenManager must be IMPORTED. On
Windows the shared target also compiles with LOGOS_SHARED_USE_DLL so the
protocol-owned types become dllimport; LOGOS_QT_HOST_BUILDING_SHARED is tested
FIRST in logos_shared_api.h, so LogosAPI still resolves to dllexport there.
ARCHIVE DESTINATION on the install is load-bearing on Windows and inert
elsewhere: a shared library's import library (.dll.a) is the ARCHIVE artifact
while the DLL is RUNTIME, so omitting it installs no import library and a
consumer gets an imported target whose IMPORTED_IMPLIB does not exist.
VERIFIED, aarch64-darwin:
liblogos_qt_host.dylib defines LogosAPI:: 23
defines TokenManager:: 0, LogosAPIClient:: 0
imports TokenManager:: 5, LogosAPIClient:: 1
links @rpath/liblogos_protocol.dylib
static archive symbol tables IDENTICAL to master (1494 lines), one
byte differing -- ar metadata, not content. The macro
switch is behaviour-preserving for every existing
consumer.
all 7 checks PASS
The layering check was confirmed discriminating rather than vacuous by running
its logic against liblogos_core.dylib, which defines TokenManager 32 times and
is correctly rejected.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* chore(deps): take logos-protocol master, which now exports the shared library
logos-protocol#65 merged as 2e3344a. The lock pinned 0d2a3c0, the commit BEFORE
it, so this branch would have configured against a protocol with no exported
logos_protocol_shared and tripped its own guard:
logos-protocol::logos_protocol_shared is not a target, so
logos_qt_host_shared cannot be built.
That guard is deliberate -- the alternative is silently falling back to the
static archive and embedding a second TokenManager -- but it means the lock bump
is a hard prerequisite rather than housekeeping.
Also moves protocol 0.4.0 -> 0.5.0 (#63, the module teardown surface), which is
why the Windows export table grows 360 -> 839: more symbols in the archive, all
of them generated rather than curated.
All 7 checks PASS against the merged protocol, including shared-runtime-layering.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>