Repository navigation
feat(zig): add bindings/zig, example/zig-hello and Linux/macOS CI on Zig 0.17.0 - #321
Conversation
…Zig 0.17.0 (issue c4punks#36) First step of the Zig bindings agreed in issue c4punks#36. bindings/zig is a Zig package (minimum_zig_version 0.17.0) exporting a `cwist` module: - build.zig translates the installed CWIST headers with addTranslateC (Zig 0.17 has no @cImport) and links libcwist statically through `pkg-config --static cwist`, like the Rust build.rs: -I feeds translate-c, -L/-l the module, -lstdc++ maps to Zig's libc++, and the Homebrew directories of the system deps come from their own .pc files. - src/cwist.zig wraps App (init/deinit, get/post/put/delete/patch routes through the cwist_app_*_ex functions with a typed context and a comptime trampoline, in-memory dispatch, listen on the reactor server with one worker) plus Request/Response views and shutdown(), with tests against the real library. - src/cwist.h includes the system <stdatomic.h>/<pthread.h> first and build.zig defines __TTAK_STDATOMIC_SYSTEM_INCLUDED, so libttak does not fall back to its portable atomics shim, which translate-c cannot parse. example/zig-hello serves the same routes as example/rust-hello. .github/workflows/zig.yml (Linux and macOS) installs the official Zig 0.17.0 archive checked against its SHA-256, builds and installs CWIST, runs `zig build test`, and serves real requests with zig-hello through scripts/ci/hello_smoke.sh, the former rust_hello_smoke.sh, which now takes the expected X-Powered-By value as an argument (rust.yml updated).
|
The two WASM failures ("WASI 0.2 socket server smoke" and "Component pipeline (WIT + jco guests)") don't come from this PR, which changes no C code. Both stop compiling
So I've left it out of this PR. Happy to send a separate fix if useful, for example compiling that path out under |
|
The two Root cause, as far as I can tell: #318 (c299f60) made while (!atomic_load_explicit(&a->ack, memory_order_acquire)) {
if (pthread_equal(pthread_self(), a->dispatch_thread)) return true;
sched_yield();
}The ack is published only after the handler returns. The Rust server tests from #296/#299 deliberately complete the Since #318 guarantees a foreign completion never touches the response before the handler has returned, the race those tests force can no longer happen. The tests (and the |
…unks#36) On Linux the bundled C++ code in libcwist (BoringSSL) is built by g++ against libstdc++ and references its internals; the CI link failed on `std::__throw_out_of_range_fmt`, which Zig's own libc++ (what -lstdc++ otherwise maps to) does not provide. For a native Linux target build.zig now links the system libstdc++ found through `c++ -print-file-name` (CXX is honoured), and keeps Zig's libc++ elsewhere, including macOS, where the system runtime is libc++ and the job already passes.
…c4punks#36) With the system libstdc++ linked, the Linux CI link moved on to `_Unwind_Resume`: the g++-built objects need the libgcc_s unwinder, which the g++ driver links next to -lstdc++ and Zig does not. build.zig now resolves libgcc_s.so.1 (libgcc_s.so is a linker script) through `c++ -print-file-name` alongside libstdc++.so, and falls back to Zig's libc++ only if either is missing.
First step of the Zig bindings agreed in #36:
bindings/zigwith abuild.zigthat links throughcwist.pc, a hello example, and Linux/macOS CI pinned to Zig 0.17.0.What it adds
bindings/zigis a Zig package (build.zig.zon,minimum_zig_version = "0.17.0") that exports acwistmodule.@cImport, sobuild.zigtranslates the installed CWIST headers withb.addTranslateC(src/cwist.h). The raw API is available ascwist.c.build.zigrunspkg-config --cflags --libs --static cwist, the same way the Rustbuild.rsdoes:-Ipaths feed translate-c;-L/-lgo to the module, so libcwist and its bundled dependencies link statically from thecwist.pcdirectories;--statickeepsLibs.private(curl, nghttp2);-lstdc++maps to Zig's libc++;.pcfiles;PKG_CONFIGis honoured, and a missingcwist.pcfails with install instructions.src/cwist.zig). A small layer on top:App.init/deinit;get/post/put/delete/patch, registered through thecwist_app_*_exfunctions from feat(app): per-route user context with cwist_app_*_ex() registration (issue #36) #279, with a typed context (a pointer, orvoid) and a comptime trampoline;Request(method,path,body,header,param,query) andResponse(setStatus,setBody,addHeader) as views for one handler call;dispatch;listen(reactor server, one worker, no fork, same asApp::listenin Rust) andshutdown.example/zig-helloserves the same routes asexample/rust-hello(/and/users/:id, with anX-Powered-By: CWIST Zigheader) and stops on SIGTERM/SIGINT..github/workflows/zig.ymlruns onubuntu-latestandmacos-15:zig build test;zig-helloand runs it through the same smoke check asrust-hello: readiness,GET /,GET /users/42, 404, and SIGTERM with exit status 0.scripts/ci/rust_hello_smoke.shbecomesscripts/ci/hello_smoke.sh, which takes the expectedX-Powered-Byvalue as an argument.rust.ymlpasses"CWIST Rust"; the checks are otherwise unchanged.One translate-c detail: libttak's
stdatomic.hfalls back to a portable shim when the compiler does not look like GCC, and translate-c cannot parse that shim.src/cwist.hincludes the system<stdatomic.h>/<pthread.h>first, andbuild.zigdefines__TTAK_STDATOMIC_SYSTEM_INCLUDED. This is the same problem bindgen needed-D_Atomic=_Atomicfor.Tests
zig build testruns these against the real libcwist through in-memory dispatch:error.Header) and nothing is injected;error.Dispatch.In CI,
example/zig-helloserves real requests over TCP and shuts down cleanly on SIGTERM.Verification
Run locally on Windows with the official Zig 0.17.0. There is no libcwist build for these targets here, so linking stops at the expected undefined
cwist_*symbols.zig build test -Dtarget=x86_64-linux-gnu: translate-c of the CWIST headers and full semantic analysis ofsrc/cwist.zigand its tests succeed. The only errors are undefinedcwist_*symbols at link, from a stand-in empty libcwist.zig build -Dtarget=x86_64-linux-gnuinexample/zig-hello: same result, with the path dependency onbindings/zigresolving.zig build test -Dtarget=aarch64-macos: translate-c of the headers against the Darwin libc headers and semantic analysis succeed. The only errors come from the linker rejecting the Linux-format stand-inlibcwist.a.zig fmt --checkon all Zig and ZON files: cleanbash -n scripts/ci/hello_smoke.sh: OKgit diff --check, ASCII check: cleanpython scripts/ci/check_test_wiring.py,python scripts/ci/check_inline_exports.py: OKThe real link, running the tests and the example over TCP happen in this PR's CI (
Zig bindingson Linux and macOS). The Rust job checks the renamed smoke script.Not in this PR
cwist.cexposes them raw in the meantime, and they can follow one at a time as they did for Rust.