Skip to content

feat: Qt-free clients for apps (client mode, typed collections, logos_generate_clients) - #173

Draft
dlipicar wants to merge 6 commits into
feat/peeringfrom
feat/standalone-apps
Draft

dlipicar wants to merge 6 commits into
feat/peeringfrom
feat/standalone-apps

Conversation

@dlipicar

@dlipicar dlipicar commented Sep 26, 2026 •

Copy link
Copy Markdown
Contributor

Stacked on the peering branch (#172). A standalone C++ app (not a module) can generate typed clients for any module from its .lidl. The clients call through the app's own runtime, whether the module runs locally or is imported from a peered runtime. Module builds are byte-identical.

  • Generator:
    • --lidl X.lidl --api-style lp [--output-dir D] writes only <module>_api.{h,cpp}: no umbrella, no Qt. It is byte-for-byte the --dep wrapper modules already get.
    • Opt-in --typed-collections types [T], {tstr: T} and positional ?T through lidlTypeToStdCdylib and the protocol's codecs. Without it, nothing changes.
  • LogosCore: shellName() and client<T>(), which builds a generated client that calls as the shell; its calls use the credential start() adopted into the plain protocol image. The header's C mirror gains logos_consumer_call_async.
  • Build helpers: CMake logos_generate_clients(TARGET t LIDL a.lidl… [TYPED_COLLECTIONS]), shipped in the package config and running the generator at build time; nix lib.mkClients { system; lidls; typedCollections; }.

Verified (macOS):

  • Unit tests: checks.aarch64-darwin.tests 432/432.
  • Checks: generator-cli (5 new assertions), module-impl-abi, mk-clients, and clients-cmake. The last builds from the installed package, links the real plain protocol, and runs.
  • Round trips: the generated clients compile and round-trip a record of records, a uint > 2^32, a high-byte bstr, typed maps and lists, and both states of ?T. Mutations of the lenient decode, the record codec and the record qualification each fail these tests.
  • Byte identity: base and head generators over all 69 workspace .lidl files, in every mode, give 0 differences across 4,005 files.
  • End to end: bc-watch, a C++ client in logos-core-demo (local for now), runs a runtime of its own through LogosCore. It builds peering_module's and blockchain_module's clients with logos_generate_clients, links a logoscore daemon through its local invite, and imports its devnet node. It read height 8,519 and received live newBlock events.

Pre-existing emitter bugs found by compiling every contract's client, not fixed here because fixing them changes module output: a parameter named timeout_ms redefines the wrapper's own, C++-keyword names, and recursive records.

Android. packages.aarch64-android is the Qt-free SDK (nix/default.nix { qt = false; }): the headers and the CMake package a plain module or an app builds against on Android. It ships no generator, since generators run on the build machine. The last commit pins logos-co/logos-nix#16 and logos-co/logos-protocol#100 until they merge.

Stacked on #172. The CI on this repo runs for PRs into master, so read the checks above.

🤖 Generated with Claude Code

@github-actions

github-actions Bot commented Sep 26, 2026 •

Copy link
Copy Markdown

📊 cpp-sdk doc-test report

The real accounts module, run through a logoscore daemon with the whole stack built against this commit of the C++ SDK — rendered alongside the commands actually run and their output (updated each run, commit 0002196):

Pages can take a minute to update after the run finishes.

dlipicar and others added 6 commits October 3, 2026 11:31
`--lidl X.lidl --api-style lp` emits the lp wrapper alone, <module>_api.{h,cpp}:
exactly what the umbrella emits for `--dep <module>=X.lidl`, with no umbrella,
so a program that is not a module builds it with its own origin. `--lidl`
without --api-style (or with qt) still emits the Qt client stubs.

`--typed-collections`, in that mode only, types [T] (other than [tstr]),
{tstr: T} and positional ?T instead of collapsing them to LogosList / LogosMap.
lidl_to_json gives each such slot its lidlTypeToStdCdylib spelling, records
qualified; the lp emitter types the slot and moves it through logos-protocol's
logos::toJson / fromJson, with a codec specialization per record over the
existing conversions. Decode stays lenient: a wrong shape yields T{}. The flag
is refused in every other mode, and without it no emitter's output changes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
shellName() returns Config::shellName, kept for both runtime placements, and
client<T>() builds a generated lp client with it as the origin, in place, since
a client owns its lp_client and cannot move. Its calls use the shell credential
start() adopts into the plain protocol image, so the host links that image from
liblogos' lib output.

The C mirror gains logos_consumer_call_async and logos_consumer_result_cb,
which liblogos exports; the test stubs it with liblogos' exact signature, so the
mirror cannot drift unnoticed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
logos_generate_clients(TARGET t LIDL a.lidl... [TYPED_COLLECTIONS]
[OUTPUT_DIR d]) ships in the SDK's CMake package: it runs the client mode at
build time (the generator from LOGOS_CPP_GENERATOR, beside the package, or on
PATH) and adds each <module>_api.cpp and its directory to the target. The nix
twin, lib.mkClients { system; lidls; typedCollections ? false; }, takes a .lidl
or a module's packages.<sys>.lidl directory per module name.

tests/clients builds the generator from this checkout, generates a fixture's
client through the function, with and without typed collections, and runs it
over stubbed lp_* calls that echo their argument: a record of records, a uint
above 2^32, high-byte bstr, [int], {tstr: Rec}, ?tstr, nested records, events,
and lenient decode. Neither target sees Qt. checks.clients-cmake does the same
from the installed package against the real plain protocol image, and
checks.mk-clients covers the nix helper.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
packages.aarch64-android carries what a plain module reads from
LOGOS_CPP_SDK_ROOT: the headers, in both include roots, and the
logos-cpp-sdk CMake package. No generator: it runs on the build platform.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
logos-co/logos-nix#16 and logos-co/logos-protocol#100; revert both once
they merge.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@dlipicar
dlipicar force-pushed the feat/standalone-apps branch from 9546fd1 to c236837 Compare October 3, 2026 14:32
dlipicar added a commit to logos-co/logos-module-builder that referenced this pull request Oct 3, 2026
logos-co/logos-nix#16, logos-co/logos-protocol#100, logos-co/logos-cpp-sdk#173
and logos-co/logos-plugin-qt#51 carry what an aarch64-android module build
needs; revert each once it merges.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

This branch has not been deployed

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant