Skip to content

feat(build): CWIST_FAT/CWIST_APP_FAT embedded-friendly fat archive - #427

Merged
gg582 merged 2 commits into
devfrom
feat/cwist-fat-archive
Oct 22, 2026
Merged

gg582 merged 2 commits into
devfrom
feat/cwist-fat-archive

Conversation

@gg582

@gg582 gg582 commented Oct 22, 2026

Copy link
Copy Markdown
Member

What

  • make CWIST_FAT=1 builds libcwist.a as a fat archive: all vendored static archives (BoringSSL, lsquic, libttak, cnats, cJSON, uriparser, usrsctp) are merged in via an ar MRI script (libtool -static on Darwin). An embedded target then needs only libcwist.a + include/cwist + the app source at link time; just system libraries (curl, nghttp2, brotli, zstd, z, pthread, dl, m, stdc++) stay external.
  • make CWIST_APP_FAT=1 (implies CWIST_FAT=1) drops the vendored archives from the example apps' link line via a new APP_LIBS variable, so app binaries pull everything from the fat libcwist.a.
  • A .build-fat stamp re-archives when the toggle flips (no object recompile); duplicate objects in OBJS are deduplicated in the fat merge.

Default builds are unchanged: make keeps producing the CWIST-objects-only archive and the existing link lines.

Verification (local, Ubuntu 24.04, gcc 14)

  • make CWIST_FAT=1 libcwist.a → 775 members (466 vendored), nm shows SSL_new, lsquic_engine_new, natsConnection_Connect, cJSON_Parse, sqlite3_open, uriParseUriA, usrsctp_socket.
  • Embedded simulation: copied only libcwist.a, include/, and example/micro/01-hello/main.c to a scratch dir, linked with system libs only, ran it, and curl http://127.0.0.1:8080/ returned Hello, CWIST!.
  • make CWIST_APP_FAT=1 example/micro/01-hello/hello link line references libcwist.a and zero vendored lib/**.a; binary serves correctly.
  • Flipping back to a plain build re-archives the CWIST-only lib via the stamp.

CI

New fat.yml workflow (push/PR to main/dev) reproduces all of the above: fat build, member/symbol checks, the scratch-dir embedded link smoke, and a CWIST_APP_FAT=1 example build.

gg582 added 2 commits October 22, 2026 22:59
- make CWIST_FAT=1 folds every vendored static archive (BoringSSL,
  lsquic, libttak, cnats, cJSON, uriparser, usrsctp) into libcwist.a via
  an ar MRI merge (libtool -static on Darwin), so copying the single
  archive plus include/cwist onto an embedded target is enough to link
  a server app; only system libraries stay external. A .build-fat stamp
  re-archives when the toggle flips, without recompiling objects.
- CWIST_APP_FAT=1 implies CWIST_FAT=1 and drops the vendored archives
  from the example apps' link line (APP_LIBS): the app binary pulls
  everything from libcwist.a.
- New fat.yml workflow builds the fat archive, checks vendored members
  and key symbols are folded in, links and serves the hello example in
  a scratch dir with only libcwist.a + headers + app source present,
  and builds an example with CWIST_APP_FAT=1.
- The ifeq-selected recipe was chosen at parse time, so fat-dist's
  target-specific CWIST_FAT=1 built a plain archive with a fat stamp;
  the embedded link then missed BoringSSL (SSL_get_error via the system
  OpenSSL DSO). Branch on $(CWIST_FAT) inside the recipe instead.
- New fat-dist target stages dist/cwist-fat/: the fat archive plus the
  vendored headers the public API references (cjson, openssl, sqlite3,
  ttak) — the bundle copied to the embedded board.
- fat.yml now builds fat-dist and runs the link smoke from the bundle.
@gg582
gg582 merged commit 6f680cf into dev Oct 22, 2026
27 checks passed
gg582 added a commit that referenced this pull request Oct 22, 2026
…427) to main (#434)

* feat(wasm): streaming dispatch in the component adapter (issue #203) (#426)

* feat(wasm): streaming dispatch in the component adapter (issue #203)

The cwist-guest-stream world had no JS entry point: the stream smoke
called guestStream.dispatchStream directly and collected chunks in a
hand-written host import. Consumers of cwist-wasm/component had nothing
to move SSE code onto from the Emscripten Module.cwistStreamChunk path.

createStreamHost() returns the c4punks:cwist/host import, and
handle.stream(init, onChunk) routes each send-chunk to the callback of
the stream in flight. The guest awaits each callback (backpressure). A
throwing callback reaches the guest as the err arm of send-chunk, which
aborts the pump, and stream() rejects with the callback's own error.
Streams on one handle run one at a time and wait for a pending
useSession().

component.d.ts now says handle() returns a Promise against 0.3 guests,
and types the streaming additions. The stream smoke drives the guest
through the adapter and adds the abort path.

Refs #203

* fix(wasm): share the stream runner registry and ship the io worker

- component.js kept STREAM_RUNNERS in module scope, but a bundler
  consumer (and the stream smoke's esbuild alias) inlines a second copy
  of the adapter into the guest bundle: the host registers with the
  bundled copy while stream() looks up the npm copy, so streaming always
  failed with 'streaming needs streamHost'. Keep the registry on
  globalThis so every copy shares it.
- preview3-shim's preview2-shim io worker spawns
  new Worker(new URL('./worker-thread.bundle.js', import.meta.url));
  esbuild does not emit that file, so component-stream-smoke copies it
  next to the bundle.

---------

Co-authored-by: Lee Yunjin <gzblues61@daum.net>

* feat(build): CWIST_FAT/CWIST_APP_FAT embedded-friendly fat archive (#427)

* feat(build): CWIST_FAT/CWIST_APP_FAT embedded-friendly fat archive

- make CWIST_FAT=1 folds every vendored static archive (BoringSSL,
  lsquic, libttak, cnats, cJSON, uriparser, usrsctp) into libcwist.a via
  an ar MRI merge (libtool -static on Darwin), so copying the single
  archive plus include/cwist onto an embedded target is enough to link
  a server app; only system libraries stay external. A .build-fat stamp
  re-archives when the toggle flips, without recompiling objects.
- CWIST_APP_FAT=1 implies CWIST_FAT=1 and drops the vendored archives
  from the example apps' link line (APP_LIBS): the app binary pulls
  everything from libcwist.a.
- New fat.yml workflow builds the fat archive, checks vendored members
  and key symbols are folded in, links and serves the hello example in
  a scratch dir with only libcwist.a + headers + app source present,
  and builds an example with CWIST_APP_FAT=1.

* fix(build): select the fat recipe at recipe time and stage fat-dist

- The ifeq-selected recipe was chosen at parse time, so fat-dist's
  target-specific CWIST_FAT=1 built a plain archive with a fat stamp;
  the embedded link then missed BoringSSL (SSL_get_error via the system
  OpenSSL DSO). Branch on $(CWIST_FAT) inside the recipe instead.
- New fat-dist target stages dist/cwist-fat/: the fat archive plus the
  vendored headers the public API references (cjson, openssl, sqlite3,
  ttak) — the bundle copied to the embedded board.
- fat.yml now builds fat-dist and runs the link smoke from the bundle.

---------

Co-authored-by: anux <anushree.kasturi06@gmail.com>
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