だいじな事:
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 出力のみに変更するのが期待動作する分割に必要です。