Skip to content

Latest commit

Β 

History

History
791 lines (621 loc) Β· 38.9 KB

08_cargo.md

File metadata and controls

791 lines (621 loc) Β· 38.9 KB

Cargo 툴 μ†Œκ°œ

러슀트 μ–Έμ–΄μ˜ μ»΄νŒŒμΌλŸ¬λŠ” rustcλΌλŠ” νˆ΄μž…λ‹ˆλ‹€. ν•˜μ§€λ§Œ rustcλ₯Ό 직접 μ‹€ν–‰ν•˜λŠ” 일은 거의 μ—†μŠ΅λ‹ˆλ‹€. λŒ€μ‹  Cargoλ₯Ό μ‚¬μš©ν•©λ‹ˆλ‹€. Cargoκ°€ λ¬΄μ—ˆμΈμ§€ μ–΄λ–€ 일듀을 ν•΄μ£ΌλŠ”μ§€λ₯Ό μ•Œμ•„λ³΄κ² μŠ΅λ‹ˆλ‹€.

κ°€μž₯ λ¨Όμ € Cargo의 help 메세지λ₯Ό 보면 러슀트의 νŒ¨ν‚€μ§€λ₯Ό 관리λ₯Ό μœ„ν•œ 툴이라고 μ„€λͺ…ν•©λ‹ˆλ‹€.

quick-guide-rust-programming $ cargo help
Rust's package manager

Usage: cargo [+toolchain] [OPTIONS] [COMMAND]
       cargo [+toolchain] [OPTIONS] -Zscript <MANIFEST_RS> [ARGS]...

Options:
  -V, --version             Print version info and exit
      --list                List installed commands
      --explain <CODE>      Provide a detailed explanation of a rustc error message
  -v, --verbose...          Use verbose output (-vv very verbose/build.rs output)
  -q, --quiet               Do not print cargo log messages
      --color <WHEN>        Coloring: auto, always, never
  -C <DIRECTORY>            Change to DIRECTORY before doing anything (nightly-only)
      --locked              Assert that `Cargo.lock` will remain unchanged
      --offline             Run without accessing the network
      --frozen              Equivalent to specifying both --locked and --offline
      --config <KEY=VALUE>  Override a configuration value
  -Z <FLAG>                 Unstable (nightly-only) flags to Cargo, see 'cargo -Z help' for details
  -h, --help                Print help

Commands:
    build, b    Compile the current package
    check, c    Analyze the current package and report errors, but don't build object files
    clean       Remove the target directory
    doc, d      Build this package's and its dependencies' documentation
    new         Create a new cargo package
    init        Create a new cargo package in an existing directory
    add         Add dependencies to a manifest file
    remove      Remove dependencies from a manifest file
    run, r      Run a binary or example of the local package
    test, t     Run the tests
    bench       Run the benchmarks
    update      Update dependencies listed in Cargo.lock
    search      Search registry for crates
    publish     Package and upload this package to the registry
    install     Install a Rust binary
    uninstall   Uninstall a Rust binary
    ...         See all commands with --list
See 'cargo help <command>' for more information on a specific command.

μ—¬κΈ°μ—μ„œ νŒ¨ν‚€μ§€λŠ” 일반적으둜 μƒκ°ν•˜λŠ” ν•˜λ‚˜μ˜ μ†Œν”„νŠΈμ›¨μ–΄ μ„€μΉ˜ 파일 rpmμ΄λ‚˜ debνŒŒμΌμ„ λ§ν• λ•Œ μ‚¬μš©ν•˜λŠ” νŒ¨ν‚€μ§€κ°€ μ•„λ‹™λ‹ˆλ‹€. λŸ¬μŠ€νŠΈμ—μ„œλŠ” μš°λ¦¬κ°€ κ°œλ°œν•˜λŠ” ν”„λ‘œμ νŠΈλ₯Ό νŒ¨ν‚€μ§€λΌκ³  λΆ€λ¦…λ‹ˆλ‹€. νŒ¨ν‚€μ§€λ₯Ό κ΄€λ¦¬ν•˜λŠ” νˆ΄μ΄λΌλŠ” μ˜λ―ΈλŠ” ν”„λ‘œμ νŠΈμ˜ κ°œλ°œν•˜λŠ” λͺ¨λ“  λ‹¨κ³„μ—μ„œ μ‚¬μš©λ˜λŠ” νˆ΄μ΄λΌλŠ” μ˜λ―Έμž…λ‹ˆλ‹€. ν”„λ‘œμ νŠΈ κ°œλ°œμ„ μœ„ν•œ 컴파일, ν”„λ‘œμ νŠΈ 전체 λΉŒλ“œ, μ™ΈλΆ€ 크레이트(λŸ¬μŠ€νŠΈμ—μ„œλŠ” μ™ΈλΆ€ 라이브러리λ₯Ό 크레이트라고 λΆ€λ¦…λ‹ˆλ‹€) λ‹€μš΄λ‘œλ“œ, μ‹€ν–‰ 파일 μ„€μΉ˜ λ“±λ“± 개발 κ³Όμ •μ˜ λͺ¨λ“  일을 μ²˜λ¦¬ν•  수 μžˆμŠ΅λ‹ˆλ‹€. 보톡 λ‹€λ₯Έ μ–Έμ–΄μ—μ„œλŠ” λ³„λ„μ˜ νˆ΄μ„ μ‚¬μš©ν•΄μ•Όλ˜λŠ” μ½”λ“œ 주석을 λ¬Έμ„œν™”ν•˜λŠ” κΈ°λŠ₯μ΄λ‚˜ μ½”λ“œ μ •λ ¬ λ“±μ˜ κΈ°λŠ₯듀도 μžˆμŠ΅λ‹ˆλ‹€.

그리고 help 메세지에 λ‚˜μ˜€λŠ” λͺ…λ Ήμ–΄ λ¦¬μŠ€νŠΈκ°€ λͺ¨λ“  λͺ…λ Ήμ–΄μ˜ λ¦¬μŠ€νŠΈκ°€ μ•„λ‹™λ‹ˆλ‹€. 주둜 많이 μ‚¬μš©λ˜λŠ” λͺ…λ Ήμ–΄λ“€λ§Œ 보여주고 μžˆμŠ΅λ‹ˆλ‹€. 전체 λͺ…λ Ήμ–΄ 리슀트λ₯Ό 보렀면 cargo --list λͺ…령을 μ‚¬μš©ν•©λ‹ˆλ‹€.

user@AL02279337 quick-guide-rust-programming % cargo --list
Installed Commands:
    add                  Add dependencies to a Cargo.toml manifest file
    b                    alias: build
    bench                Execute all benchmarks of a local package
    build                Compile a local package and all of its dependencies
    c                    alias: check
    check                Check a local package and all of its dependencies for errors
    clean                Remove artifacts that cargo has generated in the past
    clippy               Checks a package to catch common mistakes and improve your Rust code.
    config               Inspect configuration values
    d                    alias: doc
    doc                  Build a package's documentation
    expand
    fetch                Fetch dependencies of a package from the network
    fix                  Automatically fix lint warnings reported by rustc
    fmt                  Formats all bin and lib files of the current crate using rustfmt.
    generate-lockfile    Generate the lockfile for a package
    git-checkout         This command has been removed
    help                 Displays help for a cargo subcommand
    info                 Display information about a package in the registry
    init                 Create a new cargo package in an existing directory
    install              Install a Rust binary
    locate-project       Print a JSON representation of a Cargo.toml file's location
    login                Log in to a registry.
    logout               Remove an API token from the registry locally
    metadata             Output the resolved dependencies of a package, the concrete used versions including overrides, in machine-readable format
    miri
    new                  Create a new cargo package at <path>
    owner                Manage the owners of a crate on the registry
    package              Assemble the local package into a distributable tarball
    pkgid                Print a fully qualified package specification
    publish              Upload a package to the registry
    r                    alias: run
    read-manifest        Print a JSON representation of a Cargo.toml manifest.
    remove               Remove dependencies from a Cargo.toml manifest file
    report               Generate and display various kinds of reports
    rm                   alias: remove
    run                  Run a binary or example of the local package
    rustc                Compile a package, and pass extra options to the compiler
    rustdoc              Build a package's documentation, using specified custom flags.
    search               Search packages in the registry. Default registry is crates.io
    t                    alias: test
    test                 Execute all unit and integration tests and build examples of a local package
    tree                 Display a tree visualization of a dependency graph
    uninstall            Remove a Rust binary
    update               Update dependencies as recorded in the local lock file
    vendor               Vendor all dependencies for a project locally
    verify-project       Check correctness of crate manifest
    version              Show version information
    yank                 Remove a pushed crate from the index

νŠΉμ • λͺ…령어에 λŒ€ν•œ 보닀 μžμ„Έν•œ μ„€λͺ…을 λ³΄κ³ μ‹ΆμœΌλ©΄ cargo help λͺ…λ Ήμ–΄λ₯Ό μ‚¬μš©ν•©λ‹ˆλ‹€. λ¦¬λˆ…μŠ€μ˜ 맀뉴얼 νŽ˜μ΄μ§€μ™€ λ™μΌν•œ ν˜•νƒœμ˜ 맀뉴얼을 λ³Ό 수 μžˆμŠ΅λ‹ˆλ‹€.

user@AL02279337 quick-guide-rust-programming % cargo help add
CARGO-ADD(1)                           General Commands Manual                           CARGO-ADD(1)

NAME
       cargo-add β€” Add dependencies to a Cargo.toml manifest file

SYNOPSIS
       cargo add [options] crate…
       cargo add [options] --path path
       cargo add [options] --git url [crate…]

