पुस्तकालय और बाइनरी दोनों के साथ जंग पैकेज?


190

मैं एक रस्ट पैकेज बनाना चाहता हूं जिसमें एक पुन: प्रयोज्य पुस्तकालय (जहां अधिकांश कार्यक्रम लागू किया गया है) दोनों शामिल हैं, और एक निष्पादन योग्य भी है जो इसका उपयोग करता है।

यह मानते हुए कि मैंने रस्ट मॉड्यूल सिस्टम में किसी भी शब्दार्थ को भ्रमित नहीं किया है, मेरी Cargo.tomlफ़ाइल कैसी दिखनी चाहिए ?

जवाबों:


205
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();
}

2
धन्यवाद डौग, मैं यह कोशिश करूँगा! क्या # [! Crate_name =] और #! [Crate_type] एनोटेशन वैकल्पिक हैं?
एंड्रयू वैगनर

4
जब आप कार्गो का उपयोग करते हैं, तो ये विकल्प अनावश्यक होते हैं क्योंकि कार्गो उन्हें संकलक झंडे के रूप में पास करता है। यदि आप चलते हैं cargo build --verbose, तो आप उन्हें rustcकमांड लाइन में देखेंगे ।
व्लादिमीर मतवेव

33
क्या आप जानते हैं कि [[bin]]सारणियों की एक सरणी क्यों है? क्यों इस्तेमाल करें [[bin]]और क्या नहीं [bin]? इस पर कोई दस्तावेज नहीं लगता है।
CMCDragonkai

40
@CMCDragonkai यह एक toml प्रारूप विनिर्देश है [[x]] एक सरणी है जो एक बार deserialized है; अर्थात। एक एकल टोकरा कई बायनेरिज़ का उत्पादन कर सकता है, लेकिन केवल एक पुस्तकालय (इस प्रकार [लिबास], [[लिबास]] नहीं)। आपके पास कई बिन अनुभाग हो सकते हैं। (मैं मानता हूं, यह अजीब लग रहा है, लेकिन शराब हमेशा एक विवादास्पद विकल्प था)।
डग

1
क्या बाइनरी को संकलित करने से रोकने का एक तरीका है जब मैं चाहता हूं कि यह लीब है? बाइनरी में अतिरिक्त निर्भरताएं हैं जो मैं "बाइनरी" नामक एक सुविधा के माध्यम से जोड़ता हूं, जब मैं इसे उस सुविधा के बिना संकलित करने का प्रयास करता हूं, तो यह निर्माण करने में विफल रहता है। यह शिकायत करता है कि यह उन बक्से को नहीं खोज सकता है जो बिन आयात करने की कोशिश कर रहे हैं।
पर्सन93

150

आप केवल बाइनरी स्रोतों को 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


13
जंग के सम्मेलन-ओवर-कॉन्फ़िगरेशन दृष्टिकोण के साथ अच्छी तरह से फिट बैठता है! दोनों एक साथ उत्तर देते हैं और आपके पास कुछ महान सुविधा और लचीलापन है।
भेड़

9
extern crate example;2018 जंग के रूप में आवश्यक नहीं है, आप सीधे use example::really_complicated_code;गुंजाइश का नाम लिए बिना फ़ंक्शन का उपयोग कर सकते हैं और उपयोग कर सकते हैं
ससमान

47

एक वैकल्पिक समाधान वास्तव में दोनों चीजों को एक पैकेज में रटना करने की कोशिश नहीं करना है। एक दोस्ताना निष्पादन के साथ थोड़ी बड़ी परियोजनाओं के लिए, मैंने कार्यक्षेत्र का उपयोग करना बहुत अच्छा पाया है

हम एक बाइनरी प्रोजेक्ट बनाते हैं जिसमें इसके अंदर एक लाइब्रेरी शामिल है:

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)

