Skip to content

Commit 21d818e

Browse files
authored
feat: add WebAssembly support for C/C++ FFI and CI validation (#29)
* feat: add WebAssembly support for C/C++ FFI and CI validation * feat: update roadmap and documentation for WASM & no_std support in versions 1.1.0 & 1.1.1
1 parent dd45aa7 commit 21d818e

6 files changed

Lines changed: 88 additions & 12 deletions

File tree

.github/workflows/wasm-build.yml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,9 @@ jobs:
3333
- name: wasm32-unknown-unknown-example
3434
target: wasm32-unknown-unknown
3535
command: cargo build -p tinyxml2 --target wasm32-unknown-unknown --example wasm_parse
36+
- name: wasm32-unknown-unknown-capi
37+
target: wasm32-unknown-unknown
38+
command: cargo build -p tinyxml2-capi --target wasm32-unknown-unknown --release
3639
- name: wasm32-wasip1
3740
target: wasm32-wasip1
3841
command: cargo build -p tinyxml2 --target wasm32-wasip1
@@ -42,6 +45,9 @@ jobs:
4245
- name: wasm32-wasip1-example
4346
target: wasm32-wasip1
4447
command: cargo build -p tinyxml2 --target wasm32-wasip1 --example wasm_parse
48+
- name: wasm32-wasip1-capi
49+
target: wasm32-wasip1
50+
command: cargo build -p tinyxml2-capi --target wasm32-wasip1 --release
4551
steps:
4652
- name: Checkout repository
4753
uses: actions/checkout@v4

CHANGELOG.md

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,19 @@
22

33
All notable changes to this project will be documented in this file.
44

5-
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6-
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
5+
## [1.1.1] - 2026-07-14
6+
7+
### Added
8+
- **WebAssembly Support for C/C++ FFI**: Enabled compilation of the `tinyxml2-capi` FFI bindings crate for `wasm32-unknown-unknown` and `wasm32-wasip1` targets. C and C++ projects compiled to WebAssembly (via Emscripten or WASI SDK) can now link with the static library (`libtinyxml2_capi.a`) as a drop-in replacement.
9+
- **CI Validation for C/C++ WASM**: Added automated GitHub Actions check to compile `tinyxml2-capi` for WASM targets.
10+
- **WASM FFI Integration Guide**: Added detailed compilation and linking instructions for Emscripten (`emcc`) and WASI SDK (`clang`) under `docs/architecture/wasm.md`.
11+
12+
## [1.1.0] - 2026-07-01
13+
14+
### Added
15+
- **`no_std` Support**: Added `no_std` support with `alloc` allocator feature-gated for resource-constrained environments.
16+
- **Rust WASM Support**: Verified compilation and execution of `tinyxml2` core library under `wasm32-unknown-unknown` and `wasm32-wasip1`.
17+
- **Abstract I/O**: File operations and stream writers are now feature-gated under the `std` feature.
718

819
## [1.0.0] - 2026-07-01
920

Cargo.lock

Lines changed: 4 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ members = [
99
]
1010

1111
[workspace.package]
12-
version = "1.1.0"
12+
version = "1.1.1"
1313
edition = "2024"
1414
rust-version = "1.85.0"
1515
license = "MIT"

ROADMAP.md

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -309,15 +309,18 @@ parse_document()
309309

310310
---
311311

312-
## Phase 9: WASM & `no_std` Support (Target: Version 1.1.0) ✅ **COMPLETED**
312+
## Phase 9: WASM & `no_std` Support (Target: Versions 1.1.0 & 1.1.1) ✅ **COMPLETED**
313313

314314
Enable tinyxml2-rs to run in resource-constrained embedded environments and web browsers.
315315

316-
### Key Deliverables
316+
### Key Deliverables (v1.1.0)
317317
- [x] **no_std compatibility** — Feature-gate standard library dependencies and use the `alloc` crate for all dynamic memory allocations (`Vec`, `String`, `Box`). Target: `#![no_std]` with `extern crate alloc`.
318318
- [x] **WASM target support** — Validate the core crate on `wasm32-unknown-unknown` and `wasm32-wasip1`. JavaScript bindings are intentionally left to the host application boundary; see `docs/architecture/wasm.md`.
319319
- [x] **Abstract I/O** — Gate file/stream writers behind the `std` feature and keep the core parser, DOM, and string serialization available without `std::io::Write`.
320320

321+
### Key Deliverables (v1.1.1)
322+
- [x] **C/C++ FFI WASM Support** — Support compiling and linking the FFI bindings (`tinyxml2-capi`) on `wasm32-unknown-unknown` and `wasm32-wasip1` targets for C/C++ WebAssembly integration.
323+
321324
---
322325

323326
## Phase 10: XPath & Serde Integration (Target: Version 1.2.0) 🔲 **PLANNED**

docs/architecture/wasm.md

Lines changed: 59 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -88,18 +88,74 @@ feature. Validate no_std support with `--lib`, or from a consumer crate that
8888
supplies the allocator, panic strategy, and host boundary required by that
8989
environment.
9090

91+
## C and C++ WebAssembly Support
92+
93+
The C FFI compatibility layer (`tinyxml2-capi`) compiles to WebAssembly targets out of the box. C and C++ projects compiled to WebAssembly (via Emscripten or WASI SDK) can link against this compiled Rust artifact as a drop-in replacement.
94+
95+
> [!NOTE]
96+
> The project's CI validates compiling the Rust artifacts (`libtinyxml2_capi.a` and `tinyxml2_capi.wasm`) for WASM targets. Compiling and linking the final C/C++ application remains the responsibility of the consumer's C toolchain (e.g. Emscripten or WASI SDK).
97+
98+
When compiled to `wasm32-unknown-unknown` or `wasm32-wasip1`, it generates:
99+
- A WebAssembly binary (`tinyxml2_capi.wasm`)
100+
- A static library (`libtinyxml2_capi.a`)
101+
102+
### Compiling the C FFI for WebAssembly
103+
104+
To compile the C FFI bindings library for WebAssembly:
105+
106+
```bash
107+
# Target the browser / JavaScript environment (e.g. for Emscripten)
108+
cargo build -p tinyxml2-capi --target wasm32-unknown-unknown --release
109+
110+
# Target WASI environments (e.g. for Wasmtime, Wasmer)
111+
cargo build -p tinyxml2-capi --target wasm32-wasip1 --release
112+
```
113+
114+
The resulting library `libtinyxml2_capi.a` will be located under `target/wasm32-unknown-unknown/release/` or `target/wasm32-wasip1/release/`.
115+
116+
### Linking in C/C++ WebAssembly Projects
117+
118+
#### 1. Browser/Emscripten Toolchain (`emcc`)
119+
To compile a C/C++ file with Emscripten and link the Rust WASM static library:
120+
121+
```bash
122+
emcc -Icrates/tinyxml2-capi/include -O3 \
123+
crates/tinyxml2-capi/examples/basic.c \
124+
target/wasm32-unknown-unknown/release/libtinyxml2_capi.a \
125+
-o basic.js \
126+
-s WASM=1 \
127+
-s ALLOW_MEMORY_GROWTH=1
128+
```
129+
130+
#### 2. WASI SDK Toolchain (`clang`)
131+
To compile for a standalone WASI runtime (e.g., Wasmtime) using the WASI SDK:
132+
133+
```bash
134+
/path/to/wasi-sdk/bin/clang -Icrates/tinyxml2-capi/include -O3 \
135+
--sysroot=/path/to/wasi-sysroot \
136+
crates/tinyxml2-capi/examples/basic.c \
137+
target/wasm32-wasip1/release/libtinyxml2_capi.a \
138+
-o basic.wasm
139+
```
140+
141+
### ABI and Memory Considerations
142+
- **Shared Memory**: Since Rust and C/C++ compile into a single WebAssembly module when linked statically, they share the same linear memory and allocator (supplied by the C runtime or Rust's target).
143+
- **String Lifetimes**: Pointers returned by `tx_document_to_string`, `tx_element_name`, or other getters returning `*const c_char` point to UTF-8 C-strings borrowed from the `TxDocument`/`TxPrinter`-owned `CString` caches. Callers **must not free** these pointers. They become invalid as soon as the document is modified (mutated) or when the owning document/printer wrapper is freed.
144+
91145
## Validation
92146

93-
Use these commands when changing parser, DOM, or serialization code:
147+
Use these commands when changing parser, DOM, serialization, or FFI code:
94148

95149
```bash
96150
cargo check -p tinyxml2
97151
cargo check -p tinyxml2 --no-default-features --lib
98152
cargo check -p tinyxml2 --no-default-features --target wasm32-unknown-unknown --lib
99153
cargo check -p tinyxml2 --target wasm32-wasip1 --lib
100154
cargo build -p tinyxml2 --target wasm32-unknown-unknown --example wasm_parse
155+
cargo build -p tinyxml2-capi --target wasm32-unknown-unknown --release
156+
cargo build -p tinyxml2-capi --target wasm32-wasip1 --release
101157
cargo test -p tinyxml2 --all-targets
158+
cargo test -p tinyxml2-capi
102159
```
103160

104-
Workspace crates that bind to native C/C++ code, such as `tinyxml2-capi`,
105-
`tinyxml2-bench`, and `tinyxml2-cpp-helper`, remain native-only.
161+
Workspace crates that bind to native C/C++ code, such as `tinyxml2-bench` and `tinyxml2-cpp-helper`, remain native-only.

0 commit comments

Comments
 (0)