• 作成:
  • 更新:

Nix flakesでwasmtimeを使う時にwasmtime/conf.hを追加でインストールする方法

問題

wasmtimeとC FFIで連携するHaskellプログラムが以下のエラーでcabal buildに失敗する。

error: 次のファイルから読み込み:  Wasi.hsc:5:
/nix/store/yk4x6g0g36h5bvczrq9jvmbsr5g927di-wasmtime-29.0.1-dev/include/wasi.h:12:10: 致命的エラー: wasmtime/conf.h: No such file or directory
   12 | #include <wasmtime/conf.h>
      |          ^~~~~~~~~~~~~~~~~
コンパイルを停止しました。

Error: [Cabal-7125]

cabalファイルにextra-libraries: wasmtimeと書いてあっても失敗する。

wasmtime自体はNix flakesでインストールしている。 wasmtimeコマンド自体はちゃんと動く。そもそもwasi.hはwasmtimeパッケージのファイルである。

実際にwasmtime/conf.hヘッダーファイルは存在していない。

原因

調べてみたところ、 C APIのヘッダーファイルはcargoでビルドしたあとにcmakeでビルドするシステムになっているらしい。

not all headers are installed for C API · Issue #9382 · bytecodealliance/wasmtime

なんでそんなことになっているのかはよくわからない。 cargoの制限の都合とかですかね…?

それはさておき、追加の手順が必要ならば、追加の手順を追加するだけですね。

解決

Nix flakesにはpostInstallとoverlayの機能があるので、追加のインストール手順を渡してやれば良さそうだ。

元々のpostInstallをnix replで確認する。

nix-repl> :p pkgs.wasmtime.postInstall
:p pkgs.wasmtime.postInstall
# move libs from out to dev
install -d -m 0755 $dev/lib
install -m 0644 ${!outputLib}/lib/* $dev/lib
rm -r ${!outputLib}/lib

install -d -m0755 $dev/include/wasmtime
install -m0644 $src/crates/c-api/include/*.h $dev/include
install -m0644 $src/crates/c-api/include/wasmtime/*.h $dev/include/wasmtime

これを元にoverlaysにoverlayを追加して、 postInstallに追加のインストール手順を追加する。

(self: super: {
  wasmtime = super.wasmtime.overrideAttrs (oldAttrs: {
    postInstall = ''
      ${oldAttrs.postInstall or ""}
      cmake -S crates/c-api -B target/c-api --install-prefix "$(pwd)/artifacts"
      cmake --build target/c-api
      cmake --install target/c-api
      install -m0644 $(pwd)/artifacts/include/wasmtime/conf.h $dev/include/wasmtime
    '';
  });
})

少し注意するポイントは$srcなどにはビルドが終わってからは簡単に書き込めないこと。なのでインストール元のディレクトリは$srcからではなく$(pwd)から辿る必要がある。

問題解決手順自体は大したものではなかったが、そもそもoverlayを追加する場所を間違えて追加ビルドが走らなかったりして迷ってしまった。まだ私はNixに習熟していないと感じる。

追加形式である必要はないかも

oldAttrs.postInstallに追加する形式で書いたが、これを除いてもインストールコマンドは走った。追加形式である必要はないのかもしれない。