mirror of
https://github.com/logos-co/logos-basecamp.git
synced 2026-08-27 06:41:14 +00:00
* fix(ci): run the symbol gate, and teach it the Windows layout
The gate was exposed in flake.nix `checks` and built by nothing. Both
workflows enumerate individual `nix build .#<output>` steps by hand and no
`nix flake check` runs in this repo, so `git grep -E 'symbol-gate|flake check'
-- .github/` returned nothing: the one control that mechanically enforces the
one-runtime invariant was dead code. A PR relinking the logos runtime into
main_ui would have merged green — and on Linux and macOS it would have RUN
green too, because both interpose a duplicate definition away at load time.
Two things were wrong with the gate itself, both specific to the platform
where a duplicate is actually fatal:
* the peer-image sweep globbed `$ROOT/lib` for *.dylib/*.so only. On Windows
every liblogos_* shared image is staged into bin/ as a .dll, so the sweep
matched nothing, no definer was found, and the exactly-one assertion
reported "0 definers" for TokenManager, LogosAPI and LogosAPIClient — it
could not pass on a correct tree. Its three sibling probes (provider,
negative control, consumer) had each been taught bin/*.dll; this one had
not.
* `nm -D` was selected for every non-Darwin target including the mingw
cross, and a PE has no ELF dynamic symbol table. Measured against a real
mingw PE (libffi-8.dll, binutils 2.46): `nm -D` reads 0 lines and errors,
plain `nm` reads 687, `nm --defined-only` 686. valid() would have caught
that and aborted the gate as vacuous rather than passing it, so this was
fail-closed — but the gate would never once have run on Windows.
x86_64-windows is not wired into CI here: that attribute cannot be evaluated
as pinned (see flake.nix's binBundleDir note), a pre-existing blocker. The
gate now understands the layout, so wiring it is a one-line follow-up.
Also drops two stale comments that pointed at LogosSharedFromDll.cmake, the
single-provider shim deleted in #348, and the claim that liblogos_core is the
provider — liblogos_protocol and liblogos_qt_host define these types now, which
is exactly why the assertion is exactly-one rather than naming an owner.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* fix(symbol-gate): call nm and c++filt by their target-prefixed names
The cross bintools installs ONLY x86_64-w64-mingw32-nm and
x86_64-w64-mingw32-c++filt; there is no bare `nm` or `c++filt` on PATH inside
the Windows derivation. Every measurement therefore produced nothing, and
valid() refused to assert over an empty read -- so the gate got as far as
identifying the right images and then stopped:
provider = bin/liblogos_core.dll
consumers = bin/LogosBasecamp.exe
plugins/package_manager_ui/package_manager_ui_replica_factory.dll
plugins/main_ui/main_ui.dll
== each runtime type is defined by EXACTLY ONE image ==
liblogos_core.dll ERROR: nm read 0 symbols — vacuous
That is the vacuity guard working exactly as intended: fail-closed rather than
report a reassuring zero. But it meant the gate could never actually run on
Windows. The tool was missing, not incapable -- the host's own nm reads these
PEs fine (7350 symbols out of liblogos_core.dll).
stdenv.cc.targetPrefix is "" natively, so this is a no-op on Linux and macOS.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* fix(symbol-gate): do not count PE import thunks as definitions
With nm reachable, the gate ran on Windows for the first time and reported a
split-brain that is not there:
TokenManager 4 definers: liblogos_core.dll(3) LogosBasecamp.exe(1)
liblogos_protocol.dll(41) liblogos_qt_host.dll(5)
liblogos_core.dll defines ZERO runtime symbols by design, and measures 0 on
macOS. The Windows numbers are an artifact of PE: for every imported function
GNU ld synthesizes a jump stub in .text AND an __imp_<mangled> slot in the
import address table, and `nm --defined-only` reports the stub as `T`. The
pairing is visible directly:
I __imp__ZN12TokenManager8instanceEv
T TokenManager::instance()
So the filter is that pairing: a symbol counts as DEFINED only when the image
has no __imp_ slot for it. That is the right discriminator rather than merely a
working one -- a genuine second copy statically linked into an image has no
__imp_ slot and still counts, which is exactly the case this gate exists to
catch.
The PE export table would also have suppressed the phantom (liblogos_core.dll
exports 0 TokenManager symbols, liblogos_protocol.dll exports 45), and it was
the first thing I reached for. It is the wrong tool here: a real private copy
is absent from the export table too, so it would trade this false positive for
a false negative.
Measured on the cross build, the filter reproduces the macOS shape exactly:
liblogos_core.dll TokenManager 0 LogosAPI/Client 0
liblogos_protocol.dll 41 109
liblogos_qt_host.dll 0 29
LogosBasecamp.exe 0 0
main_ui.dll 0 0
package_manager_ui_replica_factory.dll 0 0
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* ci(windows): run the symbol gate where it actually matters
The gate now evaluates, builds and passes for x86_64-windows, so wire it into
build-windows and drop the caveat the other two jobs carried saying it could
not be. PE has no symbol interposition, so a duplicate runtime that Linux and
macOS silently collapse to one is fatal only here -- and CI cross-builds this
bundle and never runs it, which makes a build-time assertion the only signal
that exists.
Measured on a real cross build (needs an x86_64-linux builder; logos_build_info.h
is an x86_64-linux derivation, so this cannot run from an aarch64-darwin host):
TokenManager 1 definer: liblogos_protocol.dll(41) OK
LogosAPI 1 definer: liblogos_qt_host.dll(32) OK
LogosAPIClient 1 definer: liblogos_protocol.dll(122) OK
TIER 1 LogosBasecamp.exe 0 · main_ui.dll 0 · pmui_replica_factory.dll 0
SYMBOL GATE: PASS
and the negative control rejects a planted duplicate on PE too, catching 41
TokenManager and 122 LogosAPIClient definitions including the one that names
the failure exactly:
guard variable for TokenManager::instance()::instance
That control is what makes the pass mean something. It also proves the __imp_
thunk filter does not over-reach: a genuine private copy is still detected at
full strength.
Also corrects the binBundleDir note, which was stale in BOTH of its claims --
logos-package-manager-ui not cross-compiling, and the separate EVAL-time
blocker in logos-package-downloader-module. Both were fixed upstream. The
bundle the gate just ran against contains package_manager_ui, so the tree the
note's measurements describe is missing a plugin that is no longer missing.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>