DESCRIPTION
       This command can add or modify dependencies.
......

λ‹€μŒλΆ€ν„° μ œκ°€ κ°œλ°œν•˜λ©΄μ„œ 자주 μ‚¬μš©ν•˜λŠ” λͺ…령어듀을 짧게 μ†Œκ°œν•˜κ² μŠ΅λ‹ˆλ‹€.

cargo new

ν˜„μž¬ 디렉토리에 μƒˆλ‘œμš΄ νŒ¨ν‚€μ§€λ₯Ό μœ„ν•œ 디렉토리λ₯Ό λ§Œλ“€κ³ , Cargo.toml 파일과 .gitignore 파일 λ“± κ°œλ°œμ„ μ‹œμž‘ν•˜κΈ° μœ„ν•΄ ν•„μš”ν•œ νŒŒμΌλ“€μ„ μžλ™μœΌλ‘œ μƒμ„±ν•΄μ€λ‹ˆλ‹€. κ°€μž₯ 많이 μ‚¬μš©ν•˜λŠ” μ˜΅μ…˜μ€ 2가지 -binκ³Ό --libμž…λ‹ˆλ‹€. --binμ˜΅μ…˜μ€ μ‹€ν–‰ νŒŒμΌμ„ λ§Œλ“€κΈ°μœ„ν•œ νŒ¨ν‚€μ§€λ₯Ό μƒμ„±ν•©λ‹ˆλ‹€. μ§€κΈˆ 예제 νŒŒμΌλ“€μ˜ ꡬ쑰λ₯Ό 보면 μ „λΆ€ src/main.rsνŒŒμΌμ„ 가지고 μžˆμŠ΅λ‹ˆλ‹€. μ‹€ν–‰ νŒŒμΌμ„ λ§Œλ“€κΈ° μœ„ν•œ νŒ¨ν‚€μ§€μ΄κΈ° λ•Œλ¬Έμ— --binμ˜΅μ…˜μ„ μ΄μš©ν•΄μ„œ λ§Œλ“€μ–΄μ‘ŒμŠ΅λ‹ˆλ‹€. --binμ˜΅μ…˜μœΌλ‘œ νŒ¨ν‚€μ§€λ₯Ό ν•˜λ‚˜ μƒμ„±ν•΄λ³΄κ² μŠ΅λ‹ˆλ‹€.

$ cargo new --bin bin-example
    Creating binary (application) `bin-example` package
bin-example $ ls -a
.          ..         .git       .gitignore Cargo.toml src

bin-exampleμ΄λΌλŠ” μ΄λ¦„μ˜ νŒ¨ν‚€μ§€λ₯Ό λ§Œλ“€μ—ˆμŠ΅λ‹ˆλ‹€. λ°”μ΄λ„ˆλ¦¬, 즉 μ‹€ν–‰ νŒŒμΌμ„ λ§Œλ“€κΈ° μœ„ν•œ νŒ¨ν‚€μ§€μž…λ‹ˆλ‹€. bin-exampleλ””λ ‰ν† λ¦¬μ—λŠ” Gitνˆ΄μ„ μœ„ν•œ .git디렉토리와 .gitignore파일이 μƒμ„±λ˜μ—ˆμŠ΅λ‹ˆλ‹€. 그리고 Cargoμžμ‹ μ΄ ν”„λ‘œμ νŠΈ 관리λ₯Ό μœ„ν•˜ μ‚¬μš©ν•˜λŠ” Cargo.toml파일과 μ†ŒμŠ€λ₯Ό μ €μž₯ν•  src 디렉토리가 μƒμ„±λ˜μ—ˆμŠ΅λ‹ˆλ‹€. src/main.rs νŒŒμΌμ—λŠ” κ°„λ‹¨ν•œ μ˜ˆμ œκ°€ λ“€μ–΄μžˆμŠ΅λ‹ˆλ‹€.

bin-example $ cat src/main.rs 
fn main() {
    println!("Hello, world!");
}

--libμ˜΅μ…˜μ€ 라이브러리λ₯Ό λ§Œλ“€κΈ° μœ„ν•œ νŒ¨ν‚€μ§€λ₯Ό 생성할 λ•Œ μ‚¬μš©ν•©λ‹ˆλ‹€. src/main.rsκ°€ μ•„λ‹ˆλΌ src/lib.rs νŒŒμΌμ„ μƒμ„±ν•©λ‹ˆλ‹€.

 $ cargo new --lib lib-example
    Creating library `lib-example` package
note: see more `Cargo.toml` keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
$ cd lib-example
lib-example $ ls -a
.          ..         .git       .gitignore Cargo.toml src
lib-example % ls src/
lib.rs

lib.rsνŒŒμΌμ€ κ°„λ‹¨ν•œ ν•¨μˆ˜μ˜ μ˜ˆμ œμ™€ μœ λ‹› ν…ŒμŠ€νŠΈ μ˜ˆμ œκ°€ λ“€μ–΄μžˆμŠ΅λ‹ˆλ‹€.

% cat src/lib.rs
pub fn add(left: u64, right: u64) -> u64 {
    left + right
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn it_works() {
        let result = add(2, 2);
        assert_eq!(result, 4);
    }
}

참고둜 .git 디렉토리가 μƒμ„±λ˜μ—ˆλ‹€κ³ ν•΄μ„œ Githubμ΄λ‚˜ μžμ‹ μ΄ μ‚¬μš©ν•˜λŠ” μ €μž₯μ†Œμ™€ μ—°κ²°λ˜μ—ˆλ‹€λŠ” 것은 μ•„λ‹™λ‹ˆλ‹€. git remote -vλͺ…령을 싀행해보면 μ•„λ¬΄λŸ° μ €μž₯μ†Œλ„ μ„€μ •λ˜μ§€ μ•Šμ•˜λ‹€λŠ” 것을 확인할 수 μžˆμŠ΅λ‹ˆλ‹€. 본인이 μ‚¬μš©ν•œ μ €μž₯μ†Œμ˜ 메뉴얼을 μ°Έκ³ ν•΄μ„œ μ €μž₯μ†Œ 연결을 μœ„ν•œ μ…‹νŒ…μ„ ν•΄μ£Όμ–΄μ•Όν•©λ‹ˆλ‹€.

cargo check

νŒ¨ν‚€μ§€λ₯Ό μƒμ„±ν–ˆλ‹€λ©΄ cargo check λͺ…λ ΉμœΌλ‘œ μ»΄νŒŒμΌλŸ¬κ°€ μ œλŒ€λ‘œ μ„€μΉ˜λ˜μ—ˆλŠ”μ§€, λͺ¨λ“  κ°œλ°œμ„ μœ„ν•œ ν™˜κ²½ μ…‹νŒ…μ΄ μ€€λΉ„λ˜μ—ˆλŠ”μ§€ 등을 확인해볼 수 μžˆμŠ΅λ‹ˆλ‹€. μ†ŒμŠ€ μ½”λ“œμ— μ—λŸ¬κ°€ μ—†λŠ”μ§€κΉŒμ§€ ν™•μΈν•˜κΈ° λ•Œλ¬Έμ— 사싀상 cargo buildλͺ…λ Ήκ³Ό 차이가 μ—†μ–΄λ³΄μž…λ‹ˆλ‹€. ν•˜μ§€λ§Œ build λͺ…령보닀 λ¨Όμ € checkλͺ…령을 λ¨Όμ € μ†Œκ°œν•˜λŠ” μ΄μœ κ°€ μžˆμŠ΅λ‹ˆλ‹€. build λͺ…령은 말 κ·ΈλŒ€λ‘œ νŒ¨ν‚€μ§€λ₯Ό λΉŒλ“œν•΄μ„œ μ΅œμ’… μ‹€ν–‰ νŒŒμΌκΉŒμ§€ μƒμ„±ν•˜μ§€λ§Œ, check λͺ…령은 μ‹€ν–‰ 파일 생성없이 μ—λŸ¬λ§Œ μ²΄ν¬ν•©λ‹ˆλ‹€. κ·Έλž˜μ„œ checkλͺ…령이 더 λΉ λ¦…λ‹ˆλ‹€. κ°œλ°œν•˜λ©΄μ„œ μƒˆλ‘œ μž‘μ„±ν•œ μ½”λ“œμ— μ—λŸ¬κ°€ μ—†λŠ”μ§€ ν™•μΈν•˜κΈ° μœ„ν•΄ μˆ˜λ„μ—†μ΄ 많이 컴파일러λ₯Ό μ‹€ν–‰ν•΄μ„œ μ‹€ν–‰ νŒŒμΌμ„ λ§Œλ“€μ–΄λ³Έ κ²½ν—˜μ΄ μžˆμ„ κ²ƒμž…λ‹ˆλ‹€. ν•˜μ§€λ§Œ κ·Έλ ‡κ²Œ μƒμ„±λœ μ‹€ν–‰ νŒŒμΌμ„ 맀번 μ‹€ν–‰ν•΄λ³΄μ§€λŠ” μ•ŠμŠ΅λ‹ˆλ‹€. μ‹€ν–‰ νŒŒμΌμ„ λ§Œλ“œλŠ” μ‹œκ°„λ§Œ λ‚­λΉ„λ˜λŠ” κ²ƒμž…λ‹ˆλ‹€. buildλͺ…령보닀 check λͺ…령을 더 자주 μ‚¬μš©ν•˜λ©΄ 쑰금의 μ‹œκ°„μ΄λΌλ„ 더 μ•„λ‚„ 수 μžˆμŠ΅λ‹ˆλ‹€. μ–Όλ§ˆλ‚˜ μ‹œκ°„μ΄ μ•„κ»΄μ§€λŠ”μ§€ ν•œλ²ˆ λΉ„κ΅ν•΄λ³΄κ² μŠ΅λ‹ˆλ‹€.

