Rust で cdylib/wasm を吐く crate を分割したら依存先の機能を呼べなくなり、なんとなく extern crate を明示してみたら can't find されて5分くらい悩んだメモ
だいじな事:
crate
を分割したら、お呼ばれされる側の Cargo.toml で[lib]
のcrate-type
が明示的にrlib
を吐かない定義になっていないか確認しよう!
期待動作する例
# crate aaa に依存される側の crate bbb の Cargo.toml # ☆ ↓ src/lib.rs ありの crate では書かなくても同義扱いなのだけど、今回のメモの本質的な部分なのであえて明示しました。 [lib] crate-type = [ "rlib" ]
# crate bbb をに依存する側の crate A の Cargo.toml [dependencies] bbb = { path = "../bbb" }
// crate bbb に依存する crate aaa の main.rs // ◎ Rust を edition = "2018" で使う場合は extern carate は不要です; あっても問題ないけど extern crate bbb; // ◎ use しなくてもシンボルへの完全なパスを書けば使えます use bbb::some_module::some_sub_module::awesome_feature; // ◎ crate bbb に分割した何かを使う的な模擬コード let my_hoge = awesome_feature::hoge();
5分くらい悩んだダメな例
# crate aaa に依存される側の crate bbb の Cargo.toml [lib] crate-type = [ "cdylib" ] # ☆ rlib 出力が無いと依存してくれる側の .rs から extern して密結合できないのです。うっかり
解説
分割前の crate が .wasm を吐くとか、 .so/.dll/.dylib 的なそれを吐くのがプロジェクト単位での出力の場合、 [lib]
で crate-type = [ "cdylib" ]
とか定義しているはずです。そのような aaa から bbb を分割する際に、 Cargo.tml の内容を aaa の複製を元に書き出し、 cdylib
しか出力しない crate bbb を定義してしまうと、 crate aaa から [dependencies]
で依存する事はできますが、rlib
が無い状態では rust のソースコードから extern
して密結合的に使う事はできません。 crate bbb が cdylib
を出力する定義では crate aaa のビルドでも .wasm あるいは .so/.dll/.dylib 的なそれはビルドされます。その出力「も」欲しい場合もあるかとは思いますが、今回は crate aaa を整理のために crate bbb と分割し、 crate aaa から crate bbb へ依存するのが目的のため rlib
出力を追加定義または rlib
出力のみに変更するのが期待動作する分割に必要です。