概述

  Rust 是一种强调性能、类型安全和并发性的通用编程语言。它强制执行内存安全,使用其特有的所有权机制,而无需传统的垃圾收集器。Rust 不强制执行编程范式,但受到函数式编程思想的影响。

  1. 最初是由 Mozilla 员工 Graydon Hoare 在 2006 年作为个人项目创建的
  2. Mozilla 于 2009 年正式赞助了该项目
  3. Rust 是一门编译型的语言。最初,其编译器是用大约 38000 行 OCaml 编写,在 2009 年之后,开始用 Rust 语言基于 LLVM 编写自托管编译器
  4. 在 2015 年 5 月发布第一个稳定版

编程语言

  编程语言是用来定义计算机程序的形式语言。一门新的编程语言,除了有自己的词法与语法、类型系统、执行模型等基本语义与核心特性之外,通常还得有配套的工具链(编译器、标准库、链接器)或解释器、包管理器、构建工具等配套的开发工具。
在这里插入图片描述
  许多古老的编程语言,例如,C 语言,其诞生之初就只有语言标准与编译器,而不是一开始就设计有其他一些工具。然后,在以后的其逐渐变为流行的过程中,才诞生了一些配套的开源或者商业的构建工具,编译工具链等等!

分类

  目前,各种编程语言五花八门,并且根据不同特性有多种分类方式。例如,Python 是一种 动态 解释型强类型定义脚本 语言。

分类维度 类别 主要特征 代表语言 备注说明
按历代分类 第一代语言(1GL) - 机器语言 - 面向机器的二进制指令
- 机器直接执行
- 与硬件强绑定,不可移植
二进制机器代码 由 0 和 1 组成,直接对应硬件的高低电平。
第二代语言(2GL) - 汇编语言 - 使用助记符代替机器指令
- 通过汇编过程转换成机器指令
- 平台相关,不可直接移植
汇编语言 (ASM) 特定汇编语言与特定机器指令集一一对应。
第三代语言(3GL) - 高级语言 - 抽象层次高,类似人类语言
- 支持多种编程范式 (过程式、面向对象等)
- 脱离机器硬件,具备代码可移植性
C, C++, Java, Python, C# 告诉计算机“如何做”,即定义执行任务的详细步骤。
第四代语言(4GL) - 应用语言 - 非过程化编程
- 只需告诉计算机“要做什么”
- 高度封装,专注于特定领域
SQL, MATLAB, PowerShell 不需要指定实现任务的详细执行步骤,例如数据库查询。
按编译及运行方式 编译型 - 源代码一次性全部编译成平台相关的机器码
- 运行速度快,效率高
- 移植到新平台需重新编译
C, C++, Go, Rust 生成的可执行文件可直接由操作系统运行。
解释型 - 代码由解释器逐行读取并执行
- 跨平台性好,一处编写处处运行
- 运行时依赖解释器,速度相对较慢
传统 Ruby, PHP, Shell 脚本 开发效率高,但运行性能通常不如编译型语言。
混合型 - 源代码先编译成与平台无关的中间代码 (字节码)
- 字节码在虚拟机(VM)上运行
- VM通过解释器或JIT(即时编译)执行字节码,平衡性能与移植性
Java, C#, Python (现代实现), JavaScript (现代V8引擎) 结合了编译型和解释型的优点,是目前主流语言的趋势。
按数据类型确认时段 动态类型语言 - 变量的类型在运行时才确定
- 无需显式声明变量类型
- 代码简洁灵活,但IDE支持和错误检查相对较弱
Python, JavaScript, Ruby, PHP 第一次赋值时,变量的类型才被确定,后续可改变。
静态类型语言 - 变量的类型在编译时就确定
- 必须显式声明或推断变量类型
- 代码规范严谨,便于IDE进行代码补全和错误检查
Java, C++, C#, Go, Rust 变量一旦声明,其类型便固定下来,不能随意更改。
按语言性质 编程语言 - 用于创造独立软件和应用程序
- 定义计算机程序的形式语言
- 拥有完整的语法、数据结构和控制流
C/C++, Java, Go, Rust 向计算机发出指令,精确定义数据和在各种情况下应采取的行动。
脚本语言 - 主要用于控制、集成现有软件
- 通常以文本形式保存,由解释器执行
- 缩短“编写-编译-链接-运行”的循环
JavaScript, Python, PHP, Shell 常用于自动化任务、Web后端、网页交互等场景,又称“胶水语言”。
标记语言 - 用于定义数据的结构和表示,而非逻辑
- 使用“标签”来标记文本的语义和结构
- 由渲染引擎或解析器处理,不具备执行逻辑
HTML, XML, Markdown 以 “ml” (Markup Language) 结尾是其常见特征。
按类型系统的强弱 强类型语言 - 类型安全,不允许隐式类型转换
- 不同类型之间操作会直接报错
- 减少因类型误用导致的意外错误
Python, Java, C#, Ruby, Go 变量有类型,值也有类型,操作时会严格检查类型是否匹配。
弱类型语言 - 类型不安全,允许广泛的隐式类型转换
- 编译器/解释器会尝试“理解”并自动转换
- 灵活性高,但容易产生难以察觉的bug
JavaScript, PHP, VBScript 变量的类型由其使用时的上下文决定,可以灵活地转换。

