Skip to content

Latest commit

 

History

History
235 lines (180 loc) · 7.39 KB

File metadata and controls

235 lines (180 loc) · 7.39 KB

Actions Status Actions Status Actions Status codecov

Component Model C++

This repository contains a C++ ABI implementation of the WebAssembly Component Model.

Features

OS

  • Ubuntu 24.04
  • MacOS 13
  • MacOS 14 (Arm)
  • Windows 2019
  • Windows 2022

Host Data Types

  • Bool
  • S8
  • U8
  • S16
  • U16
  • S32
  • U32
  • S64
  • U64
  • F32
  • F64
  • Char
  • Strings (UTF-8, UTF-16, Latin-1+UTF-16)
  • List
  • Record
  • Tuple
  • Variant
  • Enum
  • Option
  • Result
  • Flags
  • Streams (readable/writable)
  • Futures (readable/writable)
  • Own
  • Borrow

Host Functions

  • lower_flat_values
  • lift_flat_values

Tests / Samples

  • ABI
  • WasmTime
  • Wamr
  • WasmEdge

When expanding the canonical ABI surface, cross-check the Python reference tests in ref/component-model/design/mvp/canonical-abi/run_tests.py; new host features should mirror the behaviors exercised there.

Build Instructions

Prerequisites

  • CMake 3.5 or higher (3.22+ recommended for presets)
  • C++20 compatible compiler
  • vcpkg for dependency management
  • Rust toolchain with cargo (for additional tools)

Platform-specific requirements

Ubuntu/Linux:

sudo apt-get install -y autoconf autoconf-archive automake build-essential ninja-build

macOS:

brew install pkg-config autoconf autoconf-archive automake coreutils libtool cmake ninja

Windows:

  • Visual Studio 2019 or 2022 with C++ support

Rust tools (required for samples and tests)

cargo install wasm-tools wit-bindgen-cli

Basic Build (Header-only)

For header-only usage without tests or samples:

git clone https://github.com/LexisNexis-GHCPE/component-model-cpp.git
cd component-model-cpp
git submodule update --init --recursive

mkdir build && cd build
cmake .. -DBUILD_TESTING=OFF -DBUILD_SAMPLES=OFF
cmake --build .

Build with Dependencies (Tests & Samples)

Using CMake presets with vcpkg:

Linux

git clone https://github.com/LexisNexis-GHCPE/component-model-cpp.git
cd component-model-cpp
git submodule update --init --recursive

# Configure and build
cmake --preset linux-ninja-Debug
cmake --build --preset linux-ninja-Debug

# Run tests
cd build && ctest -VV

Windows

git clone https://github.com/LexisNexis-GHCPE/component-model-cpp.git
cd component-model-cpp
git submodule update --init --recursive

# Configure and build
cmake --preset vcpkg-VS-17
cmake --build --preset VS-17-Debug

# Run tests
cd build && ctest -C Debug -VV

macOS

git clone https://github.com/LexisNexis-GHCPE/component-model-cpp.git
cd component-model-cpp
git submodule update --init --recursive

# Configure and build
cmake --preset linux-ninja-Debug
cmake --build --preset linux-ninja-Debug

# Run tests
cd build && ctest -VV

Manual Build without Presets

If you prefer not to use CMake presets:

mkdir build && cd build
cmake .. -DCMAKE_TOOLCHAIN_FILE=../vcpkg/scripts/buildsystems/vcpkg.cmake
cmake --build .
ctest -VV  # Run tests

Build Options

  • -DBUILD_TESTING=ON/OFF - Enable/disable building tests (requires doctest, ICU)
  • -DBUILD_SAMPLES=ON/OFF - Enable/disable building samples (requires wasi-sdk)
  • -DCMAKE_BUILD_TYPE=Debug/Release/RelWithDebInfo/MinSizeRel - Build configuration

Usage

This library is a header only library. To use it in your project, you can:

  • Copy the contents of the include directory to your project.
  • Use vcpkg to install the library and its dependencies.

Async runtime helpers

The canonical Component Model runtime is cooperative: hosts must drive pending work by scheduling tasks explicitly. cmcpp now provides a minimal async harness in cmcpp/runtime.hpp:

  • Store owns the pending task queue and exposes invoke plus tick().
  • FuncInst is the callable signature hosts use to wrap guest functions.
  • Thread::create builds a pending task with user-supplied readiness/resume callbacks.
  • Call::from_thread returns a cancellation-capable handle to the caller.
  • Task coordinates canonical backpressure, canon_task.{return,cancel}, and canon_yield helpers exposed through context.hpp.
  • canon_backpressure_{set,inc,dec} update in-flight counters; most canonical entry points now guard ComponentInstance::may_leave before touching guest state.

Typical usage:

cmcpp::Store store;
cmcpp::FuncInst func = [](cmcpp::Store &store,
              cmcpp::SupertaskPtr,
              cmcpp::OnStart on_start,
              cmcpp::OnResolve on_resolve) {
  auto args = std::make_shared<std::vector<std::any>>(on_start());
  auto gate = std::make_shared<std::atomic<bool>>(false);

  auto thread = cmcpp::Thread::create(
    store,
    [gate]() { return gate->load(); },
    [args, on_resolve](bool cancelled) {
      on_resolve(cancelled ? std::nullopt : std::optional{*args});
      return false; // finished
    },
    true,
    [gate]() { gate->store(true); });

  return cmcpp::Call::from_thread(thread);
};

auto call = store.invoke(func, nullptr, [] { return std::vector<std::any>{}; }, [](auto) {});
// Drive progress
store.tick();

Waitables, streams, and futures

The canonical async ABI surfaces are implemented via canon_waitable_*, canon_stream_*, and canon_future_* helpers on ComponentInstance. Waitable sets can be joined to readable/writable stream ends or futures, and canon_waitable_set_poll reports readiness using the same event payload layout defined by the spec. See the doctests in test/main.cpp for end-to-end examples.

Call tick() in your host loop until all pending work completes. Cancellation is cooperative: calling Call::request_cancellation() marks the associated thread as cancelled before the next tick().

Related projects

Star History

Star History Chart