rust 教程 06 crates和modules

我们将讨论rust中的crates和modules的概念来帮助组织项目

crates

rust程序是由crates组成的,每个crate是单个库或可执行文件以及一些可选信息。

当使用cargo build --verbose来构建时,可以看到依赖信息;我们也可以在Cargo.toml中指定依赖的版本信息。

[dependencies]
num = "0.4"

当编译库rlib时,rust使用--crate-type lib的选项;编译称二进制时,使用--crate-type bin. 当rust程序依赖外部库时,通常会传递--extern来告知外部库名称。当然这些并不需要显式指定。

当编译成release版本时,使用cargo build --release,这将生成更高效的代码。

build profile

Cargo.toml中存在一些配置设置,影响rustc的命令行参数:

命令行 cargo.toml section
cargo build [profile.dev]
cargo build --release [profile.release]
cargo test [profile.test]

为了更好地利用profiler,我们可能需要在release版本下,保留debug 的符号

[profile.release]
debug = true

modules

crates是项目之间的共享;而module是项目内的共享,作为rust的名字空间:

mod spores {
    use cell::{Cell, Gene};
    pub struct Spore {

    }

    pub(crate) fn test() {}
}

注意pub(crate)意味着它可以在crate内的任何位置被访问,但并不作为外部接口导出。

嵌套modules

pub(super)可以使得item只对parent module可见;pub(in <path>)可以使得item对特定的parent及其后代可见,

将modules划分为多个文件

一个module也可以这样写,mod spores;;这里我们是让rust去找这个spores存在的文件。注意rust不会分离地编译module,当重新build时,会重新编译所有的module。

考虑一个复杂的组织:

fern_sim/
|-- Cargo.toml
--- src/
    --- main.rs
    --- spores.rs
    --- plant/
        --- mod.rs
        --- leave.rs
        --- stems/
            --- ph.rs
            --- xy.rs
        --- stems.rs

我们可以在stems.rs 声明两个新的submodules:

pub mod ph;
pub mod xy;

路径和导入

use 类似于C++中的use

注意submodule不会自动继承父module的item,可以使用 use super::来指定。

使用use ::image;表示使用外部的image crate; 当前module也可以通过self指定。

标准prelude

statics & consts

pub const PI: f64 = 3.14; // 类似 #define

pub static PI: f64 = 3.14; // 可以被ref

把一个程序转为库

lib.rs

fern_sim/
--- cargo.toml
--- src/
    --- bin/
        --- rfern.rs

cargo run --bin rfern可以编译对应的二进制文件。

Attributes

rust程序中的任何item都可以被attr修饰

条件编译:

#[cfg(target_os="android")]
mod mobile;

一些常用cfg:

option 什么时候用
test test被开启时
debug_assertions debug assert被开启时
unix 只为unix系统编译,包括macos
windows
target_pointer_width = "64" 64 位
target_arch = "x86_64" 面向x86_64
target_os = "macos"
feature = "robots" 特定的feature
not(A)
all(A, B)
any(A, B)

考虑一种不会被自动内联的情况:当定义在一个crate的函数或方法被另一个crate调用时,除非是generic或是#[inline]显式注解。

为了给整个crate标注属性,需要在开头使用#!

test

使用#[test]进行标注

#[test]
fn math_test() {
    assert_eq!(0+1, 1);
}

可以使用debug_assert!等,将不会在release模式下编译

为了测试失败的情况,应使用#[should_panic(expected="h")]

注意test只有在cargo test时才会编译;如果有很多代码,可以将其组织为test module,如下

#[cfg(test)]
mod tests {

    #[test]
    fn //
}

Workspace

当项目中存在多个crates,可以使用workspace的概念进行组织,例如在顶层目录新建一个Cargo.toml

[workspace]
members = ["fern_sim"]
posted @ 2025-03-22 10:39  xwher  阅读(64)  评论(0)    收藏  举报