AOT / JIT

  通常,根据编译型语言与解释型语言而不同所包含的工具差别比较大。实际上,还有一种混合型语言,例如,JavaScript,这两种方式都支持。混合型语言结合了编译型和解释型的优点,通过将源代码编译成中间代码(字节码),然后在虚拟机上运行,虚拟机可以通过解释器或JIT(即时编译)来执行字节码,从而平衡了性能与移植性。
在这里插入图片描述

开发环境

  我们说使用一门编程语言,一方面是根据语法编写源代码,另一方面就是使用各种工具处理代码。因此,要使用 Rust 语言开发,首先就要下载安装官方提供的各种工具来搭建 Rust 的开发环境。

工具安装

  对于使用 Rust 进行开发,官方并没有一个统一的 IDE,用户可以任意选择。不过,官方推荐了一些常用代码编辑器,这些编辑器通过其插件系统搭配官方提供的开发辅助工具中的 rust-analyzer 就可以完美实现 Rust 代码的开发。
在这里插入图片描述
  代码编辑器(推荐是 VSCode)使用者根据自己的喜好选择安装即可,而开发辅助工具及编译工具链则需要单独进行安装。Rust 官方提供了预编译好的工具可执行程序,并通过名为 rustup 的工具统一安装及管理。

  打开 Rust 的官方网站会自动侦测我们使用的操作系统,并给出对应的安装方法。对于 Windows 系统,我们需要下载运行官网的 rustup-init.exe 可执行程序来安装 Rust 相关工具;而对于 Linux 或 macOS 系统,则需要在自己系统命令终端中使用命令 curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh 来进行安装。
在这里插入图片描述
  curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh 实际上就是下载名为 rustup-init.sh 的 Shell 脚本并执行,而 rustup-init.sh 脚本中就会下载适用于当前系统的 rustup-init 可执行程序来进行安装,因此,不同的平台下的安装过程基本一致!执行两种安装示意图如下所示:
