New here? See QUICKSTART.md.
MuPDF built as a
WASI 0.2 component, using
wasi-sdk 33 targeting
wasm32-wasip2. Loads under wasmtime and under any host that speaks the
component model — including wasmos in
the browser lane.
wit/mupdf.wit # artifex:mupdf@0.1.0 — types + document + convenience
src/component.c # C glue between wit-bindgen output and MuPDF C API
third_party/mupdf/ # git submodule, pinned to 1.28.2
scripts/
install-wasi-sdk.sh # wasi-sdk 33 for the host OS/arch → toolchain/wasi-sdk
install-tools.sh # wit-bindgen + wasm-tools → toolchain/bin
Makefile
# 1. Populate submodules
git submodule update --init --recursive
# 2. Fetch toolchain (wasi-sdk 33 + wit-bindgen + wasm-tools)
make tools
# 3. Build build/mupdf.component.wasm
makeThe last step wraps the wasip2 core module as a WASI 0.2 component and echoes the resolved WIT so you can see the export shape at a glance.
| Var | Default | What it does |
|---|---|---|
WASI_SDK_DIR |
./toolchain/wasi-sdk |
Point at an existing wasi-sdk install |
WIT_BINDGEN |
$(command -v wit-bindgen) |
Use a system wit-bindgen |
WASM_TOOLS |
$(command -v wasm-tools) |
Use a system wasm-tools |
Example:
make WASI_SDK_DIR=/opt/wasi-sdk-33.0world mupdf exports two interfaces (both in wit/mupdf.wit):
document— a resource: open once, then callmetadata,page-count,page-info,outline,render-page,extract-text,search,page-to-svg,page-to-html,to-clean-pdf.convenience— one-shot bytes-in/bytes-out helpers:render-first-page,document-info,extract-all-text.
Errors are a variant covering io, invalid-document, password-required,
wrong-password, not-supported, out-of-range, internal.
wasmtime run --wasi=preview2 -S component-model=y build/mupdf.component.wasmSince the component doesn't export a wasi:cli/run entrypoint, host code
(Rust with wasmtime::component::bindgen!, or JS via jco transpile) must
instantiate it and call the exported functions directly.
Transpile with jco inside your wasmos scaffold and consume it the same way
your other guest-* examples do; the produced component uses only
wasi:cli-agnostic imports so it works in both wasmtime and JS-host lanes.
OS=wasip2is passed to MuPDF'sMakerules— no branch matches, so Makerules falls through to its Unix defaults, and every host-specific feature (X11, GLUT, libcrypto, pthreads, objcopy) is disabled through theHAVE_*=nooverrides.make generateruns on the host (portable shell + host CC) to build MuPDF's font/hyphenation/ICC data C files; onlymake libsis cross- compiled with wasi-sdk._WASI_EMULATED_MMANand_WASI_EMULATED_SIGNALare enabled so MuPDF's incidental use ofmmap/signallinks cleanly under wasip2.- The linker uses
--gc-sections --no-entry; the component's entry points are the WIT exports, not amain.
Your LSP will complain about mupdf/fitz.h and mupdf.h on src/component.c
until you've run make bindings at least once — those headers live under
third_party/mupdf/include/ (populated by the submodule) and build/bindings/
(generated). Point compile_commands.json at build/bindings and
third_party/mupdf/include if you want clean intellisense.
cd third_party/mupdf && git fetch --tags && git checkout <newer-tag> && cd -
git submodule update --init --recursive
make clean && makeMuPDF is AGPL-3.0 (commercial licence available from Artifex). This wrapper code is under the same terms.