라이브러리와 바이너리가 모두있는 녹 패키지?


190

재사용 가능한 라이브러리 (대부분의 프로그램이 구현되는 곳)와 그것을 사용하는 실행 파일이 모두 들어있는 Rust 패키지를 만들고 싶습니다.

Rust 모듈 시스템에서 시맨틱을 혼동하지 않았다고 가정하면 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
고마워 Doug, 나는 그것을 시도 할 것이다! #! [crate_name =] 및 #! [crate_type] 주석은 선택 사항입니까?
앤드류 바그너

4
카고를 사용하는 경우 카고가 컴파일러 플래그로 옵션을 전달하므로 이러한 옵션은 필요하지 않습니다. 을 실행 cargo build --verbose하면 rustc명령 행에 표시됩니다.
블라디미르 Matveev

33
[[bin]]테이블 배열 인지 아십니까 ? 왜 사용 [[bin]]하지 [bin]않습니까? 이것에 대한 문서가없는 것 같습니다.
CMCDragonkai

40
@CMCDragonkai 그것은 toml 형식 스펙이다 [[x]]는 일단 deserialized 된 배열이다; 즉. 단일 크레이트는 여러 바이너리를 생성 할 수 있지만 하나의 라이브러리 만 생성 할 수 있습니다 (따라서 [lib]가 아닌 [lib]). 여러 구간 섹션을 가질 수 있습니다. (나는 이것이 이상하게 보이지만, toml은 항상 논란의 여지가있는 선택이었다)에 동의한다.
Doug

1
내가 원하는 모든 것이 lib 일 때 바이너리를 컴파일하지 못하게하는 방법이 있습니까? 바이너리에는 "binary"라는 기능을 통해 추가되는 추가 종속성이 있으며 해당 기능없이 컴파일하려고하면 빌드에 실패합니다. bin.rs가 가져 오려는 상자를 찾을 수 없다고 불평합니다.
Person93

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; 범위를 명명하지 않고 함수를 하고 사용할
sassman

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. 작업 공간은 각 구성 요소의 중복 빌드를 방지합니다. and 디렉토리 cargo build에서 모두 실행 하면 라이브러리가 두 번 빌드되지 않으며 두 프로젝트간에 공유됩니다.mylibrarythe-binary


이것은 훨씬 더 좋은 방법으로 보입니다. 분명히 질문이 제기 된 지 수년이 지났지 만 사람들은 여전히 ​​대규모 프로젝트를 조직하는 데 어려움을 겪고 있습니다. 위의 선택된 답변과 작업 공간을 사용하는 데 단점이 있습니까?
Jspies

4
@Jespies 내가 생각할 수있는 가장 큰 단점은 작업 공간을 처리하는 방법을 완전히 알지 못하는 도구가 있다는 것입니다. 그들은 일종의 "프로젝트"개념을 가진 기존 도구와 상호 작용할 때 이상한 점에 있습니다. 나는 개인적으로 연속적인 접근 방식을 취하는 경향이 있습니다.에서 모든 것부터 시작하여 main.rs점점 커짐에 따라 모듈로 나눕니다. 마침내 src/bin조금 더 커졌을 때로 분할 된 다음 핵심 로직을 많이 재사용하기 시작할 때 작업 공간으로 이동합니다.
Shepmaster

감사합니다. 현재 프로젝트에는 프로젝트의 일부로 개발되었지만 외부에서도 사용되는 두 개의 라이브러리가 있습니다.
Jspies

잘 빌드되고 실행되지만 cargo testlib.rs의 단위 테스트를 무시하는 것 같습니다
Stein

3
@Stein 나는 당신이 원하는 것 같아요cargo test --all
Shepmaster

18

lib.rsmain.rs소스 폴더를 함께 넣을 수 있습니다 . 충돌이 없으며 화물이 두 가지를 모두 쌓을 것입니다.

documentaion 충돌을 해결하려면 다음을 추가하십시오 Cargo.toml.

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

3
" 추가로, 사실상 실행 파일로 사용될 src / main.rs를 만들 수 있습니다 ". 다른 대답으로는 안돼? 그리고 문서 충돌은 받아 들여진 대답으로 해결됩니다. 이것이 왜 독특한 지 보여주기 위해 답을 명확히해야 할 수도 있습니다. 다른 답변을 참조하여 작성해도 좋습니다.
Shepmaster
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.