cargo、crates.io
本章內容
- 通過 release profile 來自定義構建
- 在https://crates.io/上發布庫
- 通過 workspaces 組織大工程
- 從 https://crates.io/來安裝庫
- 使用自定義命令擴展 cargo
一、通過 release profile 來自定義構建
release profile (發布配置)
- release profile:
- 是預定義的
- 可自定義:可使用不同的配置,對代碼編譯擁有更多的控制
- 每個 profile 的配置都獨立于其它的 profile
- cargo 主要的兩個 profile:
- dev profile:適用于開發,cargo build
- release profile:適用于發布,cargo build --release
自定義 profile
- 針對每個 profile,Cargo 都提供了默認的配置
- 如果想自定義 xxxx profile 的配置:
- 可以在 Cargo.toml 里添加 [profile.xxxx] 區域,在里面覆寫默認配置的子集
[package]
name = "closure"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
[profile.dev]
opt-level = 1
[profile.release]
opt-level = 3
執行
closure on master [?] is ?? 0.1.0 via ?? 1.67.1 took 2.9s
? cargo build
Compiling closure v0.1.0 (/Users/qiaopengjun/rust/closure)
Finished dev [optimized + debuginfo] target(s) in 0.16s
closure on master [?] is ?? 0.1.0 via ?? 1.67.1
?
- 對于每個配置的默認值和完整選項,請參見:https://doc.rust-lang.org/cargo/
二、發布 crate 到 crates.io (1)
Crates.io
- 可以通過發布包來共享你的代碼
- crate 的注冊表在 https://crates.io/
- 它會分發已注冊的包的源代碼
- 主要托管開源的代碼
檔案注釋
- 檔案注釋:用于生成檔案
- 生成 HTML 檔案
- 顯式公共 API 的檔案注釋:如何使用API
- 使用 ///
- 支持 Markdown
- 放置在被說明條目之前
生成 HTML 檔案的命令
- cargo doc
- 它會運行 rustdoc 工具(Rust 安裝包自帶)
- 把生成的 HTML 檔案放在 target/doc 目錄下
- cargo doc --open:
- 構建當前crate的檔案(也包含 crate 依賴項的檔案)
- 在瀏覽器打開檔案
/// Adds one to the number given.
///
/// # Examples
///
/// ```
/// let arg = 5;
/// let answer = my_crate::add_one(arg);
///
/// assert_eq!(6, answer);
/// ```
pub fn add_one(x: i32) -> i32 {
x + 1
}
運行
closure on master [?] is ?? 0.1.0 via ?? 1.67.1
? cargo doc
Documenting closure v0.1.0 (/Users/qiaopengjun/rust/closure)
Finished dev [optimized + debuginfo] target(s) in 0.39s
closure on master [?] is ?? 0.1.0 via ?? 1.67.1
? cargo doc --open
Finished dev [optimized + debuginfo] target(s) in 0.00s
Opening /Users/qiaopengjun/rust/closure/target/doc/closure/index.html
closure on master [?] is ?? 0.1.0 via ?? 1.67.1
? cargo doc --open
Documenting closure v0.1.0 (/Users/qiaopengjun/rust/closure)
Finished dev [optimized + debuginfo] target(s) in 0.41s
Opening /Users/qiaopengjun/rust/closure/target/doc/closure/index.html
closure on master [?] is ?? 0.1.0 via ?? 1.67.1
常用章節
# Examples- 其它常用的章節:
- Panics:函式可能發生 panic 的場景
- Errors:如果函式回傳 Result,描述可能的錯誤種類,以及可導致錯誤的條件
- Safety:如果函式處于 unsafe 呼叫,就應該解釋函式 unsafe 的原因,以及呼叫者確保的使用前提,
檔案注釋作為測驗
- 示例代碼塊的附加值:
- 運行 cargo test:將把檔案注釋中的示例代碼作為測驗來運行
/// Adds one to the number given.
///
/// # Examples
///
/// ```
/// let arg = 5;
/// let answer = closure::add_one(arg);
///
/// assert_eq!(6, answer);
/// ```
pub fn add_one(x: i32) -> i32 {
x + 1
}

為包含注釋的項添加檔案注釋
- 符號://!
- 這類注釋通常用描述 crate 和模塊:
- crate root(按慣例 src/lib.rs)
- 一個模塊內,將 crate 或模塊作為一個整體進行記錄
//! # Closure Crate
//!
//! `closure` is a collection of utilities to make performance
//! calculations more convenient.
/// Adds one to the number given.
///
/// # Examples
///
/// ```
/// let arg = 5;
/// let answer = closure::add_one(arg);
///
/// assert_eq!(6, answer);
/// ```
pub fn add_one(x: i32) -> i32 {
x + 1
}

