diff --git a/.github/workflows/wasm-build.yml b/.github/workflows/wasm-build.yml index ee598c5..c8b3657 100644 --- a/.github/workflows/wasm-build.yml +++ b/.github/workflows/wasm-build.yml @@ -33,6 +33,9 @@ jobs: - name: wasm32-unknown-unknown-example target: wasm32-unknown-unknown command: cargo build -p tinyxml2 --target wasm32-unknown-unknown --example wasm_parse + - name: wasm32-unknown-unknown-capi + target: wasm32-unknown-unknown + command: cargo build -p tinyxml2-capi --target wasm32-unknown-unknown --release - name: wasm32-wasip1 target: wasm32-wasip1 command: cargo build -p tinyxml2 --target wasm32-wasip1 @@ -42,6 +45,9 @@ jobs: - name: wasm32-wasip1-example target: wasm32-wasip1 command: cargo build -p tinyxml2 --target wasm32-wasip1 --example wasm_parse + - name: wasm32-wasip1-capi + target: wasm32-wasip1 + command: cargo build -p tinyxml2-capi --target wasm32-wasip1 --release steps: - name: Checkout repository uses: actions/checkout@v4 diff --git a/CHANGELOG.md b/CHANGELOG.md index 172994c..9424120 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,8 +2,19 @@ All notable changes to this project will be documented in this file. -The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), -and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [1.1.1] - 2026-07-14 + +### Added +- **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. +- **CI Validation for C/C++ WASM**: Added automated GitHub Actions check to compile `tinyxml2-capi` for WASM targets. +- **WASM FFI Integration Guide**: Added detailed compilation and linking instructions for Emscripten (`emcc`) and WASI SDK (`clang`) under `docs/architecture/wasm.md`. + +## [1.1.0] - 2026-07-01 + +### Added +- **`no_std` Support**: Added `no_std` support with `alloc` allocator feature-gated for resource-constrained environments. +- **Rust WASM Support**: Verified compilation and execution of `tinyxml2` core library under `wasm32-unknown-unknown` and `wasm32-wasip1`. +- **Abstract I/O**: File operations and stream writers are now feature-gated under the `std` feature. ## [1.0.0] - 2026-07-01 diff --git a/Cargo.lock b/Cargo.lock index 3fff8e0..186238f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -819,7 +819,7 @@ dependencies = [ [[package]] name = "tinyxml2" -version = "1.1.0" +version = "1.1.1" dependencies = [ "proptest", "serde", @@ -828,7 +828,7 @@ dependencies = [ [[package]] name = "tinyxml2-bench" -version = "1.1.0" +version = "1.1.1" dependencies = [ "cc", "criterion", @@ -837,7 +837,7 @@ dependencies = [ [[package]] name = "tinyxml2-capi" -version = "1.1.0" +version = "1.1.1" dependencies = [ "cbindgen", "tinyxml2", @@ -845,7 +845,7 @@ dependencies = [ [[package]] name = "tinyxml2-cpp-helper" -version = "1.1.0" +version = "1.1.1" dependencies = [ "cc", ] diff --git a/Cargo.toml b/Cargo.toml index 18dd990..0e753a9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,7 +9,7 @@ members = [ ] [workspace.package] -version = "1.1.0" +version = "1.1.1" edition = "2024" rust-version = "1.85.0" license = "MIT" diff --git a/ROADMAP.md b/ROADMAP.md index aebd8eb..ef6e9b8 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -309,15 +309,18 @@ parse_document() --- -## Phase 9: WASM & `no_std` Support (Target: Version 1.1.0) ✅ **COMPLETED** +## Phase 9: WASM & `no_std` Support (Target: Versions 1.1.0 & 1.1.1) ✅ **COMPLETED** Enable tinyxml2-rs to run in resource-constrained embedded environments and web browsers. -### Key Deliverables +### Key Deliverables (v1.1.0) - [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`. - [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`. - [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`. +### Key Deliverables (v1.1.1) +- [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. + --- ## Phase 10: XPath & Serde Integration (Target: Version 1.2.0) 🔲 **PLANNED** diff --git a/docs/architecture/wasm.md b/docs/architecture/wasm.md index d6946ad..3e14261 100644 --- a/docs/architecture/wasm.md +++ b/docs/architecture/wasm.md @@ -88,9 +88,63 @@ feature. Validate no_std support with `--lib`, or from a consumer crate that supplies the allocator, panic strategy, and host boundary required by that environment. +## C and C++ WebAssembly Support + +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. + +> [!NOTE] +> 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). + +When compiled to `wasm32-unknown-unknown` or `wasm32-wasip1`, it generates: +- A WebAssembly binary (`tinyxml2_capi.wasm`) +- A static library (`libtinyxml2_capi.a`) + +### Compiling the C FFI for WebAssembly + +To compile the C FFI bindings library for WebAssembly: + +```bash +# Target the browser / JavaScript environment (e.g. for Emscripten) +cargo build -p tinyxml2-capi --target wasm32-unknown-unknown --release + +# Target WASI environments (e.g. for Wasmtime, Wasmer) +cargo build -p tinyxml2-capi --target wasm32-wasip1 --release +``` + +The resulting library `libtinyxml2_capi.a` will be located under `target/wasm32-unknown-unknown/release/` or `target/wasm32-wasip1/release/`. + +### Linking in C/C++ WebAssembly Projects + +#### 1. Browser/Emscripten Toolchain (`emcc`) +To compile a C/C++ file with Emscripten and link the Rust WASM static library: + +```bash +emcc -Icrates/tinyxml2-capi/include -O3 \ + crates/tinyxml2-capi/examples/basic.c \ + target/wasm32-unknown-unknown/release/libtinyxml2_capi.a \ + -o basic.js \ + -s WASM=1 \ + -s ALLOW_MEMORY_GROWTH=1 +``` + +#### 2. WASI SDK Toolchain (`clang`) +To compile for a standalone WASI runtime (e.g., Wasmtime) using the WASI SDK: + +```bash +/path/to/wasi-sdk/bin/clang -Icrates/tinyxml2-capi/include -O3 \ + --sysroot=/path/to/wasi-sysroot \ + crates/tinyxml2-capi/examples/basic.c \ + target/wasm32-wasip1/release/libtinyxml2_capi.a \ + -o basic.wasm +``` + +### ABI and Memory Considerations +- **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). +- **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. + ## Validation -Use these commands when changing parser, DOM, or serialization code: +Use these commands when changing parser, DOM, serialization, or FFI code: ```bash cargo check -p tinyxml2 @@ -98,8 +152,10 @@ cargo check -p tinyxml2 --no-default-features --lib cargo check -p tinyxml2 --no-default-features --target wasm32-unknown-unknown --lib cargo check -p tinyxml2 --target wasm32-wasip1 --lib cargo build -p tinyxml2 --target wasm32-unknown-unknown --example wasm_parse +cargo build -p tinyxml2-capi --target wasm32-unknown-unknown --release +cargo build -p tinyxml2-capi --target wasm32-wasip1 --release cargo test -p tinyxml2 --all-targets +cargo test -p tinyxml2-capi ``` -Workspace crates that bind to native C/C++ code, such as `tinyxml2-capi`, -`tinyxml2-bench`, and `tinyxml2-cpp-helper`, remain native-only. +Workspace crates that bind to native C/C++ code, such as `tinyxml2-bench` and `tinyxml2-cpp-helper`, remain native-only.