इस योजना के दो बड़े लाभ हैं:

  1. बाइनरी अब निर्भरता का उपयोग कर सकती है जो केवल उस पर लागू होती है। उदाहरण के लिए, आप उपयोगकर्ता अनुभव को बेहतर बनाने के लिए बहुत सारे बक्से शामिल कर सकते हैं, जैसे कि कमांड लाइन पार्सर या टर्मिनल फॉर्मेटिंग। इनमें से कोई भी पुस्तकालय को "संक्रमित" नहीं करेगा।

  2. कार्यक्षेत्र प्रत्येक घटक के निरर्थक निर्माण को रोकता है। यदि हम निर्देशिका और निर्देशिका cargo buildदोनों में चलते हैं , तो पुस्तकालय दोनों बार नहीं बनाया जाएगा - यह दोनों परियोजनाओं के बीच साझा किया जाता है।mylibrarythe-binary


यह जाने के लिए एक बेहतर तरीका है। जाहिर है कि यह सवाल पूछे जाने के वर्षों से है लेकिन लोग अभी भी बड़ी परियोजनाओं के आयोजन के साथ संघर्ष करते हैं। क्या कार्यक्षेत्र का उपयोग करने के लिए एक नकारात्मक पहलू है बनाम ऊपर दिए गए चयनित उत्तर?
जेपीस

4
@ सबसे बड़ा नकारात्मक पहलू यह है कि मैं अपने सिर के ऊपर से सोच सकता हूं कि कुछ उपकरण हैं जो पूरी तरह से नहीं जानते हैं कि कार्यक्षेत्र से कैसे निपटना है। वे मौजूदा उपकरण के साथ बातचीत करते समय एक अजीब जगह की तरह होते हैं जिसमें कुछ प्रकार की "परियोजना" अवधारणा होती है। मैं व्यक्तिगत रूप से एक सातत्य दृष्टिकोण अपनाने की कोशिश करता हूं: मैं सब कुछ के साथ शुरू करता हूं main.rs, फिर इसे मॉड्यूल में तोड़ता हूं क्योंकि यह बड़ा हो जाता है, अंत में src/binजब यह सिर्फ थोड़ा बड़ा होता है तब विभाजन होता है, जब मैं मुख्य तर्क का पुन: उपयोग करना शुरू कर देता हूं तो एक कार्यक्षेत्र में चला जाता हूं।
शीपस्टर

धन्यवाद मैं इसे एक स्पिन दूंगा। मेरी वर्तमान परियोजना में कुछ ऐसे परिवाद हैं जो परियोजना के हिस्से के रूप में विकसित किए गए हैं लेकिन बाहरी रूप से भी उपयोग किए जाते हैं।
जापियों

यह बनाता है और ठीक चलता है, लेकिन cargo testलगता है कि यूनिट परीक्षण को lib.rs में नजरअंदाज कर दिया गया है
स्टीन

3
@ सचिन मुझे लगता है कि आप चाहते हैंcargo test --all
Shepmaster

18

आप एक साथ फ़ोल्डर में lib.rsऔर main.rsस्रोतों को रख सकते हैं। कोई संघर्ष नहीं है और कार्गो दोनों चीजों का निर्माण करेगा।

डॉक्यूमेंटेशन संघर्ष को हल करने के लिए अपने को जोड़ें Cargo.toml:

[[bin]]
name = "main"
doc = false

3
यह " इसके अतिरिक्त, आप केवल एक src / main.rs बना सकते हैं जो कि डिफैक्टो निष्पादन योग्य के रूप में उपयोग किया जाएगा " द्वारा कवर किया जाएगा । दूसरे जवाब में, नहीं? और प्रलेखन संघर्ष को स्वीकार किए गए उत्तर द्वारा हल किया जाता है, है ना? आपको यह दिखाने के लिए अपने उत्तर को स्पष्ट करने की आवश्यकता हो सकती है कि यह अद्वितीय क्यों है। उन पर निर्माण करने के लिए अन्य उत्तरों का संदर्भ देना ठीक है।
शेमपस्टर
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.