最後更新: 2024-09-13
目錄
- Cargo
- build & run Opts
- Configuration file
- Optimization
介紹
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
優先等級
- /projects/foo/bar/baz/.cargo/config.toml
- /projects/foo/bar/.cargo/config.toml
- /projects/foo/.cargo/config.toml
- /projects/.cargo/config.toml
- /.cargo/config.toml
- $CARGO_HOME/config.toml
- $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", ]