RustでWasm/WITのメモ
WIT とは
WIT (Webassembly interface type)
はWebAssembly Component Model
として定義されている
WITの仕様
Rustでwasm componentを扱う際の注意事項
-
Nightly
版のRust
を使用するとcargo component build
でこける。-
Stable
版であれば問題ない
-
インストールしたもの
- cargo component
cargo install cargo-component
- wasm-tools
cargo install wasm-tools
- wit-tools
cargo insdtall wit
-
2024-12-15
時点でwit
コマンドのソースが存在していない- 廃止されたか?
- ビルドに関しては
wkg wit build -d .
で行えた
wa.dev
ではなくローカルのレポジトリで済ませたいため、以下も追加でインストール
- warg -
warg protocol
のリファレンス実装 (https://github.com/bytecodealliance/registry)cargo install warg-cli
cargo install warg-server
wasm-tools compose
はdeprecated
と言われたのでwac-cli
をインストールした。
-
cargo install wac-cli
- https://github.com/bytecodealliance/wac
-
wac plug <ベースWASM> --plug <インポートするWASM> -o <出力WASMパス>
- 使い方 - https://component-model.bytecodealliance.org/tutorial.html#composing-the-calculator
- ケバブスタイルでも合成してくれる
-
wasm-tools compose
は-
を_
に置き換える必要があった
-
chikoski
氏の一連のチュートリアルを実施するのがよさそう
- part 1 Hello world https://zenn.dev/chikoski/articles/wasm-component-hello-world
- part 2 Wasm component (library) https://zenn.dev/chikoski/articles/wasm-component-hello-world-warg
- part 3 Wasm component (package) https://zenn.dev/chikoski/articles/wasm-component-hello-world-wit-package
他のチュートリアル
- Wasm Component Model By Example
warg-serverのインストール
2024-12-11現在
- インストール
cargo install warg-server
- 管理用環境変数の追加
export WARG_OPERATOR_KEY="ecdsa-p256:I+UlDo0HxyBBFeelhPPWmD+LnklOpqZDkrFP5VduASk="
- 起動
-
warg-server --content-dir <PATH>
--namespace <NAMESPACE> - レポジトリのREADMEには記載されていないが、
--namespace
を指定しないと、クライアントからパッケージの初期化で失敗する
-
wrag-cliのインストール
- インストール
cargo install warg-cli
- 設定の初期化
- warg config --registry http://127.0.0.1:8090
- キーの追加
- warg key new
- READMEでは、
warg key new --registry 127.0.0.1:8090
と書かれているが、コマンド実行でキーが見つからないと言われて失敗する - レジストリを指定しない場合、
default
がレジストラとして追加される
- READMEでは、
- 設定ファイルに追記される
- warg key new
パッケージの公開
warg publish <WORLD名>:<PACKAGE名>
怪文書
references/cargo-component/src/commands/add.rs
AddCommand::resolve_version(...)
...
references/cargo-component/crates/core/src/registry.rs
Registry::resolve(...)
references/cargo-component/crates/core/src/registry.rs
load_package(...)
references/cargo-component/crates/core/src/registry.rs
CachingClient<FileCache>::list_all_versions()
~/.cargo/registry/src/index.crates.io-6f17d22bba15001f/wasm-pkg-client-0.8.3/src/lib.rs
Client::list_all_versions(pkg)
Client::resolve_source(pkg)
/.well-known/wasm-pkg/registry.json
からパッケージの取得を試みる
- InnerClientの構築の際
- FileSystemClient::new_with_config
- ~/.cargo/registry/src/index.crates.io-6f17d22bba15001f/wasm-pkg-client-0.8.3/src/warg/mod.rs
- FileSystemClientから
api::Client::well_known_config()
でリクエスト
デフォのバックエンドがNoneだった
backend_configsも空 -> ociになる
グローバル設定
- ~/.config/wasm-pkg/config.toml or ~/$XDG_CONFIG_HOME/wasm-pkg/config.toml
- パッケージリストが指定されていれば、
-r
の指定も、wit.toml
での指定なくても取得する
- パッケージリストが指定されていれば、
レジストリの設定情報はmetadataかregistry_configsのいずれかから取得する
preferred_protocol には local
は指定できない
registry_configsはローカル環境の設定目的(default_backend = local
)
registry cache: ~/Library/Caches/warg/registries/<LABEL> (MacOS)
content cache: ~/Library/Caches/warg/content
namespace cache: ~/Library/Caches/warg/namespaces
キャッシュをクリアするとwargでアクセスできなくなる?
リリース版のcorgo-componentはwarg-v2のリクエストを投げる -> 失敗してる
デバッグビルドするとv1のリクエストを投げている
~/.cargo/registry/src/index.crates.io-6f17d22bba15001f/wasm-pkg-client-0.8.3/src/warg/loader.rs
WargBackend::list_all_versions
~/.cargo/registry/src/index.crates.io-6f17d22bba15001f/warg-client-0.9.1/src/lib.rs
Client::update_checkpoints(...)
Client::update_packages_and_return_federated_packages(...)
- ここでwarg-serverにリクエストを飛ばしてる
- リクエスト一覧
- ~/.cargo/registry/src/index.crates.io-6f17d22bba15001f/warg-api-0.9.1/src/v1/paths.rs
メタデータは内部的にcargo manifestコマンドで取得している
- 親プロジェクトのCargo.tomlから取得している。
- コメントアウトすると存在しない扱いになる
WITコンポーネントの合成
-
wkg wit build -d .
- 事前に依存パッケージを追加しなくても良さそう
- カレントディレクトリに
*.wasm
を出力-
-o <PATH>
で出力先を指定可能
-
現在、毎回認証を求められる
- キーチェーンからクレデンシャル引っ張ってきてくれない
wkg publish
で公開できない
Error: malformed component: component package version not found
になる
cargo-componentのCargo.toml
package.metadata.component
テーブル
-
package
サブテーブル - レジストラに公開する際にの名前 (必須)- 文字列かテーブル形式のいずれかで指定する
- 文字列形式
- "<PACKAGE>" = "<VERSION>"
- テーブル形式 (
[package.metadata.component.package]
)package = "<PACKAGE>"
version = "<VERSION>"
- 文字列形式
- ローカルパスの直接指定
- テーブル形式のみ (
[package.metadata.component.package]
)id = { path = "<WITフォルダパス>" }
- テーブル形式のみ (
- 文字列かテーブル形式のいずれかで指定する
-
target
サブテーブル -WIT
のworld
情報- 文字列かテーブル形式のいずれかで指定する
- 文字列形式
package = "<PACKAGE>[/<WORLD>]@<VERSION>"
- テーブル形式 (
[package.metadata.component.target]
)-
package = "<PACKAGE>"
(必須) -
version = "<VERSION
(必須) -
world = "<WORLD"
-
wit
ファイルのパスなのか、wit
フォルダが置かれたパスなのかの説明は一切なし!(怒)
-
- `registry = "<REG-LABEL>"
- 情報なし!
- 公開先か?
-
- 文字列形式
- ローカルターゲットの直接指定
- テーブル形式のみ (
[package.metadata.component.target]
)-
path = "<WITファイル名>"
(必須) world = "<WITフォルダパス"
-
- テーブル形式のみ (
- ローカルターゲットの依存指定
- テーブル形式のみ (
[package.metadata.component.target.dependencies]
)- "<PACKAGE>" = "<VERSION>"
- テーブル形式のみ (
- 文字列かテーブル形式のいずれかで指定する
-
registries
サブテーブル - たぶんdependency
をどこからダウンロードするかの指定 (複数指定可能- テーブル形式のみ (
[package.metadata.component.registories]
)- `<REG-LABEL> = "<URL>"
- テーブル形式のみ (
-
dependencies
サブテーブル - 自身のコンポーネントが依存する別のコンポーネントを列挙する- 以下のいずれかで指定する
-
"<PACKAGE>" = "<VERSION>
" - `"<PACKAGE>" = { package = "<PACKAGE>", version = "<VERSION>", registry = <REG-LABEL>}
-
registry
はオプションで、規定値はdefault
- 別のレジストラ(ローカルに立てたのとか)から取り込む際に指定するのかな。そこまで詳細には書かれてない
-
-
- 以下のいずれかで指定する
rusqliteのWASMコンポーネントとしてのビルド
以下の環境変数をセットした上で
export WASI_SDK_PATH="/usr/local/opt/wasi-sdk/macos/"
export WASI_SYSROOT="${WASI_SDK_PATH}/share/wasi-sysroot"
export CC="${WASI_SDK_PATH}/bin/clang --sysroot=${WASI_SYSROOT}"
export AR="${WASI_SDK_PATH}/bin/llvm-ar"
export CC_wasm32_wasi="${CC}"
export CARGO_TARGET_WASM32_WASI_LINKER="${WASI_SDK_PATH}/bin/clang"
export CARGO_CFG_TARGET_ENV="wasm32-wasi"
export CLANG_LIB_WASI="${WASI_SDK_PATH}/lib/clang/18/lib/wasi"
export LIBSQLITE3_FLAGS="-DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_SHARED_CACHE -D_LARGEFILE64_SOURCE"
export RUSTFLAGS="-Clink-arg=-L$CLANG_LIB_WASI -Clink-arg=-lclang_rt.builtins-wasm32 -Clink-arg=--export-table -Clink-arg=--export=malloc -Clink-arg=--export=free"
cargo component build
でビルドは通った。
Ref: https://github.com/rusqlite/rusqlite/issues/1408
wasm
としてビルドする場合、Cargo.toml
にfeatures = ["bundled", "wasm32-wasi-vfs"]
の指定が必要なことも注意。
wasi_snapshot_preview1.wasmの配布先
Ref: https://zenn.dev/chikoski/articles/wasm-component-compatiblity-issue