Cargo & Crate

最後更新: 2024-09-13

目錄

 


介紹

Cargo is Rust’s build system and package manager.

A crate is a collection of Rust source code files.

 


Cargo

 

Creating a Project with Cargo

cargo new hello_cargo

tree hello_cargo

hello_cargo/
├── Cargo.toml
└── src
    └── main.rs

 * Cargo expects your source files to live inside the src directory

File: Cargo.toml

A recipe for your Rust project (info, dependencies)

 * toml = Tom’s Obvious, Minimal Language format # Cargo’s configuration format

 * edition = "2021" # At the time of this writing, three Rust editions are available (2015, 2018)

Doc: https://doc.rust-lang.org/cargo/reference/manifest.html

Dependencies

e.g.

[dependencies]
rand = "0.8.5"

0.8.5 is actually shorthand for ^0.8.5

^0.8.5 means any version that is at least 0.8.5 but below 0.9.0

Cargo fetches the latest versions of everything that dependency needs
from the registry (https://crates.io/)

[package] 內的 edition

...

File: Cargo.lock

Cargo has a mechanism that ensures you can rebuild the same artifact. <= Cargo.lock

It is generated automatically by cargo. (The first time you run cargo build)

The exact versions of each dependency used in your project at a particular point in time.

# It will ignore the Cargo.lock file and
# figure out all the latest versions that fit your specifications in Cargo.toml

cargo update

 



Build & Run

 

Debug Build

cargo build

# cargo build && ./target/debug/hello_cargo

cargo run

測試是否 build 到

# doesn’t produce an executable. much faster than 'cargo build'.

cargo check

Optimizations Build

# To compile it with optimizations

cargo build --release

 


build Opts & run Opts

 

build

cargo build [Opts]

# Compile the current package

 * build 後不會 run

Dev builds are the default. no optimize

The compiled code will be placed in the target/debug

Opts

-r, --release

Build optimized artifacts with the release profile
The --release flag is equivalent to "--profile=release"

run

cargo run    # Run the current package

clean

cargo clean  # Remove generated artifacts

--release    Remove all artifacts in the "release directory"

 


Configuration file

 

優先等級

  1. /projects/foo/bar/baz/.cargo/config.toml
  2. /projects/foo/bar/.cargo/config.toml
  3. /projects/foo/.cargo/config.toml
  4. /projects/.cargo/config.toml
  5. /.cargo/config.toml
  6. $CARGO_HOME/config.toml
  7. $HOME/.cargo/config.toml

If a key is specified in multiple config files, the values will get merged together.

Numbers, strings, and booleans will use the value in the deeper config directory taking precedence over ancestor directories,
 where the home directory is the lowest priority.

Arrays will be joined together with higher precedence items being placed later in the merged array.

 


Optimization

 

  • release profiles
  • Codegen Units
  • Link-time Optimization
  • Alternative Allocators (e.g. jemalloc)
  • Remore debug Info
  • CPU Specific Instructions

release profiles

Cargo has two main profiles: the dev, release

# 0 ~ 3; Default: dev = 0; release = 3;

[profile.release]
opt-level = 3

Codegen Units

The Rust compiler splits crates into multiple codegen units to parallelize (and thus speed up) compilation.

However, this might cause it to miss some potential optimizations.

[profile.release]
codegen-units = 1

Link-time Optimization

# off, thin (opt-level 非 0 時會用它), fat(true), false (thin local LTO)

[profile.release]
lto = false

jemalloc

# It usable via the tikv-jemallocator crate

[dependencies]
tikv-jemallocator = "0.5"

# Then add the following to your Rust code, e.g. at the top of src/main.rs:

#[global_allocator]
static GLOBAL: tikv_jemallocator::Jemalloc = tikv_jemallocator::Jemalloc;

Furthermore, on Linux, jemalloc can be configured to use transparent huge pages (THP).

This can further speed up programs, possibly at the cost of higher memory usage.

MALLOC_CONF="thp:always,metadata_thp:always" cargo build --release

Remore debug Info

 * stripping makes your compiled program more difficult to debug and profile.

# To strip both debug info

strip = "symbols"

[profile.release]
strip = "debuginfo"

# To strip both debug info and symbols

[profile.release]
strip = "symbols"

CPU Specific Instructions

Custom flags to pass to all compiler invocations

.cargo/config.toml

[build]
RUSTFLAGS = ["-C", "target-cpu=native"]

 * Multiple features can be specified in a single option by separating them with commas
    ( e.g. "-C target-feature=+x,-y" )

 * Features from multiple -C target-feature options are combined

查看 Default 是用了什麼 CPU Instructions

rustc --print cfg

e.g.

debug_assertions
panic="unwind"
target_arch="x86_64"
target_endian="little"
target_env="gnu"
target_family="unix"
target_feature="fxsr"
target_feature="sse"
target_feature="sse2"
target_has_atomic="16"
target_has_atomic="32"
target_has_atomic="64"
target_has_atomic="8"
target_has_atomic="ptr"
target_os="linux"
target_pointer_width="64"
target_vendor="unknown"
unix

# 對於本地 CPU 的優化 - native

rustc -C target-cpu=native --print cfg

...
target_feature="aes"
target_feature="avx"
target_feature="avx2"
...

Built-in Targets

rustc ships with the ability to compile to many targets automatically, we call these "built-in" targets

rustc --print target-list

e.g. 指定要有的 CPU Instruction Set

.cargo/config.toml

rustflags = [
    "-C", "target-feature=+aes,+avx,+avx2,+bmi1,+bmi2,+f16c,+fma,
          +movbe,+pclmulqdq,+popcnt,+rdrand,+sse3,+ssse3,+sse4.1,+sse4.2,+xsave,+xsaveopt",
]

 


 

 

 

 

Creative Commons license icon Creative Commons license icon