Rust #14: 14장 Cargo 및 Crates.io에 대한 추가 정보
개요
이번 장에서는 다음에 대해 살펴보도록 합니다.
- 릴리즈 프로필을 통해 빌드 사용자 지정
- crates.io에 라이브러리 게시
- 작업 공간으로 대규모 프로젝트 구성
- crates.io에서 바이너리 설치
- 사용자 지정 명령을 이용해서 Cargo 확장
릴리즈 프로필로 빌드 사용자 지정
Cargo를 이용해 dev
및 release
빌드를 다음처럼 진행할 수 있습니다.
$ cargo build
Finished dev [unoptimized + debuginfo] target(s) in 0.0s
$ cargo build --release
Finished release [optimized] target(s) in 0.0s
그리고 Cargo.toml에 프로필 별 별도 설정을 할 수 있습니다.
[profile.dev]
opt-level = 0
[profile.release]
opt-level = 3
기본 설정은 기본 프로필에 의 해 결정되며 위의 설정 값은 기본 프로필의 동일 설정 값을 변경하게 됩니다.
Crates.io에 크레이트 게시하기
우리는 새로운 패키지를 creates.io
를 통해 편리하게 설치하여 사용할 수 있습니다. 이와 마찬가지로 우리의 패키지 역시 creates.io
에 게시하여 다른 사람들과 공유할 수도 있습니다.
유용한 문서 주석 작성
세개의 슬러시('///')를 주면 Cargo에서 API 문서를 만들 때 문서화가 됩니다.
소스코드
/// 하나의 정수형 값을 입력받아 그것에 1을 더한 값을 반환한다.
///
/// # 예시
/// ```rust
/// let arg = 5;
/// let answer = my_Crate:add_one(arg);
///
/// assert_eq!(6, answer);
///
pub fn add_one(x: i32) -> i32 { x + 1 }
이제 쉘에서,
```shell
$ cargo doc --open
하면 아래와 같은 문서를 확인할 수 있습니다.
문서
일반적으로 사용되는 섹션
문서 주석은 마크다운으로 해석되어 HTML로 변환됩니다. 다음은 크레이트 작성자가 문서에 일반적으로 사용한는 몇가지 다른 섹션입니다.
- 패닉 : 기능이 패닉을 일으킬 수 있는 시나리오입니다.
- 오류 : 기능이 오류가 발생할 수 있는 시나리오입니다.
- 안정성 : 기능이 unsafe 호출의 경우
테스트로서의 문서 주석
테스트를 진행하면 문서 주석의 예제 코드 블록도 실행이 됩니다!
Doc-tests my_crate
running 1 test
test src/lib.rs - add_one (line 5) ... ok
test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.27s
포함된 항목에 주석 달기
//!
를 주면 항목에 바로 문서를 추가할 수 있습니다.
//! # My Crate
//!
//! `my_crate` is a collection of utilities to make performing certain
//! calculations more convenient.
/// Adds one to the number given.
// --snip--
pub use
를 사용하여 편리한 공개 API 내보내기
공개 API를 사용하려 할 때 각 세부 항목에 들어가서 내용을 살펴보는 것은 접근이 어렵습니다. pub use
를 사용하면 문서화 시 항목이 표시됩니다.
//! # Art
//!
//! A library for modeling artistic concepts.
pub mod kinds {
/// The primary colors according to the RYB color model.
pub enum PrimaryColor {
Red,
Yellow,
Blue,
}
/// The secondary colors according to the RYB color model.
pub enum SecondaryColor {
Orange,
Green,
Purple,
}
}
pub mod utils {
use crate::kinds::*;
/// Combines two primary colors in equal amounts to create
/// a secondary color.
pub fn mix(c1: PrimaryColor, c2: PrimaryColor) -> SecondaryColor {
// --snip--
}
}
use art::kinds::PrimaryColor;
use art::utils::mix;
fn main() {
let red = PrimaryColor::Red;
let yellow = PrimaryColor::Yellow;
mix(red, yellow);
}
위의 화면처럼 kinds의 요소가 확인이 되지 않습니다. 이것을,
//! # Art
//!
//! A library for modeling artistic concepts.
pub use self::kinds::PrimaryColor;
pub use self::kinds::SecondaryColor;
pub use self::utils::mix;
pub mod kinds {
// --snip--
}
pub mod utils {
// --snip--
}
use art::mix;
use art::PrimaryColor;
fn main() {
// --snip--
}
로 사용할 수 있습니다.
Crates.io 계정 설정
Crates.io
에 본인의 패키지를 올리기 위해서는 계정 생성을 한 후 API 키를 받습니다. 그런 후 다음처럼 로그인을 할 수 있습니다.
``shell $cargo login abcdefghijklmnopqrstuvwxyz012345
### 새 크레이트에 메타데이터 추가
자신의 패키지를 게시하기 위해 메타데이터가 필요합니다. Cargom.toml에 관련 메타정보를 설정할 수 있습니다.
```toml
[package]
name = "guessing_game"
그러나 게시는 실패합니다.
$ cargo publish
Updating crates.io index
warning: manifest has no description, license, license-file, documentation, homepage or repository.
See https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for more info.
--snip--
error: api errors (status 200 OK): missing or empty metadata fields: description, license. Please see https://doc.rust-lang.org/cargo/reference/manifest.html for how to upload metadat
package
와 함께 필수 메타정보가 있기 때문입니다. 다음처럼 보완을 해봅시다.
[package]
name = "guessing_game"
version = "0.1.0"
edition = "2018"
description = "A fun game where you guess what number the computer has chosen."
license = "MIT OR Apache-2.0"
[dependencies]
Crates.io 게시
$ cargo publish
Updating crates.io index
Packaging guessing_game v0.1.0 (file:///projects/guessing_game)
Verifying guessing_game v0.1.0 (file:///projects/guessing_game)
Compiling guessing_game v0.1.0
(file:///projects/guessing_game/target/package/guessing_game-0.1.0)
Finished dev [unoptimized + debuginfo] target(s) in 0.19s
Uploading guessing_game v0.1.0 (file:///projects/guessing_game)
했을 때 잘 게시가 됐다면 축하합니다! 하지만 아마도 처음엔 안되었을 텐데요, cargo에서 친절하게 원인을 표시해주니 그것 대로 해결해 나가면 됩니다. 특히 crates.io
이미 사용하고 있는 패키지 명은 중복해서 쓸수가 없습니다!
기존 상자의 새 버전 게시
한번 게시가 완료되면 동일한 버젼으로 다시 게시가 안됩니다. 버전을 올리거나 기존 버전을 삭제해야 합니다.
cargo yank로 Crates.io 버젼 제거
cargo yank
로 기존 버전을 삭제할 수 있습니다. 하지만 기존 버전을 재 사용 할 수 있다는 의미는 아닙니다.
$ cargo yank --vers 1.0.1
만약 해당 버전을 다시 되돌릴려면 뒤에 --undo
명령어 인자를 추가 합니다.
$ cargo yank --vers 1.0.1 --undo
Cargo 작업공간
Cargo를 이용해 프로젝트 상위 개념인 작업공간
을 만들 수 있습니다. 다음을 따라 해봅시다.
먼저 add
라는 디렉토리를 만듭시다. 그런 후 add
디렉토리 안에서 adder
실행 크레잇을 만든 후 차례대로 add_one
과 add_two
라이브러리 크레잇을 만들어 봅시다.
add
디렉토리에 다음과 같이 Cargo.toml
를 만듭니다.
[workspace]
members = [
"adder",
"add-one",
"add-two",
]
그러면 디렉토리 구조는 다음과 같게 됩니다.
├── Cargo.toml
├── adder
│ ├── Cargo.toml
│ └── src
│ └── main.rs
├── add_one
│ ├── Cargo.toml
│ └── src
│ └── lib.rs
├── add_two
│ ├── Cargo.toml
│ └── src
│ └── lib.rs
cargo build
를 하게 되면 add
에 속해 있는 세개의 크레잇이 모두 빌드 됨을 확인할 수 있습니다.
$ cargo build
Compiling add-one v0.1.0 (W:\rust-learning\add\add-one)
Compiling adder v0.1.0 (W:\rust-learning\add\adder)
Compiling add-two v0.1.0 (W:\rust-learning\add\add-two)
Finished dev [unoptimized + debuginfo] target(s) in 0.55s
이제 add-two
에 다음의 코드를 삽입 한 후,
pub fn add_two(x: i32) -> i32 {
x + 1
}
Cargo는 작업공간에서 크레잇을 서로 의존한다고 가정하지 않으므로 직접 의존성을 명시해야 합니다.
adder/Cargo.toml
[dependencies]
add-two = { path = "../add-two" }
adder/src/main.rs
use add_two;
fn main() {
let num = 10;
println!(
"Hello, world! {} plus one is {}!",
num,
add_two::add_two(num)
);
}
이제 의존성에 의해 adder
보다 add-two
가 먼저 컴파일 됨을 확인할 수 있습니다.
$ cargo build
Compiling add-two v0.1.0 (W:\rust-learning\add\add-two)
Compiling add-one v0.1.0 (W:\rust-learning\add\add-one)
Compiling adder v0.1.0 (W:\rust-learning\add\adder)
Finished dev [unoptimized + debuginfo] target(s) in 0.61s
Cargo는 프로젝트가 여러 개일 경우 실행 크레잇을 찾아 실행을 해줍니다.
$ cargo run
Finished dev [unoptimized + debuginfo] target(s) in 0.01s
Running `target\debug\adder.exe`
Hello, world! 10 plus one is 11!
실행 크레잇이 여러개일 경우 프로젝트를 지정 할 수 있습니다.
cargo run -p adder
Finished dev [unoptimized + debuginfo] target(s) in 0.01s
Running `target\debug\adder.exe`
Hello, world! 10 plus one is 11!
작업 영역의 외부 패키지에 따라 다름
최상위 Cargo.lock에 종속성에 대한 정보가 포함되어 있지만 Cargo가 자동으로 외부 종속성을 프로젝트에 주입하지는 않습니다. 필요한 경우 개별 프로젝트의 Cargo.toml에 외부 패키지를 포함해야 합니다.
작업 영역에 테스트 추가
테스트 역시 작업공간에 포함된 모든 프로젝트의 테스트를 수행합니다.
$ cargo test
Compiling add-one v0.1.0 (file:///projects/add/add-one)
Compiling adder v0.1.0 (file:///projects/add/adder)
Finished test [unoptimized + debuginfo] target(s) in 0.27s
Running target/debug/deps/add_one-f0253159197f7841
running 1 test
test tests::it_works ... ok
test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
Running target/debug/deps/adder-49979ff40686fa8e
running 0 tests
test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
Doc-tests add-one
running 0 tests
test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
특정 프로젝트만 테스트를 수행하려면 다음과 같이 할 수 있습니다.
$ cargo test -p add_two
crates.io
에 자신의 크레잇을 게시하려면 작업공간에 있는 모든 프로젝트를 개별 게시해야 합니다.
cargo install을 이용해 Crates.io에서 바이너리 설치
이 명령을 사용하면 바이너리 크레잇을 로컬에 설치할 수 있습니다. 이것은 시스템 패키지 관리자를 대체하는 것은 아니고 개발 도구를 쉽게 설치하는 방법을 제공하는 것입니다.
cargo install ripgrep
Updating crates.io index
Downloaded ripgrep v11.0.2
Downloaded 1 crate (243.3 KB) in 0.88s
Installing ripgrep v11.0.2
--snip--
Compiling ripgrep v11.0.2
Finished release [optimized + debuginfo] target(s) in 3m 10s
Installing ~/.cargo/bin/rg
Installed package `ripgrep v11.0.2` (executable `rg`)
이후 rg
명령어를 통해 파일을 검색하기 위한 Rust 도구를 사용할 수 있게 됩니다.
사용자 지정 명령을로 Cargo 확장
실행 경로에 cargo-somthing
이라는 이름의 실행 파일을 배치하면 cargo somthing
으로 그 기능을 호출해 사용할 수 있습니다. 이 명령어는 cargo --list
를 통해서도 표출이 되게 됩니다.
정리
릴리즈 빌드, Crates.io에 게시, Cargo 작업공간 설정, Crates.io를 통해 바이너리 크레잇 설치 방법, 사용자 지정 명령을 살펴봤습니다.