编程 Wasm Component Model 构建期组合实操笔记:用 WAC CLI 拼出单个 .wasm

2026-09-02 00:03:59

Wasm Component Model 构建期组合实操笔记:WAC CLI

1. Composition 在构建期到底做了什么

wac plug / wac compose 做的事情是:拿一个 primary 组件,把它的 imports 接到一个或多个 dependency 组件的 exports 上,最终产出一个新的 .wasm

组合结果的语义有几点必须记牢:

  • 新组件导出的东西 只跟 primary 一致,dependency 的导出不会冒出来。
  • 新组件的 imports = dependency 的 imports(未被满足的)+ primary 自身未被满足的 imports。
  • 组合是不对称的:primary 是“被满足方”,dependency 是“满足方”,调换角色会得到完全不同的结果。

2. 组合只能发生在“接口层”

如果 primary 组件直接 import 了某个函数(而不是一个 instance / world 接口),组合会直接失败,报错原文:

component
has a non-instance import named

所以:组件边界必须走 WIT 接口。任何直接 import "..." 函数(比如来自二进制链接的符号)的组件,都无法被 WAC 组合。这也是为什么“用组件模型拼原生 wasm 函数”这条路目前走不通。

3. 接口版本匹配是硬约束

组合时接口名是带版本的。test:mypackagetest:mypackage@0.1.0 是两个东西,wac 不会帮你做模糊匹配。

排查办法:用 wasm-tools component wit 直接看 .wasm 里嵌的 import/export 接口全名。

wasm-tools component wit validator-component.wasm
wasm-tools component wit regex-component.wasm

对比两边的 import / export 接口名(带不带 @version),不一致就老老实实改成同一版本再组合。

4. 简单场景:wac plug 一条命令

假设:

  • validator-component.wasm 导出 validator 接口,import 了 docs:regex/match@0.1.0
  • regex-component.wasm 导出 match 接口。

一个主组件 + 一个依赖:

wac plug validator-component.wasm --plug regex-component.wasm -o composed.wasm

多个依赖并列:

wac plug path/to/component.wasm \
--plug path/to/dep1.wasm \
--plug path/to/dep2.wasm \
-o composed.wasm

局限性wac plug 不处理传递依赖。如果 dep1 自己还有未满足的 import(例如还依赖 dep3),直接 wac plug 会报错或产出一个仍带 import 的组件。

解决办法:先把 dep1dep3 组合一次,得到新的组件再作为 plug 喂给 wac plug

wac plug dep1.wasm --plug dep3.wasm -o dep1-composed.wasm
wac plug primary.wasm --plug dep1-composed.wasm -o final.wasm

5. 复杂场景:用 WAC 语言 + wac compose

要描述任意组合关系(多个实例、显式绑定、指定导出入口),写一个 composition.wac

// 声明依赖包的实例
package docs:composition

let validator = new docs:validator-impl;
let regex = new docs:regex-impl;

// primary 是 validator 实例
export validator;

然后执行:

wac compose \
--dep docs:regex-impl=regex-component.wasm \
--dep docs:validator-impl=validator-component.wasm \
-o composed.wasm \
composition.wac

这个方式能显式控制 dependency 的满足关系,能覆盖 wac plug 处理不了的传递依赖,因为你可以先声明 let x = new dep; let y = new dep2; 再决定谁给谁。

6. 什么情况下别用 WAC / 组合

  • 组件里存在非接口 import(直接 import 函数),别试,必失败。
  • 接口版本不一致还没法改(比如第三方二进制锁定版本),别硬组合,先对齐版本。
  • 当你只需要“把两个组件链接起来”但不想承担 primary/dependency 语义时,别用 wac plug——它强制不对称,且只导出 primary 的接口。

7. 现状与判断

这套工具(WAC CLI)还处于早期阶段,来自 WebAssembly/component-model 仓库的 wac 子目录(以及官方 wac docs)。命令行为、错误信息、语义细节都可能变更。

我在实际使用中的判断:

  • 单层依赖、接口清晰:wac plug 够用。
  • 依赖链超过两层:直接用 WAC 语言描述依赖图,不要试图用多个 wac plug 拼,除非你想在 shell 里维护一团乱麻。
  • 版本不匹配:先用 wasm-tools component wit 检查,别猜。
复制全文 生成海报 Wasm Component Model WAC WebAssembly WASI 组件组合 WIT

推荐文章

程序员茄子在线接单