在这里插入图片描述

  1. 实际上,rustup-init 本身就是 rustup 改了一个名字,rustup 实现了根据自身名字的不同来执行不同的功能,详见后文介绍!

  2. rustup-init 总是默认下载安装最新版。下载源位于国外,因此下载速度会很慢,偶尔还会下载失败,多试几次即可!此外,还可以通过定义如下环境变量(例如,在 Linux 的 ~/.bashrc 中增加)来将 rustup 切换为国内的镜像源

    export RUSTUP_DIST_SERVER="https://rsproxy.cn"
    export RUSTUP_UPDATE_ROOT="https://rsproxy.cn/rustup"
    
  3. 使用 MSVC 作为 ABI 的工具链(仅限于 Windows 系统)时,需要安装 Visual Studio 或 Visual C++ Build Tools,如果当前系统没有安装,安装过程中会提示下载;使用 GNU 作为 ABI 的工具链(无论是 Windows 还是类 Unix 系统)时则需要安装 GCC。

    • 根本原因是 Rust 编译工具链需要使用他们提供的链接器,详见博文 Rust 之四 编译工具链、构建过程、交叉编译 中的介绍

    • Windows 系统

      • MSVC:现在 Visual Studio 是通过 Visual Studio Installer 在线组件化安装,对于 Rust,需要 MSVC 和 Windows SDK,例如:
        • MSVC v143 - VS 2022 C++ x64/x86 build tools (Latest)
        • Windows 11 SDK (10.0.22621.0)
        • 注意,由于 Visual Studio 默认会使用本地编码(中文就是 GBK),可能会导致 Rust 会出现乱码,通常通过切换语言就可以解决!
      • GCC:通常是采用 MinGW-w64 或类似于 MSYS2、Cygwin 这类包含 MinGW-w64 环境。不推荐,会出现一些问题需要自行解决!
    • 类 Unix 系统

      • 直接使用系统命令安装系统官方提供的 GCC 工具链即可
  4. host triple 就是我们要安装的编译工具链,格式基本类似于 GNU 的 <arch>-<vendor>-<sys>-<abi>。对于 Windows 平台,可以用 MSVC 或 GNU 作为 ABI 的工具链,默认采用 MSVC 版,而对于类 Unix 系统,则只有 GNU 作为 ABI 的工具链。

    关于编译工具链,参见博文 Rust 之四 编译工具链、构建过程、交叉编译 中的详细介绍

  5. default toolchain 这个就对应编译工具链的发布通道,默认安装 Stable 通道中最新版本的发行版。实际上这里也可以指定一个版本号,例如 1.79,来安装特定版本的!

  6. profile 就是代表了要按照的各种组件的多少,后文详细介绍

安装目录

  通过上面的安装过程可以看到,开发辅助工具及编译工具链被安装到了当前用户目录下的 .cargo.rustup 这两个目录中。
在这里插入图片描述

  • .cargo 目录中包含了 Rust 所有开发工具的统一接口,官方称为 Proxies。此外,通过 cargo 命令下载的各种第三方可执行工具也被放到在此目录中以便可以直接使用!

  • .rustup 目录中则包含了特定于平台的编译工具链以及相关辅助工具!

detected conflict

  有时候,我们在使用 Rust 时会收到如下所示的错误 error: failed to install component: 'rustc-x86_64-unknown-linux-gnu', detected conflict: 'lib/rustlib/x86_64-unknown-linux-gnu/bin/llc',目前需要等等官方解决,详见 https://github.com/rust-lang/rustup/issues/2417!

Rust 组件

  Rust 是一种 静态 编译型强类型定义 的高级 编程 语言。因此,它有一套自己的编译工具链以及相关辅助工具来帮助我们处理 Rust 代码。所有的这些工具都是由一个名为 rustup 的命令行工具来统一管理!
在这里插入图片描述
  为了方便管理,rustup 引入了 componentprofileproxy 等基本概念来组织和管理所有相关工具的发布!我们在搭建 Rust 开发环境以及开发过程中都需要用到这些概念!

Proxies

  Rust 官方提供了分别适用于 Windows、Linux、MacOS 等目前主流操作系统平台的预编译好的工具可执行程序。但是,即使是在同一个操作系统平台下,也有不同的版本,为了统一不同版本的工具的区别,Rust 采用了使用统一的代理程序来作为对外工具,从而屏蔽不同版本工具的差异的方法。
