¿Paquete Rust con una biblioteca y un binario?

Me gustaría crear un paquete Rust que contenga tanto una biblioteca reutilizable (donde se implementa la mayor parte del progtwig) como un ejecutable que la use.

Suponiendo que no haya confundido ninguna semántica en el sistema del módulo Rust, ¿cómo debería ser mi archivo 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 "] [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; use mylib::test; pub fn main() { test(); } 

También puede simplemente poner fonts binarias en src/bin y el rest de sus fonts en src . Puedes ver un ejemplo en mi proyecto . No necesita modificar su Cargo.toml , y cada archivo fuente se comstackrá en un binario del mismo nombre.

La configuración de la otra respuesta se reemplaza por:

 $ tree . ├── Cargo.toml └── src  ├── bin  │  └── mybin.rs  └── lib.rs 

Cargo.toml

 [package] name = "example" version = "0.0.1" authors = ["An Devloper "] 

src / lib.rs

 use std::error::Error; pub fn really_complicated_code(a: u8, b: u8) -> Result> { Ok(a + b) } 

src / bin / mybin.rs

 extern crate example; fn main() { println!("I'm using the library: {:?}", example::really_complicated_code(1, 2)); } 

Y ejecutarlo:

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

Además, puede crear un src/main.rs que se utilizará como el ejecutable de facto. Desafortunadamente, esto entra en conflicto con el comando del cargo doc :

No se puede documentar un paquete donde una biblioteca y un binario tienen el mismo nombre. Considere renombrar uno o marcar el objective como doc = false

Puede poner lib.rs y main.rs juntos en la carpeta de fonts. No hay conflicto y la carga construirá ambas cosas.

Para resolver el conflicto de documentación agregue a su Cargo.toml :

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

Una solución alternativa es no intentar meter ambas cosas en un solo paquete. Para proyectos un poco más grandes con un ejecutable amigable, he encontrado que es muy agradable usar un espacio de trabajo

Creamos un proyecto binario que incluye una biblioteca dentro de él:

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

Cargo.toml

Esto usa la tecla [workspace] y depende de la biblioteca:

 [package] name = "the-binary" version = "0.1.0" authors = ["An Devloper "] [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> { Ok(a + b) } 

Y ejecutarlo:

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

Hay dos grandes beneficios para este esquema:

  1. El binario ahora puede usar dependencias que solo se aplican a él. Por ejemplo, puede incluir muchas cajas para mejorar la experiencia del usuario, como analizadores de línea de comando o formato de terminal. Ninguno de estos “infectará” la biblioteca.

  2. El espacio de trabajo evita construcciones redundantes de cada componente. Si ejecutamos cargo build tanto en el mylibrary como en the-binary , la biblioteca no se generará ambas veces, sino que se comparte entre ambos proyectos.