bin-example $ cargo check
    Checking bin-example v0.1.0 (/Users/user/study/bin-example)
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.29s
bin-example $ cargo build
   Compiling bin-example v0.1.0 (/Users/user/study/bin-example)
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.66s

checkλͺ…령이 build에 λΉ„ν•΄ 절반의 μ‹œκ°„λ§Œ μ‚¬μš©ν•©λ‹ˆλ‹€. μ§€κΈˆμ€ λ„ˆλ¬΄λ‚˜ κ°„λ‹¨ν•œ 예제만 λ“€μ–΄μžˆκΈ° λ•Œλ¬Έμ— μ€„μ–΄λ“œλŠ” μ‹œκ°„ 차이가 λ„ˆλ¬΄ 미미해보일 수 μžˆμŠ΅λ‹ˆλ‹€. ν•˜μ§€λ§Œ νŒ¨ν‚€μ§€μ˜ 규λͺ¨κ°€ μ‘°κΈˆμ΄λΌλ„ 컀지면 cargo buildλͺ…령에 μ‹œκ°„μ΄ 더 걸리고 닡닡함을 λŠλ‚„ 수 μžˆμŠ΅λ‹ˆλ‹€. 러슀트 μ»΄νŒŒμΌλŸ¬κ°€ λ©”λͺ¨λ¦¬ 관리λ₯Ό μœ„ν•œ λ‹€μ–‘ν•œ κΈ°λŠ₯듀을 가지고 있기 λ•Œλ¬Έμ— 컴파일 μ‹œκ°„μ΄ 느린걸둜 유λͺ…ν•©λ‹ˆλ‹€. λ‹¨μˆœνžˆ 문법 μ—λŸ¬κ°€ μ—†λŠ”μ§€ 확인할 λ•ŒλŠ” buildλͺ…λ Ή λŒ€μ‹ μ— checkλͺ…령을 μ‚¬μš©ν•˜λŠ” 것을 ꢌμž₯ν•©λ‹ˆλ‹€.

cargo build

μ΅œμ’… μ‹€ν–‰ νŒŒμΌμ„ λ§Œλ“€κΈ° μœ„ν•΄μ„œλŠ” build λͺ…령을 μ‚¬μš©ν•΄μ•Όν•©λ‹ˆλ‹€. cargoλŠ” target/debug 디렉토리λ₯Ό λ§Œλ“€κ³ , μƒμ„±λœ μ‹€ν–‰νŒŒμΌμ„ μ €μž₯ν•©λ‹ˆλ‹€. λ‹€μŒμ€ bin-example νŒ¨ν‚€μ§€μ˜ target/debug 디렉토리에 μžˆλŠ” bin-example μ‹€ν–‰ νŒŒμΌμ„ μ‹€ν–‰ν•΄λ³Έ κ²°κ³Όμž…λ‹ˆλ‹€.

bin-example $ cargo build
   Compiling bin-example v0.1.0 (/Users/user/study/bin-example)
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.29s
bin-example $ ls target 
CACHEDIR.TAG debug
bin-example $ ls target/debug 
bin-example   bin-example.d build         deps          examples      incremental
bin-example $ ./target/debug/bin-example
Hello, world!

디렉토리 이름이 debug인걸 보면 μ•Œμˆ˜μžˆλ“―μ΄ build λͺ…령에 μ•„λ¬΄λŸ° μ˜΅μ…˜λ„ 주지 μ•ŠμœΌλ©΄ 디버깅 정보가 λ“€μ–΄κ°„ μ‹€ν–‰ νŒŒμΌμ„ λ§Œλ“­λ‹ˆλ‹€. μ œν’ˆμœΌλ‘œ μΆœμ‹œν•  수 μžˆλŠ” μ‹€ν–‰ νŒŒμΌμ€ μ•„λ‹™λ‹ˆλ‹€. 릴리즈 λͺ¨λ“œμ˜ μ‹€ν–‰ νŒŒμΌμ„ λ§Œλ“€κΈ° μœ„ν•΄μ„œλŠ” --release μ˜΅μ…˜μ„ μ£Όμ–΄μ•Όν•©λ‹ˆλ‹€. λ‹€μŒμ€ 릴리즈 λͺ¨λ“œμ˜ μ‹€ν–‰ νŒŒμΌμ„ λ§Œλ“€μ–΄λ³Έ κ²°κ³Όμž…λ‹ˆλ‹€.

bin-example $ cargo build --release
   Compiling bin-example v0.1.0 (/Users/user/study/bin-example)
    Finished `release` profile [optimized] target(s) in 0.84s
bin-example $ ls target/release/
bin-example   bin-example.d build         deps          examples      incremental

디렉토리 이름이 release둜 λ°”λ€Œμ—ˆμŠ΅λ‹ˆλ‹€. κ·Έ 외에 μƒμ„±λœ νŒŒμΌμ΄λ‚˜ 디렉토리 등은 λ™μΌν•©λ‹ˆλ‹€.

λΉŒλ“œλ‘œ μƒμ„±λœ νŒŒμΌλ“€μ„ μ§€μš°κΈ°μœ„ν•΄μ„œ clean λͺ…령을 μ‚¬μš©ν•©λ‹ˆλ‹€.

bin-example $ ls  
Cargo.lock Cargo.toml src        target
bin-example $ cargo clean
     Removed 11 files, 760.6KiB total
bin-example $ ls
Cargo.lock Cargo.toml src

cargo run

μ‹€ν–‰ νŒŒμΌμ„ κ°„λ‹¨ν•˜κ²Œ μ‹€ν–‰ν•˜κΈ° μœ„ν•΄μ„œ run λͺ…령이 μžˆμŠ΅λ‹ˆλ‹€. νŒ¨ν‚€μ§€μ—μ„œ μƒμ„±ν•˜λŠ” μ‹€ν–‰ 파일이 1개라면 λ‹€λ₯Έ μ˜΅μ…˜μ΄ ν•„μš”μ—†μ§€λ§Œ, μ—¬λŸ¬κ°œλΌλ©΄ λ‹€μŒκ³Ό 같이 --bin μ˜΅μ…˜μœΌλ‘œ μ‹€ν–‰ 파일의 이름을 지정해쀄 수 μžˆμŠ΅λ‹ˆλ‹€. λ‹€μŒμ€ 이 μ±…μ˜ 예제 μ½”λ“œλ₯Ό λ‹€μš΄λ°›μ€ ν›„ function_forλΌλŠ” μ‹€ν–‰ νŒŒμΌμ„ λΉŒλ“œν•˜κ³  μ‹€ν–‰ν•΄λ³Έ κ²ƒμž…λ‹ˆλ‹€.

$ cargo build --bin function_for
   Compiling my-rust-book v0.1.0 (/home/gurugio/my-rust-book)
    Finished dev [unoptimized + debuginfo] target(s) in 0.17s
$ cargo run --bin function_for
    Finished dev [unoptimized + debuginfo] target(s) in 0.00s
     Running `target/debug/function_for`
Hello, function_for!
3 - Fizz
5 - Buzz
6 - Fizz
9 - Fizz
10 - Buzz

그리고 ν”„λ‘œκ·Έλž¨μ΄ μ»€λ§¨λ“œ 라인 μ˜΅μ…˜μ„ λ°›λŠ” κ²½μš°μ— cargo run λͺ…령에 μ»€λ§¨λ“œ 라인 μ˜΅μ…˜μ„ μΆ”κ°€ν•  수 μžˆμŠ΅λ‹ˆλ‹€. μ•„λž˜λŠ” Clapμ΄λΌλŠ” 크레이트의 예제 μ½”λ“œλ₯Ό μ‹€ν–‰ν•˜λŠ” λͺ¨μŠ΅μž…λ‹ˆλ‹€. 이 μ˜ˆμ œλŠ” --help, --version λ“± 총 4개의 μ˜΅μ…˜μ„ 받을 수 μžˆμŠ΅λ‹ˆλ‹€. 이런 예제λ₯Ό κ°œλ°œν•˜λŠ” μ€‘μ—λŠ” μ•„λž˜μ™€ 같이 demoλΌλŠ” μ‹€ν–‰νŒŒμΌμ„ μ‹€ν–‰ν•˜λŠ”κ²Œ μ•„λ‹ˆλΌ cargo run λͺ…λ ΉμœΌλ‘œ λ°”λ‘œ μ‹€ν–‰ν•˜κ³ , μ˜΅μ…˜λ„ 전달할 수 있으면 κ°œλ°œμ— νŽΈλ¦¬ν•  κ²ƒμž…λ‹ˆλ‹€.

$ demo --help
A simple to use, efficient, and full-featured Command Line Argument Parser

Usage: demo[EXE] [OPTIONS] --name <NAME>

Options:
  -n, --name <NAME>    Name of the person to greet
  -c, --count <COUNT>  Number of times to greet [default: 1]
  -h, --help           Print help
  -V, --version        Print version

$ demo --name Me
Hello Me!

