이 시리즈는 Rust 공식문서를 통해 공부한 흔적임을 밝힙니다.
우리는 바이너리 크레이트와 라이브러리 크레이트를 포함하는 패키지를 다뤄 보았다.
그런데 패키지가 더 커지게 되면 이것을 여러 개의 패키지로 나누는 것이 더 좋을 수 있다.
여러 개의 패키지로 이루어진 프로젝트는 작업공간을 통해 관리할 수 있다.
하나의 작업공간은 Cargo.lock
파일과 target
디렉토리를 공유한다.
작업공간을 구성하는 방법은 여러 가지가 있지만 그 중 보편적인 방법을 알아보겠다.
작업공간 디렉토리에 패키지 디렉토리들과 작업공간 Cargo.toml
이 존재하며
패키지 디렉토리에 src
디렉토리와 패키지 Cargo.toml
이 존재하는 구조를 만들겠다.
우리는 add_one
함수를 가진 패키지와 그리고 그것을 사용하는 바이너리를 포함하는
작업공간 add
를 생성할 것이다.
먼저 작업공간 디렉토리 add
를 생성한다.
peter@hp-laptop:~/rust-practice$ cd chapter14
peter@hp-laptop:~/rust-practice/chapter14$ mkdir add
peter@hp-laptop:~/rust-practice/chapter14$ cd add/
그리고 이 안에 바이너리 크레이트 adder
를 생성한다.
peter@hp-laptop:~/rust-practice/chapter14/add$ cargo new adder
Created binary (application) `adder` package
peter@hp-laptop:~/rust-practice/chapter14/add$
지금 생성한 이 adder
패키지는 add
작업공간에 속한다는 것을 명시하기 위해
add
디렉토리에 Cargo.toml
파일을 생성하고
[workspace]
섹션을 추가하여 멤버 정보를 작성한다.
peter@hp-laptop:~/rust-practice/chapter14/add$ vi Cargo.toml
Cargo.toml
[workspace] members = [ "adder", ]
이 상태로 작업공간을 빌드하면 add/adder
가 아닌 add
에
Cargo.lock
파일과 target
디렉토리가 생성되는 것을 확인할 수 있다.
peter@hp-laptop:~/rust-practice/chapter14/add$ cargo build
Compiling adder v0.1.0 (/home/peter/rust-practice/chapter14/add/adder)
Finished dev [unoptimized + debuginfo] target(s) in 0.63s
peter@hp-laptop:~/rust-practice/chapter14/add$ tree
.
├── adder
│ ├── Cargo.toml
│ └── src
│ └── main.rs
├── Cargo.lock
├── Cargo.toml
└── target
└── # snip
10 directories, 18 files
peter@hp-laptop:~/rust-practice/chapter14/add$
같은 작업공간 내의 패키지들은 서로 의존성을 가지고 있기 때문에
Cargo.toml
과 target
을 공유하도록 하는 것이다.
작업공간에 어떤 의존성을 추가했을 때 모든 패키지들이 같은 버전으로 사용하는 것이 보장된다.
그럼 이제 작업공간에 포함될 라이브러리 크레이트 add-one
을 작성해보자.
peter@hp-laptop:~/rust-practice/chapter14/add$ cargo new add-one --lib
warning: compiling this new crate may not work due to invalid workspace configuration
current package believes it's in a workspace when it's not:
current: /home/peter/rust-practice/chapter14/add/add-one/Cargo.toml
workspace: /home/peter/rust-practice/chapter14/add/Cargo.toml
this may be fixable by adding `add-one` to the `workspace.members` array of the manifest located at: /home/peter/rust-practice/chapter14/add/Cargo.toml
Alternatively, to keep it out of the workspace, add the package to the `workspace.exclude` array, or add an empty `[workspace]` table to the package's manifest.
Created library `add-one` package
peter@hp-laptop:~/rust-practice/chapter14/add$ vi add-one/src/lib.rs
add-one/src/lib.rs
pub fn add_one(x: i32) -> i32 { x + 1 }
크레이트를 생성할 때 뜨는 경고는 이 크레이트가 패키지 내에 생성되었는데
패키지의 Cargo.toml
의 members
에 이 크레이트가 존재하지 않는다는 것이다.
다음과 같이 추가해주면 된다.
peter@hp-laptop:~/rust-practice/chapter14/add$ vi Cargo.toml
Cargo.toml
[workspace] members = [ "adder", "add-one", ]
그리고 adder
또한 이 녀석에 대한 의존성을 가지는 바이너리가 될 것이므로
adder/Cargo.toml
에도 이 녀석에 대한 의존성을 명시해준다.
peter@hp-laptop:~/rust-practice/chapter14/add$ vi adder/Cargo.toml
adder/Cargo.toml
[package] name = "adder" version = "0.1.0" authors = ["Peter J <peter.j@kakao.com>"] edition = "2018" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] add-one = { path = "../add-one" }
이제 adder/src/main.rs
에서 use add_one;
을 통해
add-one
패키지에 있는 자료에 접근할 수 있다.
peter@hp-laptop:~/rust-practice/chapter14/add$ vi adder/src/main.rs
adder/src/main.rs
use add_one; fn main() { let num = 10; println!( "Hello, world! {} plus one is {}!", num, add_one::add_one(num) ); }
이 상태로 빌드하면 다음과 같이 빌드되는 것을 확인할 수 있다.
peter@hp-laptop:~/rust-practice/chapter14/add$ cargo build
Compiling add-one v0.1.0 (/home/peter/rust-practice/chapter14/add/add-one)
Compiling adder v0.1.0 (/home/peter/rust-practice/chapter14/add/adder)
Finished dev [unoptimized + debuginfo] target(s) in 0.25s
peter@hp-laptop:~/rust-practice/chapter14/add$
만약 어떤 바이너리를 실행하고자 한다면 -p
옵션을 통해
실행할 바이너리 크레이트의 이름을 명시해주어야 한다.
peter@hp-laptop:~/rust-practice/chapter14/add$ cargo run -p adder
Finished dev [unoptimized + debuginfo] target(s) in 0.01s
Running `target/debug/adder`
Hello, world! 10 plus one is 11!
peter@hp-laptop:~/rust-practice/chapter14/add$
Cargo.lock
작업공간에 외부 크레이트 의존성을 추가하려면
그것을 필요로 하는 패키지의 Cargo.toml
의 [dependencies]
섹션에 추가한다.
작업공간을 빌드할 때 의존성 정보는 작업공간의 Cargo.lock
에 공유된다.
여러 패키지에서 같은 외부 크레이트를 사용한다고 할 때
우리는 각각의 패키지의 Cargo.toml
에 그것을 추가해야 한다.
그리고 기존에 Cargo.lock
에 포함되어 있는 외부 크레이트를
다른 패키지에서 의존성으로 추가할 경우
기존에 내려 받아놓은 것이 있으므로 새로 내려 받지 않는다.
이것은 공간을 절약하는 효과도 있다.
우리가 다른 패키지들에서 한 것과 같이
작업공간 내 패키지에도 테스트 코드를 추가할 수 있다.
peter@hp-laptop:~/rust-practice/chapter14/add$ vi adder/src/lib.rs
adder/src/lib.rs
pub fn add_one(x: i32) -> i32 { x + 1 } #[cfg(test)] mod tests { use super::*; #[test] fn it_works() { assert_eq!(3, add_one(2)); } }
그리고 모든 패키지의 테스트를 수행하기 위해 cargo test
를 사용한다.
peter@hp-laptop:~/rust-practice/chapter14/add$ cargo test
Compiling add-one v0.1.0 (/home/peter/rust-practice/chapter14/add/add-one)
Compiling adder v0.1.0 (/home/peter/rust-practice/chapter14/add/adder)
Finished test [unoptimized + debuginfo] target(s) in 0.30s
Running target/debug/deps/add_one-c3b99376fbfb5ba9
running 1 test
test tests::it_works ... ok
test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out
Running target/debug/deps/adder-7ce7cd043cdb3e1f
running 0 tests
test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out
Doc-tests add-one
running 0 tests
test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out
peter@hp-laptop:~/rust-practice/chapter14/add$
add_one
패키지에서 테스트가 하나 수행되었으며 통과되었고
adder
패키지 테스트와 문서 테스트는 존재하지 않는다.
전체 테스트가 아니라 특정 패키지의 테스트만 수행할 수도 있는데
-p
옵션을 통해 패키지를 명시해주면 된다.
peter@hp-laptop:~/rust-practice/chapter14/add$ cargo test -p add-one
Finished test [unoptimized + debuginfo] target(s) in 0.00s
Running target/debug/deps/add_one-c3b99376fbfb5ba9
running 1 test
test tests::it_works ... ok
test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out
Doc-tests add-one
running 0 tests
test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out
peter@hp-laptop:~/rust-practice/chapter14/add$
작업공간에서 작성한 크레이트를 발행할 경우 각각의 크레이트가 개별적으로 발행된다.
크레이트 중 일부만 발행하고자 한다면
작업공간 디렉토리가 아니라 패키지 디렉토리로 들어가 발행을 해야 한다.
이 포스트의 내용은 공식문서의 14장 3절 Cargo Workspaces에 해당합니다.