Bir kütüphane ve bir ikili ile pas paketi?


190

Hem yeniden kullanılabilir bir kitaplık (programın çoğu uygulandığı yerde) hem de onu kullanan bir yürütülebilir dosya içeren bir Rust paketi yapmak istiyorum.

Rust modül sisteminde herhangi bir anlambilimi karıştırmadım, dosyam Cargo.tomlneye benzemeli?

Yanıtlar:


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
Teşekkürler Doug, deneyeceğim! #! [Crate_name =] ve #! [Crate_type] ek açıklamaları isteğe bağlı mı?
Andrew Wagner

4
Cargo'yu kullandığınızda, bu seçenekler gereksizdir çünkü Cargo bunları derleyici bayrakları olarak geçirir. Çalıştırırsanız cargo build --verbose, rustckomut satırında görürsünüz .
Vladimir Matveev

33
Neden [[bin]]bir dizi tablo olduğunu biliyor musunuz ? Neden kullanmalı [[bin]]ve kullanmıyorsunuz [bin]? Bununla ilgili herhangi bir belge yok gibi görünüyor.
CMCDragonkai

40
@CMCDragonkai Bu toml formatı belirtimi [[x]] bir kez serisinin kaldırılması; yani. tek bir sandık birden fazla ikili dosya üretebilir, fakat sadece bir kütüphane (bu nedenle [lib] değil [lib]]). Birden çok bölme bölümünüz olabilir. (Katılıyorum, bu garip görünüyor, ancak toml her zaman tartışmalı bir seçim oldu).
Doug

1
İstediğim tek şey lib olduğunda ikili dosyayı derlemesini önlemenin bir yolu var mı? İkili, "ikili" adlı bir özellik aracılığıyla eklediğim ek bağımlılıklar vardır, bu özellik olmadan derlemeye çalıştığınızda, oluşturmak başarısız. Bin.rs'ın almaya çalıştığı sandıkları bulamadığından şikayet ediyor.
Person93

150

Ayrıca, ikili kaynakları src/binve diğer kaynaklarınızı da içine koyabilirsiniz src. İçeri bir örnek görebilirsiniz projemde . Herhangi bir değişiklik yapmanız gerekmez Cargo.tomlve her kaynak dosya aynı adlı bir ikili dosyaya derlenir.

Diğer yanıtlayıcının yapılandırması daha sonra:

$ 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));
}

Ve yürütün:

$ cargo run --bin mybin
I'm using the library: Ok(3)

Ayrıca, src/main.rsdefacto yürütülebilir olarak kullanılacak bir tane oluşturabilirsiniz . Ne yazık ki, bu cargo dockomutla çakışıyor :

Bir kitaplık ve bir ikili dosyanın aynı ada sahip olduğu bir paket belgelenemez. Birini yeniden adlandırmayı veya hedefi şu şekilde işaretlemeyi düşünündoc = false


13
pas yapılandırma konfigürasyon yaklaşımı ile iyi uyuyor! her ikisi de birlikte cevap verir ve büyük rahatlık ve esnekliğe sahip olursunuz.
uçan koyun

9
extern crate example;pas 2018'den itibaren gerekli değildir use example::really_complicated_code;, kapsamı adlandırmadan doğrudan işlevi yazabilir ve kullanabilirsiniz
sassman

47

Alternatif bir çözüm, her iki şeyi de tek bir pakete sıkıştırmaya çalışmak değildir. Dostça yürütülebilir bir dosyaya sahip biraz daha büyük projeler için, bir çalışma alanı kullanmak çok güzel buldum

İçinde bir kütüphane bulunan bir ikili proje yaratırız:

the-binary
├── Cargo.lock
├── Cargo.toml
├── mylibrary
│   ├── Cargo.toml
│   └── src
│       └── lib.rs
└── src
    └── main.rs

Cargo.toml

Bu, [workspace]anahtarı kullanır ve kütüphaneye bağlıdır:

[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)
}

Ve yürütün:

$ 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)

Bu şemanın iki büyük faydası vardır:

  1. İkili dosya artık yalnızca geçerli olan bağımlılıkları kullanabilir. Örneğin, kullanıcı deneyimini geliştirmek için komut satırı ayrıştırıcıları veya terminal biçimlendirmesi gibi birçok kasa ekleyebilirsiniz. Bunların hiçbiri kütüphaneye “bulaşmayacak”.

  2. Çalışma alanı, her bir bileşenin gereksiz yapılarını önler. cargo buildHem mylibraryve hem de the-binarydizinde çalışırsak , kitaplık iki kez oluşturulmaz - her iki proje arasında paylaşılır.


Bu çok daha iyi bir yol gibi görünüyor. Açıkçası sorunun sorulmasından bu yana yıllar geçti ancak insanlar hala büyük projeler düzenlemekle mücadele ediyorlar. Yukarıda seçilen cevaba göre bir çalışma alanı kullanmanın bir dezavantajı var mı?
Jspies

4
@ Başımın üstünde düşünebileceğim en büyük dezavantajı, çalışma alanlarıyla nasıl başa çıkacağını tam olarak bilmeyen bazı araçların olmasıdır. Bir çeşit "proje" konseptine sahip mevcut araçlarla etkileşime girerken garip bir noktadalar. Şahsen bir süreklilik yaklaşımı benimsiyorum: Her şeyle başlıyorum main.rs, daha sonra büyüdükçe modüllere ayrılıyorum, sonunda src/binbiraz daha büyük olduğunda bölündüm, sonra çekirdek mantığı ağır bir şekilde yeniden kullanmaya başladığımda bir çalışma alanına geçiyorum.
Shepmaster

teşekkürler bir spin vereceğim. şu anki projem, projenin bir parçası olarak geliştirilen ancak dışarıdan kullanılan birkaç kütüphaneye sahip.
Jspies

İyi inşa eder ve çalışır, ancak cargo testlib.rs'deki birim testlerini göz ardı ediyor gibi görünüyor
Stein

3
@Stein istediğini düşünüyorumcargo test --all
Shepmaster

18

lib.rsVe main.rsKaynaklar klasörünü bir araya getirebilirsiniz . Çatışma yok ve kargo her iki şeyi de inşa edecek.

Belgesel çatışmasını çözmek için aşağıdakilere ekleyin Cargo.toml:

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

3
" Ek olarak, sadece defacto yürütülebilir dosyası olarak kullanılacak bir src / main.rs oluşturabilirsiniz ". diğer cevapta, değil mi? Ve belge çatışması kabul edilen cevapla çözüldü, değil mi? Bunun neden benzersiz olduğunu göstermek için cevabınızı netleştirmeniz gerekebilir. Bunların üzerine inşa etmek için diğer cevaplara atıfta bulunmak uygundur.
Shepmaster
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.