예제 μ½”λ“œκ°€ --helpλΌλŠ” μ˜΅μ…˜μ„ μ²˜λ¦¬ν•  수 μžˆλ‹€κ³ ν•΄μ„œ λ‹€μŒκ³Ό 같이 λ°”λ‘œ cargo run λͺ…령에 --help μ˜΅μ…˜μ„ μ£Όλ©΄ cargo run이 μ²˜λ¦¬ν•  수 μžˆλŠ” μ˜΅μ…˜λ“€μ΄ 좜λ ₯λ©λ‹ˆλ‹€. μš°λ¦¬λŠ” 예제 μ½”λ“œμ— --help μ˜΅μ…˜μ„ μ „λ‹¬ν•˜λ €λŠ” 것이지 cargoμ—κ²Œ --help μ˜΅μ…˜μ„ μ „λ‹¬ν•˜λ €λŠ” 것이 μ•„λ‹ˆκΈ° λ•Œλ¬Έμ— λ‹€λ₯Έ 방법이 ν•„μš”ν•©λ‹ˆλ‹€.

% cargo run --help  
Run a binary or example of the local package

Usage: cargo run [OPTIONS] [ARGS]...

Arguments:
  [ARGS]...  Arguments for the binary or example to run

Options:
      --message-format <FMT>  Error format
  -v, --verbose...            Use verbose output (-vv very verbose/build.rs output)
  -q, --quiet                 Do not print cargo log messages
      --color <WHEN>          Coloring: auto, always, never
      --config <KEY=VALUE>    Override a configuration value
  -Z <FLAG>                   Unstable (nightly-only) flags to Cargo, see 'cargo -Z help' for details
  -h, --help                  Print help
......μƒλž΅

cargo run λͺ…λ Ήμ—μ„œ cargo μžμ²΄μ— λŒ€ν•œ μ˜΅μ…˜μ΄ μ•„λ‹ˆλΌ μ‹€ν–‰ν•  λ°”μ΄λ„ˆλ¦¬ μ‹€ν–‰ νŒŒμΌμ—κ²Œ 전달할 μ˜΅μ…˜μ€ λ‹€μŒκ³Ό 같이 -- 이후에 μ μ–΄μ£Όκ²Œλ©λ‹ˆλ‹€. μ•„λž˜ μ‹€ν–‰ μ˜ˆμ œλŠ” demo --help둜 μ‹€ν–‰ν•œ 결과와 λ™μΌν•œ μ‹€ν–‰ κ²°κ³Όλ₯Ό 확인할 수 μžˆμŠ΅λ‹ˆλ‹€.

$ cargo run -- --help
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.10s
     Running `target/debug/bin-example --help`
Simple program to greet a person

Usage: bin-example [OPTIONS] --name <NAME>

Options:
  -n, --name <NAME>    Name of the person to greet
  -c, --count <COUNT>  Number of times to greet [default: 1]
  -h, --help           Print help
  -V, --version        Print version
$ cargo run -- -n Gioh --count 2
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.05s
     Running `target/debug/bin-example -n Gioh --count 2`
Hello Gioh!
Hello Gioh!

-- λ‹€μŒμ— μ „λ‹¬ν•œ -n Gioh --count 2 μ˜΅μ…˜μ΄ cargoκ°€ μ•„λ‹Œ 예제 μ½”λ“œλ‘œ μ „λ‹¬λ˜μ„œ μ‹€ν–‰λ˜μ—ˆμŠ΅λ‹ˆλ‹€.

cargo search 와 cargo add

ν”„λ‘œμ νŠΈλ₯Ό μ§„ν–‰ν•˜λ‹€λ³΄λ©΄ λ‹€μ–‘ν•œ μ™ΈλΆ€ 크레이트(λΌμ΄λΈŒλŸ¬λ¦¬μ™€ 같은 κ°œλ…μž…λ‹ˆλ‹€)κ°€ ν•„μš”ν•©λ‹ˆλ‹€. https://crates.io/ μ‚¬μ΄νŠΈμ—μ„œ 검색해볼 수 도 μžˆμŠ΅λ‹ˆλ‹€λ§Œ cargo search λͺ…령을 μ‚¬μš©ν•  μˆ˜λ„ μžˆμŠ΅λ‹ˆλ‹€. anyhow 크레이트λ₯Ό κ²€μƒ‰ν•΄λ³΄κ² μŠ΅λ‹ˆλ‹€.

bin-example % cargo search anyhow
anyhow = "1.0.94"                # Flexible concrete Error type built on std::error::Error
anyhow-tauri = "1.0.0"           # A crate that lets you use anyhow as a command result with the tauri framework.
anyhow_ext = "0.2.1"             # Extension of anynow
anyhow-std = "0.1.4"             # Wrap std APIs with anyhow error context.
spark-market-sdk = "0.6.6"       # SDK for interacting with the Spark Market
sentry-anyhow = "0.35.0"         # Sentry integration for anyhow. 
anyhow-loc = "0.3.0"             # anyhow with location
anyhow_trace = "0.1.3"           # Macro which adds source location as context to anyhow errors
async-anyhow-logger = "0.1.0"    # An easy crate for catching anyhow errors from an asynchronous function, and passing them to yo…
ckb-sentry-anyhow = "0.21.0"     # Sentry integration for anyhow. 
... and 1070 crates more (use --limit N to see more)

μ›ν•˜λŠ” 크레이트λ₯Ό 찾은 ν›„μ—λŠ” add λͺ…λ ΉμœΌλ‘œ νŒ¨ν‚€μ§€μ— μΆ”κ°€ν•΄μ€λ‹ˆλ‹€.

bin-example $ cargo add anyhow
    Updating crates.io index
      Adding anyhow v1.0.94 to dependencies
             Features:
             + std
             - backtrace
    Updating crates.io index
     Locking 1 package to latest compatible version
      Adding anyhow v1.0.94
bin-example % grep anyhow Cargo.toml
anyhow = "1.0.94"

Cargo.toml νŒŒμΌμ— anyhow의 κ°€μž₯ μ΅œμ‹  버전이 μΆ”κ°€λœ 것을 확인할 수 μžˆμŠ΅λ‹ˆλ‹€.

μ΅œμ‹  버전이 μ•„λ‹ˆλΌ λ‹€λ₯Έ 버전을 직접 μ§€μ •ν•˜κ³  싢을 λ•ŒλŠ” λ‹€μŒκ³Ό 같이 @x.y와 같이 버전을 μ¨μ€λ‹ˆλ‹€.

% cargo add [email protected]
    Updating crates.io index
      Adding anyhow v1.0 to dependencies
             Features as of v1.0.0:
             + std
    Updating crates.io index
     Locking 1 package to latest compatible version
      Adding anyhow v1.0.95

러슀트둜 κ°œλ°œν•˜λ‹€λ³΄λ©΄ μ‚¬μš©ν•˜κ³ μ‹Άμ€ 크레이트의 μ΅œμ‹  κΈ°λŠ₯이 ν•„μš”ν•  λ•Œκ°€ μžˆμŠ΅λ‹ˆλ‹€. 아직 μ΅œμ‹  버전에 μΆœμ‹œλ˜μ§€μ•Šκ³  이제 막 Github에 올라온 κΈ°λŠ₯이 ν•„μš”ν• λ•Œκ°€ μ’…μ’…μžˆμŠ΅λ‹ˆλ‹€. λŸ¬μŠ€νŠΈκ°€ 아직 μΆœμ‹œλœμ§€ 였래된 μ–Έμ–΄κ°€ μ•„λ‹ˆκ³ , μ΅œκ·Όμ—λ„ ν™œλ°œν•˜κ²Œ 개발되고있기 λ•Œλ¬Έμž…λ‹ˆλ‹€. κ·ΈλŸ΄λ•ŒλŠ” λ‹€μŒκ³Ό 같이 --gitμ˜΅μ…˜μœΌλ‘œ Gihub의 클둠 μ£Όμ†Œλ₯Ό μž…λ ₯ν•΄μ£Όλ©΄ Github의 main 브랜치λ₯Ό λ‹€μš΄λ°›μ•„μ€λ‹ˆλ‹€. ν•„μš”ν•˜λ‹€λ©΄ --branch μ˜΅μ…˜μ„ μΆ”κ°€ν•΄μ„œ 브랜치 이름도 지정할 수 μžˆμŠ΅λ‹ˆλ‹€.

