--- title: Building Cross-Platform SDKs: From FFI to WebAssembly author: Mark Phelps full_title: Building Cross-Platform SDKs: From FFI to WebAssembly category: articles url: https://blog.flipt.io/from-ffi-to-wasm document_tags: ['backend', 'cgo', 'ffi', 'go', 'programming', 'rust', 'WASM', 'webassembly'] source: reader date: 2025-03-13 created: 2025-03-13 last_highlighted_date: 2025-03-12 published_date: 2025-03-10 summary: 🚀 A hybrid approach using WebAssembly (WASM) and native code enables truly portable cross-platform SDKs, addressing challenges posed by differing C standard libraries (glibc vs musl) and allowing for seamless language interoperability. --- # Building Cross-Platform SDKs: From FFI to WebAssembly ![rw-book-cover](https://blog.flipt.io/img/banner-og.png) ## Metadata - Author: [[Mark Phelps]] - Full Title: Building Cross-Platform SDKs: From FFI to WebAssembly - Category: #articles - Published: 2025-03-10 - Document Tags: #backend #cgo #ffi #go #programming #rust #WASM #webassembly - Source: reader - Last Highlighted: 2025-03-12 15:59:37.270516+00:00 - URL: https://blog.flipt.io/from-ffi-to-wasm ## Summary 🚀 A hybrid approach using WebAssembly (WASM) and native code enables truly portable cross-platform SDKs, addressing challenges posed by differing C standard libraries (glibc vs musl) and allowing for seamless language interoperability. ## Highlights - This post describes our journey building portable, cross-language SDKs for Flipt, and the unexpected technical challenges that forced us to rethink our approach a few times along the way. What started as a somewhat straightforward FFI implementation evolved into a complex exploration of C standard libraries, static linking, and eventually led us to WebAssembly. Along the way, we discovered that even in 2025, the dream of truly portable libraries remains surprisingly elusive - but our hybrid approach combining WASM with native code might be the key to cross-platform SDKs. ([View Highlight](https://read.readwise.io/read/01jp5h4pqwzfmc7wdmfgvg7e35)) - Tags: #đŸ‘» ai highlighted - Then an idea came. What if we could 'wrap' our static library with a shared library that would load the static library at runtime? This way we could still build our static library with the `musl` C standard library and have a shared library that could be used in any language via FFI. ([View Highlight](https://read.readwise.io/read/01jp5h4prc09ah2d25qnwrspjt)) - Tags: #đŸ‘» ai highlighted - All Linux first class ports are for systems using glibc only. Linux systems using other C libraries are not fully supported and are not treated as first class. ([View Highlight](https://read.readwise.io/read/01jp5h7h5a166b4gf7dwt690wr)) - WASM offered several compelling advantages: 1. Platform-independent bytecode format 2. No direct dependency on system libraries 3. Sandboxed execution environment 4. Isolated linear memory model ([View Highlight](https://read.readwise.io/read/01jp5h84h88jn9fzzqx0yta54z)) - WASM offered several compelling advantages: 1. Platform-independent bytecode format 2. No direct dependency on system libraries 3. Sandboxed execution environment 4. Isolated linear memory model ([View Highlight](https://read.readwise.io/read/01jp5h97x8w35nhbn2ywdx7fap)) - However, this expansion has revealed limitations in the core WASM specification: 1. No built-in threading support 2. No direct network access 3. Limited system interface capabilities 4. No direct file system access ([View Highlight](https://read.readwise.io/read/01jp5h8ebwe2a2bkzqs9b02zsc)) - However, this expansion has revealed limitations in the core WASM specification: 1. No built-in threading support 2. No direct network access 3. Limited system interface capabilities 4. No direct file system access ([View Highlight](https://read.readwise.io/read/01jp5h8zz5yc76erhqb118cff5)) - Working with WASM memory requires careful attention to prevent common issues: 1. **Memory Leaks**: Failing to call `deallocate` after allocating memory will cause leaks. This is particularly challenging in error paths where early returns might skip cleanup. 2. **Use After Free**: Reading from deallocated memory can cause undefined behavior. Always ensure memory is valid before access and copy data before deallocation if needed. 3. **Memory Management**: While WASM provides runtime bounds checking for memory access, you still need to carefully manage memory allocation and deallocation. The linear memory model requires explicit tracking of allocated regions. 4. **Resource Cleanup**: In concurrent scenarios, ensure proper cleanup when operations are cancelled or timeouts occur. ([View Highlight](https://read.readwise.io/read/01jp5ha348aw679ykz75p2jafr)) - We ended up using [wazero](https://github.com/tetratelabs/wazero), which is a pure Go runtime, and doesn't require CGO. Its API was similar enough to wasmtime's that we were able to make the switch relatively easily. ([View Highlight](https://read.readwise.io/read/01jp5hachbdf6cr145n5cqn4vt))