在这里插入图片描述
  当我们安装了 Rust 之后,安装目录的 .cargo/bin 目录中的这些可执行程序(rustup 除外)实际上是 .rustup/toolchains/发行版/bin 中真实工具的包装器,官方称其为 Proxies。 他们都是通过调用 .rustup/toolchains/发行版/bin 目录中的对应工具来实现功能的!
在这里插入图片描述

  1. .cargo/bin 中包含了所有可用工具的代理,.rustup/toolchains/发行版/bin 却不一定包含所有实际的工具
    在这里插入图片描述
  2. 仔细观察 .cargo/bin 中的各个可执行文件就会发现他们的大小是一模一样的,这是因为他们(包括安装时使用的 rustup-init)实际上都是 rustup 改成了不同的名字,rustup 程序会根据名字的不同执行不同的操作,后文详细介绍。
    在这里插入图片描述

Components

  Rust 官方将其提供的开发辅助工具、编译工具链、其他一些库等组织为了 Components 的形式的集合。组件这个概念是相对于编译工具链的,增减组件都是指的增减当前编译工具链中的组件。

组件名 包含的工具 介绍
rustc rustcrustdoc 编译工具链、文档工具
cargo cargo 包管理器
rustfmt rustfmtcargo-fmt 代码格式化工具
rust-std 这是 Rust 标准库。对于 rustc 支持的每个目标平台,都有一个单独的 rust-std 组件。例如安装了 rustc-x86_64-pc-windows-msvc,就会同步安装 rust-std-x86_64-pc-windows-msvc
rust-docs Rust 文档的本地版本(静态 HTML 格式),位于 .rustup/toolchains/发行版/share/doc/rust 目录中
  1. 使用命令 rustup doc 就可以在浏览器中打开
  2. 这里的文档主要是 https://github.com/rust-lang/rust 这个仓库中的 src/doc(现在,很多文档被移到了子仓库维护)下的文档,很多独立工具的文档不在其中
rust-analyzer rust-analyzer Rust 语言服务器协议的实现,用于配合 VS Code、Emacs 等实现 Rust 语言的编辑功能。
  1. 这个工具通常会以编辑器插件的形式提供,并不会单独安装
  2. 官方也不建议单独安装,它会覆盖编辑器插件中集成的 rust-analyzer,而导致出错
clippy cargo-clippyclippy-driver 代码检查工具
miri Miri 是一个实验性的 Rust 解释器,可用于检查未定义的行为
  1. 目前不提供给 Stable 通道
rust-src Rust 标准库源代码的本地副本,位于 .rustup/toolchains/发行版/lib/rustlib/src 目录中,某些工具,例如 rust-analyzer 会使用源码来提供一些功能
  1. https://github.com/rust-lang/rust 这个仓库中的 library 目录中的内容
  2. 此外还包括 LLVM 的 libunwind 的源码
  3. 默认不会安装该组件,需要使用 rustup component add rust-src 来手动安装
rust-mingw ld 它包含一个用于构建在 x86_64-pc-windows-gnu 平台上的链接器和平台库,位于 .rustup/toolchains/发行版/lib/rustlib/x86_64-pc-windows-gnu 目录中
  1. 默认安装 x86_64-pc-windows-gnu 后就包含了 rust-mingw
llvm-tools LLVM 官方的那些工具 包含 LLVM 工具的集合,位于 .rustup/toolchains/发行版/lib/rustlib/x86_64-pc-windows-gnu 目录中
rustc-dev 此组件将编译器包含为库,用于开发 Rust 的编译器,一般用不到
rls rls RLS 是一种语言服务器,已被废弃,并被 rust-analyzer 所取代。
rust-analysis RLS 使用的标准库的元数据

  组件位于 .rustup/toolchains/发行版/ 下对应的子目录中,其中 .rustup/toolchains/发行版/lib/rustlib/components 文件中就记录了针对当前编译工具链安装的组件。

  1. 大多数组件都有一个目标三元组后缀,全名是 组件名-目标三元组后缀 以区分不同的架构平台,例如,cargo-x86_64-pc-windows-gnu,通过 rustup component list 可以看到所有的组件及当前安装情况
    在这里插入图片描述

    不指定 目标三元组后缀 时,自动匹配当前系统

  2. 使用 rustup component xxx 相关命令来查看、添加或者删除组件,当我们使用 rustup component add 上表中的组件名 时,就会从 Rust 官方网站下载对应的组件放到 .rustup/toolchains/发行版/ 中。
    在这里插入图片描述

  3. 组件并不是提供到所有发布通道(这个概念见后文章节)的,有些通道没有某些组件。例如,上面的 miri 只提供给 Nightly 通道

