Rust #14: 14장 Cargo 및 Crates.io에 대한 추가 정보

·

7 min read

개요

이번 장에서는 다음에 대해 살펴보도록 합니다.

  • 릴리즈 프로필을 통해 빌드 사용자 지정
  • crates.io에 라이브러리 게시
  • 작업 공간으로 대규모 프로젝트 구성
  • crates.io에서 바이너리 설치
  • 사용자 지정 명령을 이용해서 Cargo 확장

릴리즈 프로필로 빌드 사용자 지정

Cargo를 이용해 devrelease 빌드를 다음처럼 진행할 수 있습니다.

$ 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

하면 아래와 같은 문서를 확인할 수 있습니다.

문서 image.png

일반적으로 사용되는 섹션

문서 주석은 마크다운으로 해석되어 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--

image.png

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

image.png

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

image.png

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_oneadd_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를 통해 바이너리 크레잇 설치 방법, 사용자 지정 명령을 살펴봤습니다.