再利用可能なライブラリ(ほとんどのプログラムが実装されている)と、それを使用する実行可能ファイルの両方を含むRustパッケージを作成したいと思います。
Rustモジュールシステムのセマンティクスを混同していないとすると、Cargo.toml
ファイルはどのようになりますか?
再利用可能なライブラリ(ほとんどのプログラムが実装されている)と、それを使用する実行可能ファイルの両方を含むRustパッケージを作成したいと思います。
Rustモジュールシステムのセマンティクスを混同していないとすると、Cargo.toml
ファイルはどのようになりますか?
回答:
Tok:tmp doug$ du -a
8 ./Cargo.toml
8 ./src/bin.rs
8 ./src/lib.rs
16 ./src
Cargo.toml:
[package]
name = "mything"
version = "0.0.1"
authors = ["me <me@gmail.com>"]
[lib]
name = "mylib"
path = "src/lib.rs"
[[bin]]
name = "mybin"
path = "src/bin.rs"
src / lib.rs:
pub fn test() {
println!("Test");
}
src / bin.rs:
extern crate mylib; // not needed since Rust edition 2018
use mylib::test;
pub fn main() {
test();
}
cargo build --verbose
すると、rustc
コマンドラインに表示されます。
[[bin]]
テーブルの配列なのか知っていますか?なぜ使用[[bin]]
していませんか[bin]
?これに関するドキュメントはないようです。
また、バイナリソースをsrc/bin
に、残りのソースをに配置することもできますsrc
。私のプロジェクトの例を見ることができます。を変更する必要はありません。Cargo.toml
各ソースファイルは同じ名前のバイナリにコンパイルされます。
次に、他の回答の構成を次のように置き換えます。
$ tree
.
├── Cargo.toml
└── src
├── bin
│ └── mybin.rs
└── lib.rs
Cargo.toml
[package]
name = "example"
version = "0.0.1"
authors = ["An Devloper <an.devloper@example.com>"]
src / lib.rs
use std::error::Error;
pub fn really_complicated_code(a: u8, b: u8) -> Result<u8, Box<Error>> {
Ok(a + b)
}
src / bin / mybin.rs
extern crate example; // Optional in Rust 2018
fn main() {
println!("I'm using the library: {:?}", example::really_complicated_code(1, 2));
}
そしてそれを実行します:
$ cargo run --bin mybin
I'm using the library: Ok(3)
さらに、src/main.rs
事実上の実行可能ファイルとして使用されるを作成することもできます。残念ながら、これはcargo doc
次のコマンドと競合します。
ライブラリとバイナリが同じ名前のパッケージをドキュメント化することはできません。名前を変更するか、ターゲットを
doc = false
extern crate example;
rust 2018の時点では必要ありません。use example::really_complicated_code;
スコープに名前を付けなくても、関数を直接記述して使用できます
別の解決策は、両方を1つのパッケージに詰め込もうとしないことです。やや大規模なプロジェクトでフレンドリーな実行可能ファイルがある場合、ワークスペースを使用すると非常に便利です
内部にライブラリを含むバイナリプロジェクトを作成します。
the-binary
├── Cargo.lock
├── Cargo.toml
├── mylibrary
│ ├── Cargo.toml
│ └── src
│ └── lib.rs
└── src
└── main.rs
Cargo.toml
これは[workspace]
キーを使用し、ライブラリに依存します:
[package]
name = "the-binary"
version = "0.1.0"
authors = ["An Devloper <an.devloper@example.com>"]
[workspace]
[dependencies]
mylibrary = { path = "mylibrary" }
src / main.rs
extern crate mylibrary;
fn main() {
println!("I'm using the library: {:?}", mylibrary::really_complicated_code(1, 2));
}
mylibrary / src / lib.rs
use std::error::Error;
pub fn really_complicated_code(a: u8, b: u8) -> Result<u8, Box<Error>> {
Ok(a + b)
}
そしてそれを実行します:
$ cargo run
Compiling mylibrary v0.1.0 (file:///private/tmp/the-binary/mylibrary)
Compiling the-binary v0.1.0 (file:///private/tmp/the-binary)
Finished dev [unoptimized + debuginfo] target(s) in 0.73 secs
Running `target/debug/the-binary`
I'm using the library: Ok(3)
このスキームには2つの大きな利点があります。
バイナリは、それにのみ適用される依存関係を使用できるようになりました。たとえば、コマンドラインパーサーやターミナルのフォーマットなど、ユーザーエクスペリエンスを向上させるために多数のクレートを含めることができます。これらはどれもライブラリに「感染」しません。
ワークスペースは、各コンポーネントの冗長なビルドを防ぎます。とディレクトリのcargo build
両方で実行する場合、ライブラリは両方ともビルドされず、両方のプロジェクト間で共有されます。mylibrary
the-binary
main.rs
それが大きくなるにつれてモジュールに分割し、最後にsrc/bin
少しだけ大きくなるように分割し、コアロジックを大きく再利用し始めたらワークスペースに移動します。
cargo test
、lib.rsの単体テストを無視するようです
cargo test --all
あなたは置くことができますlib.rs
し、main.rs
ソースが一緒にフォルダに移動します。衝突はなく、貨物は両方のものを構築します。
documentaionの競合を解決するには、Cargo.toml
以下を追加します。
[[bin]]
name = "main"
doc = false