Profiles

  Profiles 代表了要安装的 Components 的集合,不同的 Profiles 包含的 Component 不同,现在共有 minimaldefaultcomplete 三种 Profile 可选。

配置名称 包含组件 推荐使用场景 优点 缺点
minimal
最小配置
• rustc
• rust-std
• cargo
• Windows 系统
• CI 环境
• 不使用本地文档的场景
• 组件最少
• 文件数量少
• 避免杀毒软件冲突
• 快速安装
• 缺少开发工具
• 无本地文档
default
默认配置
• minimal 所有组件
• rust-docs
• rustfmt
• clippy
• 通用开发
• 个人学习
• 日常使用
• 功能完整
• 开箱即用
• 包含基本开发工具
• rustup 默认选择
• 文件较多
• 可能触发杀毒软件
complete
完整配置
• 所有可用组件 不推荐使用 • 理论上包含所有功能 • 安装几乎总是失败
• 包含过时组件
• 元数据臃肿
  1. 使用 rustup set profile minimal 可以更改默认的 Profile,此后安装工具链时默认将仅安装指定的 Profile 中定义的组件

  2. 使用 rustup install --profile <name> 可以在安装工具链时指定 Profile

  3. Profiles 只会影响新安装的工具链。通常情况下,后续可以使用 rustup component add 安装单个组件。

Toolchain

  toolchain 中包含了编程语言的核心实现,它是 Rust 编译器( rustc )及相关工具(如 cargo )的完整安装。关于编译工具链,我们将在博文 Rust 之四 编译工具链、构建过程、交叉编译 中的详细介绍。

Channels

  Channels 是 Rust 编译工具链以及各辅助开发工具的一种交付(发布)方式。目前,有 stable、beta、nightly 三个 Channels ,详见下文的介绍!

Overrides

  前面说了,Rust 通过 .cargo/bin 下的代理来间接调用编译工具链中真是的工具。rustup 在执行已安装的命令(如 rustc )时自动确定要使用的工具链,并且提供了如下几种方法来控制和覆盖要使用的工具链:

  1. 直接在命令行上使用的工具链覆盖简写。如果 cargorustc 或工具链中的其他工具的第一个参数以 + 开头,它将被解释为 rustup 工具链名称,并且该工具链将被优先使用。例如,cargo +beta test 就表示以指定的 beta 编译工具链来执行 test 命令

  2. 定义 RUSTUP_TOOLCHAIN 环境变量执行要使用的编译工具链目录

  3. 目录覆盖。即通过 rustup override 命令对指定目录设置指定的编译工具链。目录级别的覆盖设置会被存储到 ${RUSTUP_HOME}/settings.toml 配置文件里

  4. 在源码目录中定义 rust-toolchain.toml 文件(旧版使用 rust-toolchain 没有后缀的名字),该文件中会给出编译工具链的配置

    [toolchain]
    channel = "nightly-2020-07-10"
    components = [ "rustfmt", "rustc-dev" ]
    targets = [ "wasm32-unknown-unknown", "thumbv2-none-eabi" ]
    profile = "minimal"
    
  5. 如果没有设置其他覆盖方法,将使用 ${RUSTUP_HOME}/settings.toml 中的全局默认工具链(默认为 ~/.rustup%USERPROFILE%/.rustup)。可以使用 rustup default 命令来设置和查询当前默认值。运行 rustup default 不带任何参数将打印当前默认值。

  在实际匹配工具链时,总是按照如上由高到低的优先级使用第一个找到的编译工具链。可以在我们的源码目录中使用 rustup show 来查看当前使用哪个编译工具链来编译我们的源码。如果在非源码目录执行,显示的所有信息都是全局默认配置!

  对于目录覆盖和 rust-toolchain.toml 文件也会根据它们与当前目录的接近程度被优先考虑。简单来说,这两种覆盖方法是通过向上遍历目录树至文件系统根目录来发现的,一个更接近当前目录的 rust-toolchain.toml 文件会优先于一个距离更远的目录覆盖。

