学习Rust要有大局观(一) 工具链概览

Crash Rust

学习一种新的语言,首先需要了解的就是该语言的基本设计思路,工程架构特点,本文希望可以帮住大多数对Rust感兴趣的同学快速进入具体工程开发,并扫清大部分除基本语法之外的障碍; 具体涉及到的主题包括安装,运行,发布,三方包引入等等;

Rust安装

install

安装Rust非常简单,只需要一条命令,但是注意部分机器curl版本可能导致命令执行失败,比如梁小孩自己的开发机ubuntu20.04自带的curl提示ssl 443错误,如果遇到的话,尝试重新安装curl

curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh

check

执行Rustup命令, 注意如果是第一次全新安装, 先执行 source $HOME/.cargo/env

root@ecs-x86 :~/docs/Rust/CrashRustIn2Hours# source $HOME/.cargo/env
root@ecs-x86 :~/docs/Rust/CrashRustIn2Hours# rustup
Rustup 1.24.2 (755e2b07e 2021-05-12)
...

Hello Rust!

接下来我们完成第一个Rust项目,功能只有一句打印输出,但是大家在此章节应该学到的是如何编译并运行Rust代码程序;

编码

创建第一个rs文件(hello.rs),文件内容如下:

fn main() {
    println!("hello Rust!");
}

文件目录结构简单,代码目录下只有一个单独的hello.rs文件如下:

root@ecs-x86 CrashRustIn2Hours# tree code/
code/
└── hello.rs

0 directories, 1 file

编译&执行

Rust的编译器叫做rustc,编译时直接后跟待编译的rs文件即可, 不执行输出文件名则生成同名的可执行文件, 可以直接执行输出文件得到程序结果

root@ecs-x86 code# rustc hello.rs 
root@ecs-x86 code# tree 
.
├── hello
└── hello.rs

0 directories, 2 files

root@ecs-x86 code# ls -lhF
total 3.3M
-rwxr-xr-x 1 root root 3.3M Jun  2 13:32 hello*
-rw-rw-rw- 1 root root   42 Jun  2 13:29 hello.rs
root@ecs-x86 code# ./hello 
hello Rust!

到此你看到的是纯手工开发流程,包括编译,文件创建,目录组织等等都需要自行维护,为了方便工程化,并且快速创建工程,Rust提供了自己的自动化工具链cargo;

Hello Cargo!

cargo之于Rust犹如npm之于node, cargo可以帮助你维护包依赖关系,安装三方包,自动编译代码,执行结果,完善debugrelease的各种部署需求;

cargo三板斧:

  • cargo init 自动创建工程,包括基本的配置文件,main.rs生成等等
root@ecs-x86 code# cargo init
     Created binary (application) package
root@ecs-x86 code# tree
.
├── Cargo.toml
└── src
    └── main.rs

1 directory, 2 filese
  • cargo run 自动编译并执行;
    注意,此时编译选项均为debug模式,所以target目录下只有一个debug目录自动生成(可执行文件亦在其中)
root@ecs-x86 code# cargo run
   Compiling code v0.1.0 (/root/docs/Rust/CrashRustIn2Hours/code)
    Finished dev [unoptimized + debuginfo] target(s) in 1.34s
     Running `target/debug/code`
Hello, world!

root@ecs-x86 code# tree -L 2
.
├── Cargo.lock
├── Cargo.toml
├── src
│   └── main.rs
└── target
    ├── CACHEDIR.TAG
    └── debug
  • cargo build 单独编译,如果需要单独build可能是最终发布二进制程序,此时一般附带参数--release
root@ecs-x86 code# cargo build --release
   Compiling code v0.1.0 (/root/docs/Rust/CrashRustIn2Hours/code)
    Finished release [optimized] target(s) in 0.35s
root@ecs-x86 code# tree -L 2
.
├── Cargo.lock
├── Cargo.toml
├── src
│   └── main.rs
└── target
    ├── CACHEDIR.TAG
    ├── debug
    └── release

4 directories, 4 files

crate和module

  • crate是rust对外分发和代码共享的单位,类似jar包,类似so库,是三方库的概念
    • crate是编译打包的概念
    • crate的核心标志就是一个单独的Cargo.toml文件,是一个逻辑可编译的功能库
    • cargo package可以在target/package/目录下生成对应的*.crate打包文件
  • module是模块的概念,是代码组织方式,类似于c++的namespace, 类似于golang的package的概念
    • module的核心标志是语法层面的use <module_name>的导入和声明
    • module有三种文件组织方式(假设建立一个叫做string_util的module)
      1. 内嵌文件中使用mod string_util { ... }的方式进行定义, 内部可以包含任意多函数,结构体等等
      2. 建立一个独立文件名string_util.rs,内部无上面的显式mod <module_name>声明
      3. 建立一个文件夹string_util内部包含一个mod.rs文件,还有其他submodule的话文件夹中一般使用第二种创建新文件
    • 三者取其一,如果发现都没有或者有多重情况定义同一个mod的时候rustc便会报错.

关于crate的其他理解可以参考官方doc的部分描述:

A crate is a compilation unit in Rust. Whenever rustc some_file.rs is called, some_file.rs is treated as the crate file. If some_file.rs has mod declarations in it, then the contents of the module files would be inserted in places where mod declarations in the crate file are found, before running the compiler over it. In other words, modules do not get compiled individually, only crates get compiled.

Rust thinks in modules, not files. There is no such thing as file imports, Important concepts in the Rust Module System are packages, crates, modules, and paths

学习modulecrate的时候需要了解的基本前提知识如下:

rust的pubilcprivate的作用域控制结构体层面提升到了mod范围,结构体本身没有类似的概念,这一点相比c++,java,golang均不同,此处的修改省去了friend 友元, gettter, setter等等一些列不必要的麻烦, 同一个module内部的所有结构体函数等等可以紧密合作,简单直接,对外暴露的函数和类型单独增加pub关键字导出, 优雅而且编码友好

crate的感官理解

rust共享代码模块的公网地址为crates.io, 如果使用过mavenrpm等类似工具应该对此类地址并不陌生;

现在我们拆解一个crates.io上下载最多的rand模块看一下其中的目录结构,了解一下一个rust crate大致有什么样的目录和文件结构

➜  rand git:(master) tree -L 1
.
├── CHANGELOG.md
├── COPYRIGHT
├── Cargo.toml                  # 核心的Cargo.toml文件
├── LICENSE-APACHE
├── LICENSE-MIT
├── README.md
├── SECURITY.md
├── benches
├── examples
├── rand_chacha
├── rand_core                   # 一个单独的子crate
├── rand_distr
├── rand_hc
├── rand_pcg
├── rustfmt.toml
├── src                         # `rand`的src目录 
└── utils

9 directories, 8 files


## lib.rs 是比较特殊的一个文件名,一个crate一般只有一个,是默认的crate的导出点和入口文件.
➜  rand git:(master) tree -L 1 src
src
├── distributions
├── lib.rs
├── prelude.rs
├── rng.rs
├── rngs
└── seq

3 directories, 3 files

## 仔细研究`rand_core`你会发现它和外部的`rand`是同构的
➜  rand git:(master) tree -L 2 rand_core
rand_core
├── CHANGELOG.md
├── COPYRIGHT
├── Cargo.toml              # `rand_core`的`Cargo.toml` crate描述文件
├── LICENSE-APACHE
├── LICENSE-MIT
├── README.md
└── src
    ├── block.rs
    ├── error.rs
    ├── impls.rs
    ├── le.rs
    ├── lib.rs              # `rand_core`的`src/lib.rs`文件
    └── os.rs

1 directory, 12 files

可以看到,rand crate本身是以外部依赖其他crate(比如rand_core), 我们自己写代码的时候也可以按照这种方式组织代码,虽然工程上看代码属于同一个目录结构和工程内,但是实际上其中的代码编译关系是有明确的分割关系的. 因为crate本质上是类库的同等地位,所以一个crate只允许一个lib (lib.rs)编译入口文件,但是可以允许有多个main函数(依赖核心的lib.rs)单独编译可执行文件(binary crate);

注释和文档

相比于C++等古老的语言生态,rust的生态支持解决了太多痛点,比如crates.io的存在保证了代码的编写,发布,文档的一体化,一切都是简单的cargo命令即可完成;既然说到了文档,就要知道cargo还有cargo doc命令,只要使用markdown编写的注释便可直接生成对应的html文档,其开发友好程度让人大呼过瘾.

rust的注释写法简单说有如下几种:

  • // 普通注释,此类注释cargo doc会忽略
  • /// 文档注释 ,一般函数结构提元素的注释写法,内容可以是markdown语法,如果包含代码段,代码会被自动生成测试代码
  • //! 高层的文档注释,此类注释生成的是高层模块描述和简介
cargo new --lib myutil

# 修改src/lib.rs为如下内容

//! # The first line
//! The second line

/// Adds one to the number given.
///
/// # Examples
///
/// ```
/// let five = 5;
///
/// assert_eq!(6, add_one(5));
/// # fn add_one(x: i32) -> i32 {
/// #     x + 1
/// # }
/// ```
pub fn add_one(x: i32) -> i32 {
    x + 1
}

以上面代码为例,生成文档的过程如下:

cargo doc --no-deps
cargo doc --open

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
RustupRustup 是一个命令行应用,能够下载并在不同版本的 Rust 工具链中进行切换 —— 如编译器 rustc 和标准库,该应用所支持的平台数量不少。事实上,rustc 本身就支持大约 56 个平台,而 rustup 实际上能够为其中14个平台管理编译器,为30个平台管理标准库。Rust 1.8 中引入的 Rustup,是一个针对 Rust 语言的工具链管理器(toolchain manager),其目标是让交叉编译 Rust 代码更加简单。Mozilla 工程师 Brian Anderson 近期与我们分享了关于此的更多细节。此外,rustup 能够追踪工具链的具体版本,包括 Rust 的 nightly 版本、beta 版本和发行版本。举个例子,你可以用 rustup 检查程序在下一个 Rust 发行版下的行为。但是之前,你需要安装当前平台下的 Rust beta 版本的工具链,然后利用该工具链运行单元测试。使用 rustup 之后,可以通过执行类似下面的代码完成:$ rustup install beta $ rustup run beta cargo test再举一个例子,Anderson 介绍了如何使用 rustup 为使用 musl 标准库(而非大家常用的glibc标准库)的 Linux 版本创建静态二进制文件:$ rustup target add x86_64-unknown-linux-musl $ cargo run --target=x86_64-unknown-linux-muslrustup 还是一个正在开发中的产品,将致力于扩充支持平台的数量。特别要注意,rustup 目前还无法针对 Android 平台进行无缝交叉编译。这要求开发者手动下载 Android NDK,并针对性地创建一个“独立的工具链”。Anderson 表示,rustup 将在未来的版本中解决这个问题,增加获取并配置所要求的连接器和C语言工具链的能。另外,rustup 还计划通过 Emscripten 支持Web开发。rustup 是 Anderson 开发的 multirust 的后继者,并取代了其位置。rustup 仍被看作处于 beta 阶段,但是目前已经可以安装并试用。 标签:Rustup

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值