$ cargo add anyhow --git https://github.com/dtolnay/anyhow.git
    Updating git repository `https://github.com/dtolnay/anyhow.git`
      Adding anyhow (git) to dependencies
             Features:
             + std
             - backtrace
    Updating git repository `https://github.com/dtolnay/anyhow.git`
     Locking 1 package to latest compatible version
      Adding anyhow v1.0.94 (https://github.com/dtolnay/anyhow.git#8ceb5e98)

cargo add λͺ…λ Ήμ—μ„œ 자주 μ‚¬μš©λ˜λŠ” μ˜΅μ…˜μ€‘μ— --features μ˜΅μ…˜μ΄ μžˆμŠ΅λ‹ˆλ‹€. λ‹€μŒμ€ clap 크레이트λ₯Ό μΆ”κ°€ν•˜λ©΄μ„œ deriveλΌλŠ” κΈ°λŠ₯을 μ‚¬μš©ν•˜λŠ” λͺ…λ Ήμž…λ‹ˆλ‹€.

$ cargo add clap --features string

μ‹€ν–‰ ν›„ Cargo.toml νŒŒμΌμ„ 열어보면 λ‹€μŒκ³Ό 같이 clap ν¬λ ˆμ΄νŠΈκ°€ 좔가될 것을 확인할 수 μžˆμŠ΅λ‹ˆλ‹€.

[dependencies]
clap = { version = "4.5.26", features = ["string"] }

Cargo.toml νŒŒμΌμ„ μˆ˜μ •ν•˜λŠ” λͺ…령듀은 Cargo.toml을 μ†μœΌλ‘œ 직접 μˆ˜μ •ν•˜λŠ” 것과 λ™μΌν•©λ‹ˆλ‹€. cargo add λ“±μ˜ λͺ…령에 λŒ€ν•œ μ‚¬μš©λ²•μ΄ 잘 기얡이 λ‚˜μ§€μ•ŠμœΌλ©΄ Cargo.toml νŒŒμΌμ„ 직접 μˆ˜μ •ν•΄λ„ μƒκ΄€μ—†μŠ΅λ‹ˆλ‹€.

cargo fmt

러슀트 μ–Έμ–΄λŠ” κ³΅μ‹μ μœΌλ‘œ 정해진 것은 μ•„λ‹ˆμ§€λ§Œ λŒ€λΆ€λΆ„ λ”°λ₯΄κ³ μžˆλŠ” μŠ€νƒ€μΌ κ°€μ΄λ“œ(https://doc.rust-lang.org/nightly/style-guide/)κ°€ μžˆμŠ΅λ‹ˆλ‹€. cargo의 fmt λͺ…령을 μ‚¬μš©ν•˜λ©΄ μžλ™μœΌλ‘œ μ†ŒμŠ€ μ½”λ“œμ˜ μŠ€νƒ€μΌμ„ κ°€μ΄λ“œμ— 맞게 μˆ˜μ •ν•΄μ€λ‹ˆλ‹€. Visual Studio Codeλ“± λ‹€μ–‘ν•œ IDEμ—μ„œ 러슀트의 μ½”λ“œ 포맷을 μžλ™μœΌλ‘œ μˆ˜μ •ν•΄μ£ΌλŠ” 것이 λ°”λ‘œ fmt λͺ…령을 λ‚΄λΆ€μ—μ„œ μ‹€ν–‰ν•΄μ£ΌλŠ” κ²ƒμž…λ‹ˆλ‹€.

μ‹€ν—˜μ„ μœ„ν•΄ λ‹€μŒκ³Ό 같이 printlnμ•žμ— λΆˆν•„μš”ν•œ 곡백을 μΆ”κ°€ν•΄μ£Όκ³ , ;μ•žμ—λ„ 곡백을 λ„£μ–΄μ£Όκ² μŠ΅λ‹ˆλ‹€.

bin-example $ cat src/main.rs
fn main() {
    	println!("Hello, world!")    ;
}

μš°μ„  μŠ€νƒ€μΌ κ°€μ΄λ“œμ— λ§žμ§€ μ•ŠλŠ” 뢀뢄이 어디인지 확인해보기 μœ„ν•΄ --checkμ˜΅μ…˜μ„ μ£Όκ³  fmt λͺ…령을 μ‹€ν–‰ν•΄λ³΄κ² μŠ΅λ‹ˆλ‹€.

user@AL02279337 bin-example % cargo fmt --check
Diff in /Users/user/study/bin-example/src/main.rs:1:
 fn main() {
-        println!("Hello, world!")    ;
+    println!("Hello, world!");
 }

μ–΄λŠ μ½”λ“œλ₯Ό μ–΄λ–»κ²Œ μˆ˜μ •ν•΄μ€„μ§€λ₯Ό λ³΄μ—¬μ€λ‹ˆλ‹€. 그리고 fmt λͺ…령을 μ‹€ν–‰ν•˜λ©΄ 미리 μ•Œλ €μ€€λŒ€λ‘œ μˆ˜μ •ν•΄μ€λ‹ˆλ‹€.

bin-example $ cargo fmt
bin-example $ cat src/main.rs
fn main() {
    println!("Hello, world!");
}

cargo test

κ°œλ°œμ„ ν•˜λ‹€λ³΄λ©΄ νŒ¨ν‚€μ§€λ₯Ό λΉŒλ“œν•˜κ³  μ‹€ν–‰ν•˜λŠ” 것보닀 ν…ŒμŠ€νŠΈλ₯Ό μ‹€ν–‰ν•˜λŠ” κ²½μš°κ°€ 더 λ§Žμ„ κ²ƒμž…λ‹ˆλ‹€. CargoλŠ” νŒ¨ν‚€μ§€μ— μžˆλŠ” λͺ¨λ“  ν…ŒμŠ€νŠΈλ₯Ό μ‹€ν–‰ν•  수 μžˆλŠ” test λͺ…령을 μ œκ³΅ν•΄μ€λ‹ˆλ‹€.

이 μ±…μ—μ„œλŠ” μœ λ‹› ν…ŒμŠ€νŠΈμ™€ 톡합 ν…ŒμŠ€νŠΈλ₯Ό 어디에 λ§Œλ“€μ–΄μ•Όν•˜κ³  μ–΄λ–»κ²Œ 싀행해야할지λ₯Ό μ†Œκ°œν•©λ‹ˆλ‹€. 무엇을 ν…ŒμŠ€νŠΈν•΄μ•Όλ˜λŠ”μ§€, μ–΄λ–€ ν…ŒμŠ€νŠΈλ₯Ό λ§Œλ“€μ–΄μ•Όν•˜λŠ”μ§€ λ“± ν…ŒμŠ€νŠΈ μžμ²΄μ— λŒ€ν•œ 것은 λ³„λ„μ˜ 자료λ₯Ό μ°Έκ³ ν•΄μ£Όμ‹œκΈ° λ°”λžλ‹ˆλ‹€.

μœ λ‹› ν…ŒμŠ€νŠΈ λ§Œλ“€κΈ°

μœ λ‹› ν…ŒμŠ€νŠΈλŠ” λ‹€μŒκ³Ό 같은 ν˜•νƒœλ‘œ 각 μ†ŒμŠ€ μ½”λ“œ μ•ˆμ— λ§Œλ“€μ–΄μ€λ‹ˆλ‹€.

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn ν…ŒμŠ€νŠΈν•¨μˆ˜μ΄λ¦„() {
        ν…ŒμŠ€νŠΈμ½”λ“œ
        보톡 assert둜 μ‹œμž‘ν•˜λŠ” 맀크둜λ₯Ό μ‚¬μš©ν•¨: assert_eq!, assert_ne! λ“±
    }
}

일반적으둜 μ§€κΈˆκΉŒμ§€ λ§Œλ“€μ–΄λ³Έ μ½”λ“œμ™€ λ‹€λ₯Έ 뢀뢄이 4가지가 μžˆμŠ΅λ‹ˆλ‹€. ν•˜λ‚˜μ”© μ†Œκ°œν•˜κ² μŠ΅λ‹ˆλ‹€.

  1. #[cfg(test)]: μ•„λž˜ μ§€μ •λœ testsλΌλŠ” λͺ¨λ“ˆμ„ cargo test λͺ…령이 μ‹€ν–‰λ λ•Œλ§Œ λΉŒλ“œν•˜κ³  μ‹€ν–‰ν•˜λΌλŠ” μ˜λ―Έμž…λ‹ˆλ‹€.
  2. mod tests: testsλΌλŠ” λͺ¨λ“ˆμ„ λ§Œλ“­λ‹ˆλ‹€. ν…ŒμŠ€νŠΈν•¨μˆ˜λ₯Ό μ œν’ˆμ— λ“€μ–΄κ°€λŠ” μ½”λ“œμ™€ λ³„λ„μ˜ λͺ¨λ“ˆλ‘œ 뢄리해주기 μœ„ν•΄μ„œ λ§Œλ“­λ‹ˆλ‹€.
  3. use super::*;: ν…ŒμŠ€νŠΈκ°€ μ‘΄μž¬ν•˜λŠ” νŒŒμΌμ—μ„œ μ •μ˜ν•œ ν•¨μˆ˜λ‚˜ ꡬ쑰체 등을 μ‚¬μš©ν•˜κ²Œ ν•΄μ€λ‹ˆλ‹€.
  4. #[test]: 각 ν…ŒμŠ€νŠΈ ν•¨μˆ˜λ§ˆλ‹€ λ”°λ‘œ cargo test λͺ…λ ΉμœΌλ‘œ 싀행될 수 μžˆλ„λ‘ ν•΄μ€λ‹ˆλ‹€. 이 ν‘œμ‹œκ°€ μ—†μœΌλ©΄ cargo test둜 μ‹€ν–‰ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

이전에 μš°λ¦¬λŠ” lib-exampleμ΄λΌλŠ” 라이브러리λ₯Ό λ§Œλ“œλŠ” νŒ¨ν‚€μ§€λ₯Ό μƒμ„±ν•΄λ³΄μ•˜μŠ΅λ‹ˆλ‹€. Cargoκ°€ νŒ¨ν‚€μ§€λ₯Ό μƒμ„±ν•˜λ©΄μ„œ src/lib.rs νŒŒμΌμ„ 같이 생성해주고 κ°„λ‹¨ν•œ 예제 μ½”λ“œλ₯Ό λ„£μ–΄μ£Όμ—ˆμŠ΅λ‹ˆλ‹€. ν•΄λ‹Ή νŒŒμΌμ„ μ—΄μ–΄μ„œ λ‹€μŒκ³Ό 같이 println 맀크둜 ν•¨μˆ˜λ₯Ό μ΄μš©ν•΄μ„œ 디버깅 메세지λ₯Ό λ„£μ–΄μ£Όκ² μŠ΅λ‹ˆλ‹€.

// lib-example/src/lib.rs
pub fn add(left: u64, right: u64) -> u64 {
    left + right
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn it_works() {
        let result = add(2, 2);
        println!("Try 2 + 2"); // debugging message
        assert_eq!(result, 4);
    }
}

그리고 μš°μ„  ν•΄λ‹Ή μœ λ‹› ν…ŒμŠ€νŠΈλ₯Ό μ‹€ν–‰ν•΄λ³΄κ² μŠ΅λ‹ˆλ‹€. cargo test λͺ…령에 ν…ŒμŠ€νŠΈ ν•¨μˆ˜μ˜ 이름을 지정해주면 μ§€μ •λœ ν…ŒμŠ€νŠΈλ§Œ μ‹€ν–‰ν•΄μ€λ‹ˆλ‹€.

lib-example $ cargo test it_works            
   Compiling lib-example v0.1.0 (/Users/user/study/lib-example)
    Finished `test` profile [unoptimized + debuginfo] target(s) in 0.39s
     Running unittests src/lib.rs (target/debug/deps/lib_example-89f31e00332d9f1d)

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

싀행은 잘 λ˜μ§€λ§Œ μš°λ¦¬κ°€ 디버깅을 μœ„ν•΄ μΆ”κ°€ν•œ 메세지λ₯Ό 좜λ ₯λ˜μ§€ μ•Šμ•˜μŠ΅λ‹ˆλ‹€. λ‹€μŒκ³Ό 같이 --nocapture μ˜΅μ…˜μ„ μΆ”κ°€ν•΄μ£Όλ©΄ 디버깅 메세지λ₯Ό 좜λ ₯ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

lib-example $ cargo test it_works -- --nocapture
    Finished `test` profile [unoptimized + debuginfo] target(s) in 0.01s
     Running unittests src/lib.rs (target/debug/deps/lib_example-89f31e00332d9f1d)

running 1 test
Try 2 + 2
test tests::it_works ... ok

test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

μ£Όμ˜ν•΄μ•Όν•  것이 μžˆμŠ΅λ‹ˆλ‹€. cargo test it_works --nocaptureκ°€ μ•„λ‹ˆλΌ 쀑간에 --을 ν•œλ²ˆ 더 μ¨μ€˜μ„œ cargo test it_works -- --nocapture라고 μ¨μ€˜μ•Όλœλ‹€λŠ” κ²ƒμž…λ‹ˆλ‹€. cargo test it_works --nocapture라고 μ€‘κ°„μ˜ --을 μ•ˆμ¨μ£Όλ©΄ --nocaptureλΌλŠ” μ˜΅μ…˜μ„ testλͺ…λ Ήμ˜ μ˜΅μ…˜μ΄ μ•„λ‹Œ cargo의 μ‹€ν–‰ μ˜΅μ…˜μœΌλ‘œ μƒκ°ν•˜κΈ° λ•Œλ¬Έμž…λ‹ˆλ‹€. λ‹€μŒμ€ cargoλ₯Ό μœ„ν•œ --quiet μ˜΅μ…˜κ³Ό testλ₯Ό μœ„ν•œ --nocapture μ˜΅μ…˜μ„ λ‘˜ λ‹€ μ§€μ •ν•΄μ„œ μ‹€ν–‰ν•œ 것을 λ³΄μ—¬μ€λ‹ˆλ‹€.

lib-example $ cargo test it_works --quiet -- --nocapture

running 1 test
Try 2 + 2
.
test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

cargoλͺ…령은 --quiet μ˜΅μ…˜μ„ λ°›μ•„μ„œ λΉŒλ“œμ— κ΄€ν•œ 둜그 메세지λ₯Ό 좜λ ₯ν•˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€. 그리고 testλͺ…령은 --nocapture μ˜΅μ…˜μ„ λ°›μ•„μ„œ 디버깅 메세지λ₯Ό 좜λ ₯ν•΄μ€λ‹ˆλ‹€.

λ‹€μŒκ³Ό 같이 νŠΉμ • ν…ŒμŠ€νŠΈ ν•¨μˆ˜μ˜ 이름을 μ§€μ •ν•˜μ§€ μ•ŠμœΌλ©΄ λͺ¨λ“  ν…ŒμŠ€νŠΈλ₯Ό λ‹€ μ‹€ν–‰ν•΄μ€λ‹ˆλ‹€. λ‹€μŒ μ‹€ν–‰ κ²°κ³Όλ₯Ό 보면 μ‹€ν–‰λœ 각 ν…ŒμŠ€νŠΈμ˜ 이름과 λͺ‡κ°œμ˜ ν…ŒμŠ€νŠΈκ°€ μ„±κ³΅ν•˜κ³  μ‹€νŒ¨ν–ˆλŠ”μ§€λ₯Ό 확인할 수 μžˆμŠ΅λ‹ˆλ‹€.

lib-example $ cargo test
    Finished `test` profile [unoptimized + debuginfo] target(s) in 0.09s
     Running unittests src/lib.rs (target/debug/deps/lib_example-89f31e00332d9f1d)

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

   Doc-tests lib_example

running 0 tests

test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

톡합 ν…ŒμŠ€νŠΈ

톡합 ν…ŒμŠ€νŠΈλŠ” μœ λ‹› ν…ŒμŠ€νŠΈμ™€ ν˜•νƒœλŠ” λ™μΌν•©λ‹ˆλ‹€. 단지 μœ λ‹› ν…ŒμŠ€νŠΈλŠ” 각 μ†ŒμŠ€ νŒŒμΌλ§ˆλ‹€ λ§Œλ“€μ–΄μ€€λ‹€λ©΄ 톡합 ν…ŒμŠ€νŠΈλŠ” λ³„λ„μ˜ testsλΌλŠ” 디렉토리에 λ§Œλ“€μ–΄μ€€λ‹€λŠ” 차이가 μžˆμŠ΅λ‹ˆλ‹€. lib-example μ˜ˆμ œμ—μ„œ λ‹€μŒκ³Ό 같이 tests 디렉토리λ₯Ό λ§Œλ“€κ³ , tests/integration_add.rs νŒŒμΌμ„ μƒμ„±ν•΄μ£Όκ² μŠ΅λ‹ˆλ‹€.

lib-example % ls tests 
integration_add.rs
#[test]
fn test_integration_add() {
    assert_eq!(6, lib_example::add(2, 4));
}

cargo test λͺ…령을 μ‹€ν–‰ν•˜λ©΄ λͺ¨λ“  μœ λ‹›ν…ŒμŠ€νŠΈμ™€ ν†΅ν•©ν…ŒμŠ€νŠΈλ₯Ό μ „λΆ€ μ‹€ν–‰ν•΄μ€λ‹ˆλ‹€. λ§ˆμ°¬κ°€μ§€λ‘œ test_integration_add만 λ”°λ‘œ μ‹€ν–‰ν•  μˆ˜λ„ μžˆμŠ΅λ‹ˆλ‹€.

 lib-example $ cargo test
    Finished `test` profile [unoptimized + debuginfo] target(s) in 0.86s
     Running unittests src/lib.rs (target/debug/deps/lib_example-89f31e00332d9f1d)

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 tests/integration_add.rs (target/debug/deps/integration_add-189703c86c5c305d)

running 1 test
test test_integration_add ... ok

test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

   Doc-tests lib_example

running 0 tests

test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

주석에 λ“€μ–΄μžˆλŠ” ν…ŒμŠ€νŠΈ

μœ λ‹› ν…ŒμŠ€νŠΈμ™€ 톡합 ν…ŒμŠ€νŠΈλ₯Ό μ‹€ν–‰ν•΄λ³΄μ•˜μŠ΅λ‹ˆλ‹€. 그런데 cargo test λͺ…령을 μ‹€ν–‰ν•˜λ©΄ 총 3가지 ν…ŒμŠ€νŠΈλ₯Ό μ‹€ν–‰ν•˜λŠ” 것을 λ³Ό 수 μžˆμŠ΅λ‹ˆλ‹€. μ²«λ²ˆμ§ΈλŠ” μœ λ‹› ν…ŒμŠ€νŠΈμ΄κ³ , λ‘λ²ˆμ§ΈλŠ” 톡합 ν…ŒμŠ€νŠΈκ°€ μ‹€ν–‰λ©λ‹ˆλ‹€. 그리고 λ§ˆμ§€λ§‰μ—λŠ” Doc-testsλΌλŠ”κ²Œ μ‹€ν–‰λ©λ‹ˆλ‹€. 이전에 lib-exampleμ—μ„œ cargo testλ₯Ό μ‹€ν–‰ν–ˆμ„λ•Œ μ•„λž˜μ™€ 같이 Doc-testsλΌλŠ”κ²Œ 0개 μ‹€ν–‰λ˜μ—ˆλ‹€λŠ” 메세지λ₯Ό 보셨을 κ²ƒμž…λ‹ˆλ‹€.

   Doc-tests lib_example

running 0 tests

test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

λͺ…μ‹œμ μœΌλ‘œ ν…ŒμŠ€νŠΈ ν•¨μˆ˜λ₯Ό λ”°λ‘œ λ§Œλ“€μ–΄μ„œ μ‹€ν–‰ν•˜λŠ” ν…ŒμŠ€νŠΈλ„ μžˆμ§€λ§Œ λ‹€μŒκ³Ό 같이 주석 μ•ˆμ— 예제 μ½”λ“œλ₯Ό λ„£κ³  마치 각 ν•¨μˆ˜μ˜ μœ λ‹› ν…ŒμŠ€νŠΈμΈκ²ƒ 처럼 μ‹€ν–‰ν•  μˆ˜λ„ μžˆμŠ΅λ‹ˆλ‹€. λ‹€μŒ μ˜ˆμ œλŠ” lib-example νŒ¨ν‚€μ§€μ—μžˆλŠ” src/lib.rs νŒŒμΌμž…λ‹ˆλ‹€. addν•¨μˆ˜μ— 주석을 μΆ”κ°€ν•˜κ³ , 주석 μ•ˆμ— ν…ŒμŠ€νŠΈ μ½”λ“œλ₯Ό λ„£μ–΄μ€€ 것을 λ³Ό 수 μžˆμŠ΅λ‹ˆλ‹€.

/// '/'λ₯Ό 3개λ₯Ό μ¨μ„œ 주석을 λ§Œλ“€κ³ , μ²«μ€„μ—λŠ” ν•¨μˆ˜μ— λŒ€ν•œ 짧은 μ†Œκ°œλ₯Ό μ”λ‹ˆλ‹€.
///
/// 곡백 ν•œμ€„μ„ λ§Œλ“  ν›„, μ—¬κΈ°μ—λŠ” ν•¨μˆ˜μ— λŒ€ν•œ μžμ„Έν•œ μ„€λͺ…을 μ”λ‹ˆλ‹€.
/// μ„€λͺ…이 λλ‚˜λ©΄ μ•„λž˜μ— 곡백 ν•œμ€„μ„ λ§Œλ“  ν›„ ```와 ```둜 μ½”λ“œμ˜ μ‹œμž‘κ³Ό 끝을 ν‘œμ‹œν•©λ‹ˆλ‹€.
/// ν•¨μˆ˜λ₯Ό ν˜ΈμΆœν• λ•ŒλŠ” μ΄λ¦„λ§Œ μ¨μ£ΌλŠ”κ²Œ μ•„λ‹ˆλΌ 크레이트의 이름도 같이 μ¨μ£Όμ–΄μ•Όν•©λ‹ˆλ‹€.
/// ν˜„μž¬ 이 ν¬λ ˆμ΄νŠΈλŠ” lib_exampleμž…λ‹ˆλ‹€.
///
/// ```
/// assert_eq!(6, lib_example::add(2, 4));
/// ```
pub fn add(left: u64, right: u64) -> u64 {
    left + right
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn it_works() {
        let result = add(2, 2);
        println!("Try 2 + 2");
        assert_eq!(result, 4);
    }
}

주석에도 μ¨λ†¨μ§€λ§Œ, ν…ŒμŠ€νŠΈλ‘œ μ‚¬μš©ν•  주석은 //κ°€ μ•„λ‹ˆλΌ ///λ₯Ό μ‚¬μš©ν•΄μ•Όν•˜λŠ”κ±Έ κΈ°μ–΅ν•΄μ£Όμ‹œκΈ° λ°”λžλ‹ˆλ‹€. 그럼 cargo testλ₯Ό λ‹€μ‹œ μ‹€ν–‰ν•΄λ³΄κ² μŠ΅λ‹ˆλ‹€.

lib-example $ cargo test
    Finished `test` profile [unoptimized + debuginfo] target(s) in 0.25s
     Running unittests src/lib.rs (target/debug/deps/lib_example-89f31e00332d9f1d)

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 tests/integration_add.rs (target/debug/deps/integration_add-189703c86c5c305d)

running 1 test
test test_integration_add ... ok

test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

   Doc-tests lib_example

running 1 test
test src/lib.rs - add (line 8) ... ok

test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.50s

λ§ˆμ§€λ§‰μ— μ‹€ν–‰λœ Doc-tests에 1개의 ν…ŒμŠ€νŠΈκ°€ μΆ”κ°€λ˜μ—ˆμŠ΅λ‹ˆλ‹€. ν…ŒμŠ€νŠΈμ—λŠ” λ³„λ„μ˜ 이름이 μ—†μœΌλ‹ˆ ν…ŒμŠ€νŠΈ 이름이 μ•„λ‹ˆλΌ ν•¨μˆ˜ 이름과 μ£Όμ„μ•ˆμ— μžˆλŠ” ν…ŒμŠ€νŠΈ μ½”λ“œκ°€ μ‹œμž‘λ˜λŠ” 쀄 λ²ˆν˜Έκ°€ 좜λ ₯λ©λ‹ˆλ‹€.

λ‹€μŒκ³Ό 같이 ν•˜λ‚˜μ˜ ν•¨μˆ˜μ— ν…ŒμŠ€νŠΈκ°€ μ—¬λŸ¬κ°œ μžˆμ–΄λ„ λ³„κ°œμ˜ ν…ŒμŠ€νŠΈλ‘œ μ‹€ν–‰λ©λ‹ˆλ‹€.

/// '/'λ₯Ό 3개λ₯Ό μ¨μ„œ 주석을 λ§Œλ“€κ³ , μ²«μ€„μ—λŠ” ν•¨μˆ˜μ— λŒ€ν•œ 짧은 μ†Œκ°œλ₯Ό μ”λ‹ˆλ‹€.
///
/// 곡백 ν•œμ€„μ„ λ§Œλ“  ν›„, μ—¬κΈ°μ—λŠ” ν•¨μˆ˜μ— λŒ€ν•œ μžμ„Έν•œ μ„€λͺ…을 μ”λ‹ˆλ‹€.
/// μ„€λͺ…이 λλ‚˜λ©΄ μ•„λž˜μ— 곡백 ν•œμ€„μ„ λ§Œλ“  ν›„ ```와 ```둜 μ½”λ“œμ˜ μ‹œμž‘κ³Ό 끝을 ν‘œμ‹œν•©λ‹ˆλ‹€.
/// ν•¨μˆ˜λ₯Ό ν˜ΈμΆœν• λ•ŒλŠ” μ΄λ¦„λ§Œ μ¨μ£ΌλŠ”κ²Œ μ•„λ‹ˆλΌ 크레이트의 이름도 같이 μ¨μ£Όμ–΄μ•Όν•©λ‹ˆλ‹€.
/// ν˜„μž¬ 이 ν¬λ ˆμ΄νŠΈλŠ” lib_exampleμž…λ‹ˆλ‹€.
///
/// ```
/// assert_eq!(6, lib_example::add(2, 4));
/// ```
///
/// ```
/// assert_eq!(0, lib_example::add(0, 0));
/// ```
pub fn add(left: u64, right: u64) -> u64 {
    left + right
}

λ‹€μŒμ€ add ν•¨μˆ˜μ˜ 주석에 μžˆλŠ” ν…ŒμŠ€νŠΈλ§Œ λ³„λ„λ‘œ μ‹€ν–‰ν•˜λ„λ‘ cargo test λͺ…령에 --doc add μ˜΅μ…˜μ„ μΆ”κ°€ν•΄μ„œ μ‹€ν–‰ν•œ κ²ƒμž…λ‹ˆλ‹€. 2개의 ν…ŒμŠ€νŠΈκ°€ μ‹€ν–‰λ˜μ—ˆλ‹€λŠ” 것을 λ³Ό 수 μžˆμŠ΅λ‹ˆλ‹€.

lib-example $ cargo test --doc add
    Finished `test` profile [unoptimized + debuginfo] target(s) in 0.15s
   Doc-tests lib_example

running 2 tests
test src/lib.rs - add (line 12) ... ok
test src/lib.rs - add (line 8) ... ok

test result: ok. 2 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.58s

cargo doc

주석에 ν…ŒμŠ€νŠΈλ₯Ό λ„£λŠ” 것을 μ†Œκ°œν•˜λ©΄μ„œ 주석에 λŒ€ν•œ 이야기기 λ‚˜μ™”μœΌλ‹ˆ cargoμ—μ„œ 주석과 κ΄€λ ¨λœ κΈ°λŠ₯을 ν•˜λ‚˜ μ†Œκ°œν•˜κ² μŠ΅λ‹ˆλ‹€. 일단 add에 주석과 ν…ŒμŠ€νŠΈκ°€ μΆ”κ°€λœ μƒνƒœμ—μ„œ lib-example μ½”λ“œμ˜ μƒνƒœ κ·ΈλŒ€λ‘œ λ‹€μŒ λͺ…령을 μ‹€ν–‰ν•΄λ³΄κ² μŠ΅λ‹ˆλ‹€.

lib-example % cargo doc --open        
 Documenting lib-example v0.1.0 (/Users/user/study/lib-example)
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.43s
     Opening /Users/user/study/lib-example/target/doc/lib_example/index.html

λΈŒλΌμš°μ €μ— λ‹€μŒκ³Ό 같이 lib_example ν¬λ ˆμ΄νŠΈμ— λŒ€ν•œ λ¬Έμ„œκ°€ λ‚˜νƒ€λ‚  κ²ƒμž…λ‹ˆλ‹€.

lib_example

이 μ‚¬μ΄νŠΈλŠ” lib-example νŒ¨ν‚€μ§€ μ•ˆμ—μžˆλŠ” target/doc/lib_example 디렉토리에 μƒμ„±λ©λ‹ˆλ‹€.

lib-example $ ls target/doc/lib_example 
all.html         fn.add.html      index.html       sidebar-items.js

μ†ŒμŠ€ 파일이 add.rs의 주석을 λͺ¨μ•„놓은 fn.add.html 파일이 μƒμ„±λœ 것을 λ³Ό 수 μžˆμŠ΅λ‹ˆλ‹€. index.htmlμ—μ„œ add ν•¨μˆ˜λ₯Ό ν΄λ¦­ν•˜λ©΄ fn.add.html 파일이 μ—΄λ¦½λ‹ˆλ‹€.

cargo doc λͺ…령은 νŒ¨ν‚€μ§€ 전체에 μžˆλŠ” λͺ¨λ“  주석을 λΆ„μ„ν•΄μ„œ 이런 λ¬Έμ„œν™” μ‚¬μ΄νŠΈλ₯Ό λ§Œλ“œλŠ” 일을 ν•©λ‹ˆλ‹€. 그리고 https://doc.rust-lang.org/std/index.html 와 같이 러슀트의 크레이트 λŒ€λΆ€λΆ„μ΄ cargo doc 으둜 μƒμ„±λœ 메뉴얼 μ‚¬μ΄νŠΈλ₯Ό 가지고 μžˆμŠ΅λ‹ˆλ‹€.

std 크레이트의 메뉴얼 μ‚¬μ΄νŠΈ https://doc.rust-lang.org/std/index.html λ₯Ό 보면 std μžμ²΄μ— λŒ€ν•œ μ„€λͺ…λΆ€ν„° μ‹œμž‘ν•΄μ„œ std ν¬λ ˆμ΄νŠΈμ—μ„œ μ •μ˜λœ νƒ€μž…, λͺ¨λ“ˆ, 맀크둜 등등을 μ†Œκ°œν•˜κ³  μžˆμŠ΅λ‹ˆλ‹€. μš°λ¦¬λŠ” μ§€κΈˆ std 크레이트λ₯Ό λ³΄λ €λŠ”κ²Œ μ•„λ‹ˆλΌ λ¬Έμ„œν™”μ— λŒ€ν•œ 방법을 μ•Œμ•„λ³΄λ €λŠ” κ²ƒμ΄λ‹ˆ html λ¬Έμ„œλ₯Ό 볼게 μ•„λ‹ˆλΌ μ΄λ ‡κ²Œ html λ¬Έμ„œλ₯Ό μƒμ„±ν•˜λŠ” λ¬Έμ„œν™” 방법을 μ•Œμ•„λ΄μ•Όλ©λ‹ˆλ‹€. κ·ΈλŸ¬λ‹ˆ std 크레이트의 첫 ν™”λ©΄ κ°€μž₯ μœ„μͺ½μ— Crate stdλΌλŠ” 제λͺ© λ°”λ‘œ 밑에 μžˆλŠ” SourceλΌλŠ” 링크λ₯Ό λˆŒλŸ¬λ³΄κ² μŠ΅λ‹ˆλ‹€.

std

이제 std 크레이트의 μ†ŒμŠ€ μ½”λ“œ μ€‘μ—μ„œ srd/std/lib.rs 파일이 보일 κ²ƒμž…λ‹ˆλ‹€. 파일의 첫번째 쀄에 μžˆλŠ” 주석은 //!둜 μ‹œμž‘ν•˜λŠ” μ£Όμ„μž…λ‹ˆλ‹€. 이 주석은 μ†ŒμŠ€ νŒŒμΌμ— Markdown 포맷의 μœ„ν‚€ λ¬Έμ„œλ₯Ό μ €μž₯ν•˜κ²Œ ν•΄μ£ΌλŠ” μ£Όμ„μž…λ‹ˆλ‹€. Markdown 포맷은 κΉƒν—ˆλΈŒμ˜ README.md νŒŒμΌμ—λ„ μ‚¬μš©ν•˜λŠ” μœ„ν‚€ ν¬λ§·μž…λ‹ˆλ‹€. μœ„ν‚€ λ¬Έμ„œμ˜ μž‘μ„±λ²•μ— λŒ€ν•΄μ„œλŠ” κΉƒν—ˆλΈŒ μ‚¬μ΄νŠΈμ˜ μ•ˆλ‚΄ λ¬Έμ„œ(https://docs.github.com/ko/get-started/writing-on-github/getting-started-with-writing-and-formatting-on-github/basic-writing-and-formatting-syntax)λ₯Ό μ°Έκ³ ν•˜μ‹œκΈ° λ°”λžλ‹ˆλ‹€.

κ·Έ λ‹€μŒμœΌλ‘œ λ³΄μ΄λŠ” 주석듀은 ///을 μ‚¬μš©ν•œ κ²ƒλ“€μž…λ‹ˆλ‹€. 참고둜 //와 같이 /λ₯Ό 2번만 μ‚¬μš©ν•œ 주석은 λ¬Έμ„œμ— λ‚˜νƒ€λ‚˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€. 각 ν•¨μˆ˜λ‚˜ ꡬ쑰체, 맀크둜, 직접 μ •μ˜ν•œ νƒ€μž… λ“±λ“± ν•„μš”ν•œ 곳에 ///둜 μ‹œμž‘ν•˜λŠ” 주석을 써주면 cargo doc λͺ…령이 이 주석이 ν•¨μˆ˜μΈμ§€ ꡬ쑰체인지 등을 νŒŒμ•…ν•΄μ„œ μ’…λ₯˜λ³„λ‘œ λ‚˜λˆ„κ³  html λ¬Έμ„œλ‘œ λ§Œλ“€μ–΄μ€λ‹ˆλ‹€.

μ•„λž˜λŠ” lib-example 크레이트의 src/lib.rs νŒŒμΌμ— λ‹€μŒκ³Ό 같이 λ¬Έμ„œν™”λ₯Ό μœ„ν•œ 주석을 μΆ”κ°€ν•œ μ˜ˆμ œμž…λ‹ˆλ‹€. cargo doc λͺ…λ ΉμœΌλ‘œ μ‚¬μ΄νŠΈλ₯Ό μƒμ„±ν•œ ν›„ 각 ν•¨μˆ˜μ™€ ꡬ쑰체의 주석이 λ¬Έμ„œν™” μ‚¬μ΄νŠΈμ— λ‚˜νƒ€λ‚˜λŠ” 것을 ν™•μΈν•΄λ³΄μ‹œκΈ° λ°”λžλ‹ˆλ‹€.

//! # 제λͺ©μž…λ‹ˆλ‹€.
//!
//! 이 파일 전체에 λŒ€ν•œ μ†Œκ°œλ₯Ό λ‹΄κ³  μžˆμŠ΅λ‹ˆλ‹€.
//! * 이런 Markdown 문법듀을 μ‚¬μš©ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

/// '/'λ₯Ό 3개λ₯Ό μ¨μ„œ 주석을 λ§Œλ“€κ³ , μ²«μ€„μ—λŠ” ν•¨μˆ˜μ— λŒ€ν•œ 짧은 μ†Œκ°œλ₯Ό μ”λ‹ˆλ‹€.
///
/// 곡백 ν•œμ€„μ„ λ§Œλ“  ν›„, μ—¬κΈ°μ—λŠ” ν•¨μˆ˜μ— λŒ€ν•œ μžμ„Έν•œ μ„€λͺ…을 μ”λ‹ˆλ‹€.
/// μ„€λͺ…이 λλ‚˜λ©΄ μ•„λž˜μ— 곡백 ν•œμ€„μ„ λ§Œλ“  ν›„ ```와 ```둜 μ½”λ“œμ˜ μ‹œμž‘κ³Ό 끝을 ν‘œμ‹œν•©λ‹ˆλ‹€.
/// ν•¨μˆ˜λ₯Ό ν˜ΈμΆœν• λ•ŒλŠ” μ΄λ¦„λ§Œ μ¨μ£ΌλŠ”κ²Œ μ•„λ‹ˆλΌ 크레이트의 이름도 같이 μ¨μ£Όμ–΄μ•Όν•©λ‹ˆλ‹€.
/// ν˜„μž¬ 이 ν¬λ ˆμ΄νŠΈλŠ” lib_exampleμž…λ‹ˆλ‹€.
///
/// ```
/// assert_eq!(6, lib_example::add(2, 4));
/// ```
///
/// ```
/// assert_eq!(0, lib_example::add(0, 0));
/// ```
pub fn add(left: u64, right: u64) -> u64 {
    // //둜 μ‹œμž‘ν•˜λŠ” 주석은 λ¬Έμ„œν™”κ°€ λ˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€.
    left + right
}

/// ꡬ쑰체의 λ¬Έμ„œν™”μ— λŒ€ν•œ μ˜ˆμ œμž…λ‹ˆλ‹€.
///
/// ꡬ쑰체에 λŒ€ν•œ μ„€λͺ…을 μ μŠ΅λ‹ˆλ‹€.
/// λ‹€λ₯Έ ν•­λͺ©μ— λŒ€ν•œ λ§ν¬λŠ” [`add`]와 같은 ν˜•νƒœλ‘œ 적으면 μžλ™μœΌλ‘œ addν•¨μˆ˜μ— λŒ€ν•œ 링크λ₯Ό μƒμ„±ν•΄μ€λ‹ˆλ‹€.
///
/// # Examples
///
/// μ΄λ ‡κ²Œ 이 ꡬ쑰체λ₯Ό μ‚¬μš©ν•˜λŠ” 예제λ₯Ό 주석에 넣을 μˆ˜λ„ μžˆμŠ΅λ‹ˆλ‹€. 이 μ˜ˆμ œλ„ cargo testμ—μ„œ μ‹€ν–‰λ©λ‹ˆλ‹€.
///
/// ```
/// let ex = lib_example::StructExample::new();
/// ```
pub struct StructExample {
    /// foo ν•„λ“œμ— λŒ€ν•œ μ„€λͺ…을 μ μŠ΅λ‹ˆλ‹€.
    pub foo: usize,
    /// pub이 μ—†λŠ” ν•„λ“œλŠ” private ν•„λ“œμž…λ‹ˆλ‹€. 주석을 써도 λ¬Έμ„œ μ‚¬μ΄νŠΈμ— 보여주지 μ•ŠμŠ΅λ‹ˆλ‹€.
    bar: Option<String>,
}

impl StructExample {
    pub fn new() -> Self {
        StructExample { foo: 0, bar: None }
    }
}
lib-example $ cargo doc --open
 Documenting lib-example v0.1.0 (/Users/user/study/lib-example)
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.44s
     Opening /Users/user/study/lib-example/target/doc/lib_example/index.html
user@AL02279337 lib-example % 

lib-example