发布规则

  随着对 Rust 了解的逐渐深入,就会发现 Rust 的发布有版本(Version)、发行版(Release)、版次(Edition)这三个不同维度概念,对于初学者来说比较难以理解这三者的具体区别。官方也没有一个简单明了的解释来说明三者之间的具体含义或区别。
在这里插入图片描述

版本

  版本这个概念对应于 Version 这个词,Rust 采用语义化版本号来表示不同的版本,格式为 x.y.z,例如,Rust 1.79.0。这个语义化版本号即是 Rust 语言的版本号又同时是 Rust 工具链的版本号,我们通常说使用特定版本的 Rust,实际上就是指的使用特定版本的 Rust 工具链。
在这里插入图片描述

  1. Rust 的工具链总是与 Rust 语言一同发布,通过 https://github.com/rust-lang/rust 这个源码仓库来维护,他们的版本号都是语义化版本号

  2. Rust 中的软件包也使用语义化版本号,其项目管理工具 Cargo 以语义化版本号的相关规则来判断包版本兼容,详见后文说明

发行版

  发行版这个概念指的是 Rust 版本(Version)的交付方式。Rust 版本(Version)的交付采用了 Nightly、Beta、Stable 三个不同的 Channels 来进行发布。 采用不同 Channels 这种交付模式被称为 Release Train Model,这是一种需求收集、分析、决策、发布、问题反馈的产品开发模型。
在这里插入图片描述
  每一个 Rust 版本(Version)都会依次经过这三个 Channels 而进行发布。Nightly 是正在开发的版本、每晚自动构建、自动发布;Beta 是测试版本,每 6 周从 Nightly 生成一次,包含新特性;Stable 是稳定版本,每 6 周从 Beta 生成一次。如下是目前各个 Channel 中发布的 Rust 版本(Version):
在这里插入图片描述

  • Rust 语言与编译工具链是密切相关的,因此,发行版通常是指的编译工具(及相关工具)的交付方式

  • 发布情况可以从 Rust Forge 上获取

  • 用户通过官方提供的 rustup 工具就可以非常方便的安装及使用不同的发行版

  • Rust 的很多特性只在特定的 Channels 中发布,例如,当前 unstable 的特性,只提供给 Nightly 通道!

版次

  版次这个概念对应官方的 Edition 的概念,直接使用一个年份来表示,例如,Rust 2021 Edition,中文翻译为版次主要是为了与版本(Version)来进行区分。这个概念侧重于 Rust 这门编程语言的版本,就类似于 C99、C++11、C++17 等标准,不同的版次之间往往会出现很多不兼容的特性!

  • 每个 crate 在其 Cargo.toml 文件中使用 edition = xxx 指定其使用的版次
    在这里插入图片描述

  • 版次不是周期性发布的,只有 Rust 项目组认为确有必要时才会发布。目前可用的版次是 2015、2018、2021、2024 这四个。Edition机制允许Rust在不破坏现有代码的情况下引入新的语言特性,每个Edition都会带来一些语言改进,同时保持向后兼容性。

  • 发布情况在 The Rust Edition Guide 中有详细记录

参考

  1. https://rust-lang.github.io/rustup/
  2. https://forge.rust-lang.org/
  3. https://cloud.tencent.com/developer/article/1477262
Logo

一站式 AI 云服务平台

更多推荐