Open9

RustでWasm/WITのメモ

ktz_aliasktz_alias

インストールしたもの

  • 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ではなくローカルのレポジトリで済ませたいため、以下も追加でインストール

wasm-tools composedeprecatedと言われたのでwac-cliをインストールした。

ktz_aliasktz_alias

chikoski氏の一連のチュートリアルを実施するのがよさそう

他のチュートリアル

ktz_aliasktz_alias

warg-serverのインストール

2024-12-11現在

  1. インストール
    • cargo install warg-server
  2. 管理用環境変数の追加
    • export WARG_OPERATOR_KEY="ecdsa-p256:I+UlDo0HxyBBFeelhPPWmD+LnklOpqZDkrFP5VduASk="
  3. 起動
    • warg-server --content-dir <PATH> --namespace <NAMESPACE>
    • レポジトリのREADMEには記載されていないが、--namespaceを指定しないと、クライアントからパッケージの初期化で失敗する

wrag-cliのインストール

  1. インストール
    • cargo install warg-cli
  2. 設定の初期化
  3. キーの追加
    • warg key new
      • READMEでは、warg key new --registry 127.0.0.1:8090と書かれているが、コマンド実行でキーが見つからないと言われて失敗する
      • レジストリを指定しない場合、defaultがレジストラとして追加される
    • 設定ファイルに追記される

パッケージの公開

  • warg publish <WORLD名>:<PACKAGE名>
ktz_aliasktz_alias

怪文書

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から取得している。
    • コメントアウトすると存在しない扱いになる
ktz_aliasktz_alias

WITコンポーネントの合成

  • wkg wit build -d .
    • 事前に依存パッケージを追加しなくても良さそう
    • カレントディレクトリに*.wasmを出力
      • -o <PATH>で出力先を指定可能

現在、毎回認証を求められる

  • キーチェーンからクレデンシャル引っ張ってきてくれない

wkg publishで公開できない

Error: malformed component: component package version not found

になる

ktz_aliasktz_alias

cargo-componentのCargo.toml

https://github.com/bytecodealliance/cargo-component/blob/main/docs/design/registries.md#cargotoml-syntax

package.metadata.componentテーブル

  • packageサブテーブル - レジストラに公開する際にの名前 (必須)
    • 文字列かテーブル形式のいずれかで指定する
      • 文字列形式
        • "<PACKAGE>" = "<VERSION>"
      • テーブル形式 ([package.metadata.component.package])
        • package = "<PACKAGE>"
        • version = "<VERSION>"
    • ローカルパスの直接指定
      • テーブル形式のみ ([package.metadata.component.package])
        • id = { path = "<WITフォルダパス>" }
  • targetサブテーブル - WITworld情報
    • 文字列かテーブル形式のいずれかで指定する
      • 文字列形式
        • 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
          • 別のレジストラ(ローカルに立てたのとか)から取り込む際に指定するのかな。そこまで詳細には書かれてない
ktz_aliasktz_alias

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.tomlfeatures = ["bundled", "wasm32-wasi-vfs"]の指定が必要なことも注意。