三、pub use
使用 pub use 匯出方便使用的公共 API
- 問題:crate 的程式結構在開發時對于開發者很合理,但對于它的使用者不夠方便
- 開發者會把程式結構分為很多層,使用者想找到這種深層結構中的某個型別很費勁
- 例如:
- 麻煩:
my_crate::some_module::another_module::UsefulType; - 方便:
my_crate::UsefulType;
- 麻煩:
- 解決辦法:
- 不需要重新組織內部代碼結構
- 使用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 {
SecondaryColor::Green
}
}
src/main.rs 檔案
use art::kinds::PrimaryColor;
use art::utils::mix;
fn main() {
let red = PrimaryColor::Red;
let yellow = PrimaryColor::Yellow;
mix(red, yellow);
}
優化之后:
src/lib.rs 檔案
//! # 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 {
/// 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 {
SecondaryColor::Green
}
}
src/main.rs 檔案
// use art::kinds::PrimaryColor;
// use art::utils::mix;
use art::PrimaryColor;
use art::mix;
fn main() {
let red = PrimaryColor::Red;
let yellow = PrimaryColor::Yellow;
mix(red, yellow);
}

四、發布 crate 到 crates.io(2)
創建并設定 Crates.io 賬號
- 發布 crate 前,需要在 crates.io 創建賬號并獲得 API token
- 運行命令:cargo login [你的 API token]
- 通知 cargo,你的 API token 存盤在本地 ~/.cargo/credentials
- API token 可以在https://crates.io/進行撤銷
為新的crate 添加元資料
- 在發布crate之前,需要在 Cargo.toml 的 [package] 區域為 crate 添加一些元資料:
- crate 需要唯一的名稱:name
- description:一兩句話即可,會出現在 crate 搜索的結果里
- license:需提供許可證標識值(可到 http://spdx.org/licenses/查找)
- 可指定多個 license:用 OR
- version
- author
- 發布:cargo publish 命令
rust_tutorials on master [?] via ?? 1.67.1
? cargo login --registry crates-io
please paste the token found on https://crates.io/me below
ciopLk54SDAxB200gA4jk85abcdefgabcabc # token
Login token for `crates-io` saved
rust_tutorials on master [?] via ?? 1.67.1 took 1m 27.6s
?
rust_tutorials on master [?] via ?? 1.67.1 took 2.0s
? cargo publish --registry crates-io --allow-dirty
Updating crates.io index
發布到 Crates.io
- Crate 一旦發布,就是永久性的:該版本無法覆寫,代碼無法洗掉
- 目的:依賴于該版本的專案可繼續正常作業
發布已存在 crate 的新版本
- 修改 crate 后,需要先修改 Cargo.toml 里面的version 值,再進行重新發布
- 參照http://semver.org/來使用你的語意版本
- 再執行 cargo publish 進行發布
使用 cargo yank 從 Crates.io 撤回版本
- 不可以洗掉 crate 之前的版本
- 但可以防止其它專案把它作為新的依賴:yank(撤回)一個 crate 版本
- 防止新專案依賴于該版本
- 已經存在專案可繼續將其作為依賴(并可下載)
- yank 意味著:
- 所有已經產生 Cargo.lock 的專案都不會中斷
- 任何將來生成的 Cargo.lock 檔案都不會使用被 yank 的版本
- 命令:
- yank 一個版本(不會洗掉任何代碼):cargo yank --vers 1.0.1
- 取消 yank:cargo yank --vers 1.0.1 --undo
五、Cargo 作業空間
Cargo 作業空間(Workspaces)
- cargo 作業空間:幫助管理多個相互關聯且需要協同開發的 crate
- cargo 作業空間是一套共享同一個 Cargo.lock 和輸出檔案夾的包
創建作業空間
- 有多種方式來組建作業空間例:1個二進制 crate,2個庫 crate
- 二進制 crate:main函式,依賴于其它2個crate
- 其中1個庫crate 提供 add_one 函式
- 另外1個庫crate 提供 add_two 函式
~/rust
? mcd add # mkdir add cd add
~/rust/add
? touch Cargo.toml
~/rust/add via ?? 1.67.1
? c # code .
~/rust/add via ?? 1.67.1
?
~/rust/add via ?? 1.67.1
? cargo new adder
warning: compiling this new package may not work due to invalid workspace configuration
current package believes it's in a workspace when it's not:
current: /Users/qiaopengjun/rust/add/adder/Cargo.toml
workspace: /Users/qiaopengjun/rust/add/Cargo.toml
this may be fixable by adding `adder` to the `workspace.members` array of the manifest located at: /Users/qiaopengjun/rust/add/Cargo.toml
Alternatively, to keep it out of the workspace, add the package to the `workspace.exclude` array, or add an empty `[workspace]` table to the package's manifest.
Created binary (application) `adder` package
~/rust/add via ?? 1.67.1
? cargo build
Compiling adder v0.1.0 (/Users/qiaopengjun/rust/add/adder)
Finished dev [unoptimized + debuginfo] target(s) in 0.48s
~/rust/add via ?? 1.67.1
~/rust/add via ?? 1.67.1
? cargo new add-one --lib
Created library `add-one` package
~/rust/add via ?? 1.67.1
?
add-one/src/lib.rs 檔案
pub fn add_one(x: i32) -> i32 {
x + 1
}
adder/src/main.rs 檔案
use add_one;
fn main() {
let num = 10;
println!("Hello, world! {} plus one is {}", num, add_one::add_one(num));
}
adder/Cargo.toml 檔案
[package]
name = "adder"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
add-one = { path = "../add-one" }
rust/add/Cargo.toml 檔案
[workspace]
members = [
"adder",
"add-one",
]
運行
~/rust/add via ?? 1.67.1
? cargo build
Compiling add-one v0.1.0 (/Users/qiaopengjun/rust/add/add-one)
Compiling adder v0.1.0 (/Users/qiaopengjun/rust/add/adder)
Finished dev [unoptimized + debuginfo] target(s) in 0.30s
~/rust/add via ?? 1.67.1
? cargo run -p adder
Finished dev [unoptimized + debuginfo] target(s) in 0.00s
Running `target/debug/adder`
Hello, world! 10 plus one is 11
~/rust/add via ?? 1.67.1
?
在作業空間中依賴外部 crate
- 作業空間只有一個 Cargo.lock 檔案,在作業空間的頂層目錄
- 保證作業空間內所有 crate 使用的依賴的版本都相同
- 作業空間內所有 crate 相互兼容
為作業空間添加測驗
rust/add/add-one/src/lib.rs 檔案
pub fn add_one(x: i32) -> i32 {
x + 1
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn it_works() {
assert_eq!(3, add_one(2));
}
}
執行測驗
~/rust/add via ?? 1.67.1
? cargo test
Compiling add-one v0.1.0 (/Users/qiaopengjun/rust/add/add-one)
Compiling adder v0.1.0 (/Users/qiaopengjun/rust/add/adder)
Finished test [unoptimized + debuginfo] target(s) in 0.13s
Running unittests src/lib.rs (target/debug/deps/add_one-cb079acb8d173784)
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 unittests src/main.rs (target/debug/deps/adder-23a2e001f7410351)
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
~/rust/add via ?? 1.67.1
?
~/rust/add via ?? 1.67.1
? cargo test -p add-one
Finished test [unoptimized + debuginfo] target(s) in 0.00s
Running unittests src/lib.rs (target/debug/deps/add_one-cb079acb8d173784)
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 add-one
running 0 tests
test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
~/rust/add via ?? 1.67.1
?
六、從 CRATES.IO 安裝二進制 crate
從 CRATES.IO 安裝二進制 crate
- 命令:cargo install
- 來源:https://crates.io
- 限制:只能安裝具有二進制目標(binary target)的 crate
- 二進制目標 binary target:是一個可運行程式
- 由擁有 src/main.rs 或其它被指定為二進制檔案的 crate 生成
- 通常:README 里有關于 crate 的描述:
- 擁有 library target
- 擁有 binary target
- 兩者兼備
cargo install
- cargo install 安裝的二進制存放在根目錄的 bin 檔案夾
- 如果你用 rustup 安裝的 Rust,沒有任何自定義配置,那么二進制存放目錄是 $HOME/.cargo/bin
- 要確保該目錄在環境變數 $PATH 中
~/rust took 2m 8.1s
? cargo install rust_tutorials_qiao
Updating `tuna` index
Downloaded rust_tutorials_qiao v0.1.0 (registry `tuna`)
Downloaded 1 crate (759 B) in 3.43s
Installing rust_tutorials_qiao v0.1.0
Compiling rust_tutorials_qiao v0.1.0
Finished release [optimized] target(s) in 3.99s
Installing /Users/qiaopengjun/.cargo/bin/rust_tutorials_qiao
Installed package `rust_tutorials_qiao v0.1.0` (executable `rust_tutorials_qiao`)
~/rust took 4.0s
?
? rust_tutorials_qiao
Hello, world!
~/rust took 3.1s
?
~/rust took 3.1s
? echo $PATH # 查看PATH環境變數
使用自定義命令擴展 cargo
- cargo 被設計成可以使用子命令來擴展
- 例:如果 $PATH 中的某個二進制是 cargo-something,你可以像子命令一樣運行:
- cargo something
- 類似這樣的自定義命令可以通過該命令列出:
cargo --list - 優點:可使用 cargo install 來安裝擴展,像內置工具一樣來運行
? 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
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
init Create a new cargo package in an existing directory
install Install a Rust binary. Default location is $HOME/.cargo/bin
locate-project Print a JSON representation of a Cargo.toml file's location
login Save an api token from the registry locally. If token is not specified, it will be read from stdin.
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 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
~/rust
本文來自博客園,作者:QIAOPENGJUN,轉載請注明原文鏈接:https://www.cnblogs.com/QiaoPengjun/p/17301329.html
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/549567.html
標籤:其他
