chore(cbind): nim-ffi migration [2/9] — new-library scaffold + CI#2773
chore(cbind): nim-ffi migration [2/9] — new-library scaffold + CI#2773gmelodie wants to merge 12 commits into
Conversation
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## master #2773 +/- ##
==========================================
- Coverage 81.32% 81.31% -0.01%
==========================================
Files 171 171
Lines 31013 31014 +1
Branches 12 12
==========================================
- Hits 25221 25220 -1
- Misses 5792 5794 +2 🚀 New features to boost your workflow:
|
36ae5a8 to
0b3ac56
Compare
5ed8fb3 to
c656e20
Compare
3377a04 to
3d864f5
Compare
c656e20 to
8b39fc1
Compare
There was a problem hiding this comment.
Pull request overview
This PR introduces the initial scaffold for a new nim-ffi-based C bindings library (cbind/libp2p_ffi.nim) and wires it into Nix and GitHub Actions so it can be built and have C/CDDL bindings generated in parallel with the legacy cbind/ flow during the migration train.
Changes:
- Add a new nim-ffi library module (
cbind/libp2p_ffi.nim) with lifecycle entry points and config parsing (cbind/libp2p_ffi/config.nim). - Add temporary Nix/flake packaging to build the new FFI library and generate/install headers + CDDL (
nix/cbind-ffi.nix,flake.nix). - Extend the cbind nimble file and CI workflow with parallel tasks/jobs for building and generating bindings (
cbind/cbind.nimble,.github/workflows/cbindings.yml).
Reviewed changes
Copilot reviewed 7 out of 7 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| nix/cbind-ffi.nix | Adds a temporary Nix derivation to build the nim-ffi shared/static libs and generate/install C + CDDL outputs. |
| flake.nix | Exposes a temporary .#cbind-ffi flake package target for the new derivation. |
| cbind/libp2p_ffi/config.nim | Defines {.ffi.} config shapes and parsing into validated, typed ParsedConfig. |
| cbind/libp2p_ffi.nim | Adds the new nim-ffi library state, protocol mounting, node builder, lifecycle FFI entry points, and genBindings(). |
| cbind/cbind.nimble | Adds nimble tasks for building the new FFI library and generating C/CDDL bindings. |
| cbind/.gitignore | Ignores nim-ffi build caches and generated bindings output directories under cbind/. |
| .github/workflows/cbindings.yml | Adds a parallel CI job to build the new nim-ffi library and generate C/CDDL bindings. |
| return err("could not create libp2p node: " & e.msg) | ||
|
|
||
| proc libp2pDestroy*(lib: LibP2P) {.ffiDtor.} = | ||
| discard |
There was a problem hiding this comment.
The previous destroy 'waited' for the thread to return before returning. Does this do the same or just gets rid of lib? because if so, maybe we should defensively run a libp2pStop here?
There was a problem hiding this comment.
Good catch! Implemented a dtor hook that we can use here to make destroy call stop (needs this because destroy and stop are on different threads). Now they both call shutdown.
8df4348 to
b5f5891
Compare
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
ecd572d to
053ed72
Compare
21d09a0 to
502d422
Compare
nim-ffi cbind migration — PR train
Part 2 of a 9-PR train that replaces the hand-rolled
cbind/C bindings with the generated nim-ffi codegen, landing it domain by domain so each PR stays reviewable. Targetschore/cbind/ffi/01-deps-pinning(stacked).This PR adds
cbind/libp2p_ffi.nim, the new nim-ffi library, developed in parallel to the legacycbind/libp2p.nimso the old bindings keep shipping until the final flip. It carries the library state (LibP2P,StreamRegistry),declareLibrary, theMaxReadBytesread-ceiling reserved for the stream reads landing in a later PR, the node builder, the lifecycle entry points, andgenBindings().{.ffi.}config types (Libp2pConfig,BootstrapNode, the transport/muxer enums) and their parsing live incbind/libp2p_ffi/config.nim.config.parse()validates the raw config once and returns aParsedConfigof ready-to-use Nim values, so the node builder never touches a raw string or ordinal. The file isincluded rather than imported: nim-ffi reads{.ffi.}object fields from the AST, and exporting the fields would leak their*into the generated field names.mountProtocols, with Kademlia and service discovery mounting through separate helpers instead of one function branching on config flags.buildffi/genbindings_c/genbindings_cddlnimble tasks, a temporary.#cbind-ffinix target (which reuses the repo Makefile'snat_libstarget), and a temporaryc-bindings-ffiCI job — all pointed at the new file. The old.#cbindtarget and job are untouched.Lifecycle & shutdown
libp2pNew/libp2pStart/libp2pStop/libp2pDestroy.libp2pDestroyowns graceful shutdown: it stops the switch on the FFI worker loop before the threads are joined and the context is freed, so destroy alone is sufficient.libp2pStopis a thin, idempotent wrapper over the sameshutdownSwitchpath, kept for an explicit, error-reporting stop. Astoppedflag makes stop-then-destroy a no-op.{.ffiDtor.}; theffidep is re-pinned to feat(ffi): async teardown hook for {.ffiDtor.} logos-messaging/nim-ffi#115 (d1575f0). The FFI build compiles with-d:ffiThreadExitTimeoutMs=5000to give a gracefulswitch.stop()room beyond the 1500 ms default before the context is leaked.libp2p_new_default_config()is preserved for hosts that still call it, as a hand-maintained C-ABI mirror struct (the{.ffi.}config crosses as CBOR, not a C struct, so it isn't in the generated bindings).CI status
c-bindings-ffijob runs on macOS (macos-15/ arm64 / clang) but is currently disabled (if: false):libp2p_ffi.nimis built up domain by domain across PRs 2–9 and only compiles end-to-end at the flip, so a green run isn't meaningful until then. It's re-enabled (dropif: false) in the final PR. The legacyc-bindingsjob is unchanged and stays green throughout.Review artifact: the generated
libp2p.happears for the first time here, with just the lifecycle entry points.