ฉันต้องการสร้างแพคเกจ Rust ที่มีทั้งไลบรารีที่สามารถใช้ซ้ำได้
สมมติว่าฉันไม่ได้สับสนความหมายใด ๆ ในระบบโมดูลสนิมCargo.toml
ไฟล์ของฉันควรมีลักษณะอย่างไร
ฉันต้องการสร้างแพคเกจ 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
ที่จะใช้เป็นปฏิบัติการ defacto น่าเสียดายที่สิ่งนี้ขัดแย้งกับcargo doc
คำสั่ง:
ไม่สามารถจัดทำเอกสารแพคเกจที่ห้องสมุดและไบนารีมีชื่อเดียวกัน พิจารณาเปลี่ยนชื่อหนึ่งหรือทำเครื่องหมายเป้าหมายเป็น
doc = false
extern crate example;
ไม่จำเป็นต้องใช้เป็นสนิม 2018 คุณสามารถเขียนuse example::really_complicated_code;
และใช้งานฟังก์ชั่นได้โดยตรงโดยไม่ต้องตั้งชื่อขอบเขต
ทางเลือกอื่นคือไม่พยายามยัดทั้งสองอย่างไว้ในแพ็คเกจเดียว สำหรับโครงการขนาดใหญ่ขึ้นเล็กน้อยที่มีการปฏิบัติการที่เป็นมิตรฉันพบว่ามันดีมากที่จะใช้พื้นที่ทำงาน
เราสร้างโปรเจ็กต์ไบนารีที่มีไลบรารี่อยู่ภายใน:
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)
มีประโยชน์ใหญ่สองประการสำหรับโครงการนี้:
ตอนนี้ไบนารีสามารถใช้การอ้างอิงที่ใช้กับมันเท่านั้น ตัวอย่างเช่นคุณสามารถรวมลังจำนวนมากเพื่อปรับปรุงประสบการณ์ผู้ใช้เช่นตัวแยกวิเคราะห์บรรทัดคำสั่งหรือการจัดรูปแบบเทอร์มินัล สิ่งเหล่านี้จะ "ไม่ติด" ในห้องสมุด
พื้นที่ทำงานป้องกันการสร้างซ้ำซ้อนของแต่ละองค์ประกอบ หากเราทำงานcargo build
ทั้งในmylibrary
และthe-binary
ไดเรกทอรีห้องสมุดจะไม่ถูกสร้างขึ้นทั้งสองครั้ง - มันถูกใช้ร่วมกันระหว่างทั้งสองโครงการ
main.rs
นั้นแล้วแบ่งมันเป็นโมดูลเมื่อมันใหญ่ขึ้นในที่สุดก็แยกออกไปsrc/bin
เมื่อมันใหญ่ขึ้นเล็กน้อยจากนั้นย้ายไปยังพื้นที่ทำงานเมื่อฉันเริ่มใช้ตรรกะหลักอย่างหนัก
cargo test
ดูเหมือนว่าจะไม่สนใจการทดสอบหน่วยใน lib.rs
cargo test --all
คุณสามารถใส่lib.rs
และmain.rs
ไปยังโฟลเดอร์แหล่งที่มาด้วยกัน ไม่มีความขัดแย้งและสินค้าจะสร้างทั้งสองอย่าง
หากต้องการแก้ไขความขัดแย้งของเอกสารให้เพิ่มในCargo.toml
:
[[bin]]
name = "main"
doc = false