Rust跨平台编译

如果你感觉自己被困住了,焦虑并充满消极情绪,生命出现了停滞,那么治疗方法很简单:「做点什么」

大家好,我是「柒八九」。一个「专注于前端开发技术/RustAI应用知识分享」Coder

前言

之前我们不是写了一篇Rust 赋能前端-开发一款属于你的前端脚手架,从系统架构角度带大家看如何从0到1构建一个功能完备的前端脚手架。因为,内容包含很多,有些同学说有点消化不了,所以前段时间又写了几篇关于写脚手架可能会用到的技术。

  1. 如何在Rust中操作JSON
  2. Rust 写脚手架,Clap你应该知道的二三事

有动手能力强的小伙伴,就开始动手写自己的脚手架了。在他们写完功能后,他们就想要把脚手架编译成二进制文件,并且通过直接访问或者设置.bashrc等全局访问。更有甚者,他们还想让自己的朋友使用。在实际操作过程中,就会发生一个问题。

A同学用Mac构建了一个工具,但是她想让B同学在Windows环境上使用。此时就会发生问题,我们都知道WindowsMac由于系统架构的不同,在它们环境下编译的二进制文件是「不互通」的。

之前,我们处理的方式就是采用「交叉编译」也就是大家说的跨平台编译。但是呢,由于受文章内容的限制,我们就一带而过,没有过多的去解释。

alt

而有的小伙伴,想了解这方面的知识。所以,今天我们就来聊聊--Rust跨平台编译

好了,天不早了,干点正事哇。

alt

我们能所学到的知识点

  1. 跨平台编译及其在Rust中的好处
  2. Rust 目标三元组
  3. Rust原生跨平台编译
  4. 项目初始化
  5. 从Mac到Windows环境的跨平台编译
  6. 如何编写特定于平台的代码
  7. 其他跨平台解决方案

1. 跨平台编译及其在Rust中的好处

跨平台编译是指能够在一个平台上编译源代码,生成可以在其他平台上运行的可执行文件库文件。它的主要好处是可以显著提高代码的「可移植性」「复用性」

Rust 中,跨平台编译有以下主要优势:

  1. 「无需依赖虚拟机」 不同于 Java.NET 等需要虚拟机的语言,Rust 编译器「直接将代码编译为机器码」,因此可以直接在目标平台上运行,无需额外的运行时环境,提高了性能。

  2. 「静态链接」 Rust 默认静态链接所有依赖库,生成的可执行文件是独立的,无需依赖共享库即可运行,便于部署和分发。

  3. 「LLVM 支持」 Rust 使用 LLVM 作为编译器后端,LLVM 提供了强大的跨平台支持,能为多种 CPU 架构生成高质量的机器码。

  4. 「标准库的跨平台支持」 Rust 的标准库就设计为跨平台的,它利用了一些跨平台的抽象层,如跨平台系统调用接口,从而使标准库能够在不同操作系统上运行。

  5. 「编译时单元测试」 Rust 的单元测试在编译时就运行,可以确保在发布时,程序在不同平台上的行为是一致的。

需要说明的是,虽然 Rust 为跨平台编译提供了很好的支持,但由于不同平台的差异,仍然可能需要一些平台特定的代码。不过相比其他语言,Rust 的跨平台编译支持无疑更加方便和高效。


2. Rust 目标三元组

要进行跨平台编译,我们需要知道我们要构建的平台的「目标三元组」target triple)。Rust使用与LLVM[1]相同的格式。格式为<arch><sub>-<vendor>-<sys>-<env>

例如,

  • x86_64-unknown-linux-gnu代表一个64位 Linux机器
  • x86_64-pc-windows-gnu代表一个64位的 Windows机器

我们可以运行rustc --print target-list将打印出Rust支持的所有目标。这是一段又臭又长的数据信息。

确定我们关心的平台的目标三元组的两种最佳方法是:

  1. 在该平台上运行 rustc -vV,并查找以 host:开头的行——该行的其余部分将是 目标三元组
  2. 或者在 rust platform-support [2]页面中查找

下面一些比较常见的目标三元组

目标三元组名描述
x86_64-unknown-linux-gnu64位Linux(内核3.2+,glibc 2.17+)
x86_64-pc-windows-gnu64位MinGW(Windows 7+)
x86_64-pc-windows-msvc64位MSVC(Windows 7+)
x86_64-apple-darwin64位macOS(10.7+,Lion+)
aarch64-unknown-linux-gnuARM64 Linux(内核4.1,glibc 2.17+)
aarch64-apple-darwinARM64 macOS(11.0+,Big Sur+)
aarch64-apple-iosARM64 iOS
aarch64-apple-ios-simARM64上的Apple iOS模拟器
armv7-linux-androideabiARMv7a Android

3. Rust原生跨平台编译

之前,我们在处理f_cli的跨平台编译的时候,我们直接是用cargo build --target xx,这是Rust内置的方式。

但是呢,这块有一个问题。

要将源代码编译成适配特定平台,我们需要指定一个目标(target)。这告诉编译器我们的代码应该编译为哪个平台。因此,我们需要安装相应的 GCC[3]。然后,将目标添加到 Rust 工具链中。

工具链是一组工具,帮助语言生成功能性的目标代码。它们可以提供编译器链接器程序,或者额外的库中扩展功能。

下一步是添加链接器。这可以在 Cargo 配置中设置。

Rust 编译器「按顺序处理程序中的每个源代码文件」,并检查我们的代码以确保其遵循 Rust 语言的规则,并「将我们的源代码转换为称为目标文件的机器语言文件」编译器创建一个或多个目标文件之后,另一个名为链接器的程序将编译器生成的所有目标文件合并为一个「单独的可执行程序」。除了能够链接目标文件外,链接器还能够链接库文件。库文件是预编译代码的集合,已经被“打包”以供在其他程序中重用。

例如,如果我们想要在Mac环境下将程序编译成可以在Windows环境下运行的。就需要执行以下步骤

  1. 安装目标 mingw-w64

    brew install mingw-w64
  2. rustup 添加目标:

    rustup target add x86_64-pc-windows-gnu
  3. 创建 .cargo/config

    • 将以下指令添加到 .cargo/config
    [target.x86_64-pc-windows-gnu]
    linker = "x86_64-w64-mingw32-gcc"
  4. 最后运行:

      cargo build 
      --target=x86_64-pc-windows-gnu 
      --verbose

这只是其中一个平台,如果我们的程序想要在多个平台上发布,那就需要做更多的设置。这是一项功能繁杂的工程。

上面的解决方式是可以的,但是今天我们再解释一种更优雅的跨平台编译方式。--cross[4],该crate曾由Rust嵌入式工作组维护。

下面,我们就简单来启动一个小项目来讲解一下如何使用cross进行Rust的跨平台编译。


4. 项目初始化

又到了我们再熟悉不过的场景了。我们用cargo new构建一个项目

cargo new cross_compile

然后,我们将main.rs中内容替换成如下代码:

use current_platform::CURRENT_PLATFORM;

fn main() {
    println!("我用的电脑系统是{}!", CURRENT_PLATFORM);
}

我们使用current_platformcrate来探查我们的代码运行的系统信息。

alt

我们可以使用cargo run来执行对应的代码。因为我的系统是mac,所以CURRENT_PLATFORM对应的值为x86_64-apple-darwin

我们可以通过rustc -vV进行查验。

alt

如图所示,通过current_platform返回的值和rustc的值是匹配的。大家可以在自己的电脑上运行上面的代码。


5. 从Mac到Windows环境的跨平台编译

通过上文我们已经得知Windows的目标三元组是x86_64-pc-windows-gnu那么我们就来开始我们的操作 - 在Mac中将代码编译到Windows环境中。

我们使用cross crate进行操作。

第一步是运行cargo install cross。这将把Cross安装到$HOME/.cargo/bin

Cross通过使用一个带有适当工具链的镜像的容器引擎来工作。

alt

由于我们是macOS,所以我们选择使用Docker来进行处理。对于Linux,它建议使用Podman[5],这是一个流行的Docker替代品。

使用cross进行交叉编译和cargo类似。也是需要指定需要编译的target

cross run --target x86_64-pc-windows-gnu

第一次运行时会花费一些时间,因为需要下载并启动适当的容器。

alt

一旦完成,我们就会看到对应的代码输出。(正如上面图中的最后一行)。我们看到cross_compile.exe正在Windows环境上运行!

从上面的输出中可以看到,编译后的.exe文件位于target/x86_64-pc-windows-gnu/debug。我们可以将其复制到Windows机器上运行,会显示预期的输出。

执行完上述工作后,我们就可以在Docker中查看对应的镜像信息。 alt

Cross甚至支持在其他平台上运行测试!让我们在main.rs文件中添加一个测试:

mod tests {
    use current_platform::{COMPILED_ON, CURRENT_PLATFORM};

    #[test]
    fn test_compiled_on_equals_current_platform() {
        assert_eq!(COMPILED_ON, CURRENT_PLATFORM);
    }
}

请注意,这是一个我们期望在Mac上运行时通过的测试,但当我们跨编译到Windows并在那里运行时将会失败。

我们在Mac上运行cargo test,会得到这样的输出:

alt

要在Windows上运行测试,语法与运行可执行文件非常相似:

cross test --target x86_64-pc-windows-gnu

大约一分钟后,我们会得到输出:

alt

很遗憾,测试失败了!

测试不是在所有平台上都受支持。此外,由于线程问题,测试是顺序运行的,这可能比在本机运行测试要慢得多。


6. 如何编写特定于平台的代码

通常,我们可能希望编写仅在一个平台上运行的代码。Rust通过cfg属性[6]使这变得简单。

让我们修改我们的程序,添加一个仅在Windows上打印的消息。事实上,我们甚至不会在非Windows平台上编译此代码:

use current_platform::CURRENT_PLATFORM;

#[cfg(target_os="windows")]
fn windows_only() {
    println!("该方法只在windows环境被触发");
}

fn main() {
    println!("我用的电脑系统是{}!", CURRENT_PLATFORM);
    #[cfg(target_os="windows")]
    {
        windows_only();
    }
}

在这里,我们将cfg属性应用于windows_only()函数,以便它不会在非Windows平台上编译。但这意味着我们只能在Windows上调用它,因此我们将相同的cfg属性应用于调用该函数的代码块。

实际上,我们还可以将属性应用于其他位置,如enumstruct和匹配表达式!

Mac上运行cargo run会得到以下输出:

alt

如我们所见,上面的输出没有Windows特定的消息。但使用cross run --target x86_64-pc-windows-gnu会得到以下输出:

alt

由于编码的原因,有些汉字没显示全,但是这不是主要的核心点,我们就不做处理了。

Rust还提供了一种根据平台信息按需应用属性的简单方法

alt

7. 其他跨平台解决方案

上面我们介绍了两种跨平台编译的的方式

  1. 内置方式 cargo run --target xxx
  2. cross run --target xx

可以说,上面的方式属于是N vs N的。也就是可以在多个平台进行互相编译。

其实还有很多解决的方案。只不过有些解决方案是1 vs N 或者是N vs 1的。 下面我们就简单的列举几个。

  1. cargo-xwin [7]:将 Cargo 项目交叉编译为 Windows msvc 目标
  2. cargo-zigbuild [8]:使用 zig 作为链接器编译 Cargo 项目。

后记

「分享是一种态度」

「全文完,既然看到这里了,如果觉得不错,随手点个赞和“在看”吧。」

alt

Reference

[1]

LLVM: https://llvm.org/

[2]

rust platform-support : https://doc.rust-lang.org/nightly/rustc/platform-support.html

[3]

GCC: https://gcc.gnu.org/

[4]

cross: https://crates.io/crates/cross

[5]

Podman: https://podman.io/

[6]

cfg属性: https://doc.rust-lang.org/rust-by-example/attribute/cfg.html

[7]

cargo-xwin: https://github.com/rust-cross/cargo-xwin

[8]

cargo-zigbuild: https://github.com/rust-cross/cargo-zigbuild

本文由 mdnice 多平台发布

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/614994.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【数据结构】04串

串 1. 定义2. 串的比较3. 串的存储结构4. 具体实现5. 模式匹配5.1 常规思路实现5.2 KMP模式匹配算法5.2.1 next数组计算5.2.1 代码计算next数组5.2.2 KMP算法实现 1. 定义 串(string)是由零个或多个字符组成的有限序列&#xff0c;又叫字符串。 一般记为s a 1 , a 2 , . . . ,…

构建智能连接的未来:物联网平台系统架构解析

随着科技的不断进步和互联网的普及&#xff0c;物联网&#xff08;Internet of Things, IoT&#xff09;已成为连接世界的新方式。物联网平台作为实现物联网应用的核心基础设施&#xff0c;其系统架构的设计和实施至关重要。本文将深入探讨物联网平台系统架构的关键要素和最佳实…

WebStorm

设置 打开的文件快速定位到左侧指定目录的结构位置 调出终端控制台 Alt F1 ESlint格式化代码 插件

MATLAB Simulink仿真搭建及代码生成技术—01自定义新建模型模板

MATLAB Simulink仿真搭建及代码生成技术 目录 01-自定义新建模型模板点击运行&#xff1a;显示效果&#xff1a;查看模型设置&#xff1a; 01-自定义新建模型模板 新建模型代码如下&#xff1a; function new_model(modelname) %建立一个名为SmartAss的新的模型并打开 open_…

sysbench MySQL性能测试

目录 1. QPS&&TPS 1.1 数据库启动到现在的运行时间(秒) 1.2 查询量 1.3 status命令直接显示出QPS 1.4 每秒输出数据库状态(累加) 2. sysbench 测试工具 3. OLTP MySQL测试 3.1 普通参数 3.2 支持的lua脚本 3.3 脚本参数 3.4 测试数据准备 3.5 进行测试 3.…

AndroidAutomotive模块介绍(三)CarService服务

前言 上一篇文档总结 Android Automotive 框架的 APP 和 API 部分内容&#xff0c;本篇文档将会继续根据 Android Automotive 框架结构&#xff0c;总结 Framework 层 CarService 服务的内容。 本文档对 Android Automotive Framework 层服务将会按照如下顺序展开描述&#x…

组合导航的结果分段跳变问题

1 现象 用上海代数律动公司的AlgoT1-3组合导航设备采集数据进行组合导航算法调试&#xff0c;AlgoT1-3机器输出的结果很好很平滑&#xff0c;AlgoT1-3是带GNSS/INS的组合导航设备&#xff0c;另外还有一款更贵一点的带视觉的组合导航AlgoT1&#xff0c;效果会更好一些&#xf…

【报错】TypeError: Cannot read property ‘meta‘ of undefined

&#x1f608;解决思路 首先这里很明显我们能看到是缺少该参数&#xff1a;meta。 但是经过查找后发现和该参数无关。 &#x1f608;解决方法 后来我上网搜了下&#xff0c;网上的回答大部分偏向于是package.json这个文件中的tabBar.list数组对象只有一条的问题。 网上的大…

你会写SAP技术规格说明书(Specification)吗

有些小伙伴可能还在发愁技术规则说明书应该写什么&#xff0c;做了张思维导图&#xff0c;包含了所有RICEFW。 R - Report - 报表 I - Interface - 接口 C - Conversion - 数据转换 E - Enhancement - 增强 F - Form - 表单 W - Workflow - 工作流

数组算法——查询位置

需求 思路 使用二分查找找到第一个值&#xff0c;以第一个值作为界限&#xff0c;分为左右两个区间在左右两个区间分别使用二分查找找左边的7,&#xff1a;找到中间位置的7之后&#xff0c;将中间位置的7作为结束位置&#xff0c;依次循环查找&#xff0c;知道start>end,返回…

idea 卡怎么办

设置内存大小 清缓存重启 idea显示内存全用情况 右下角

自建远程桌面服务器,控制免root安卓手机和pc

RustDesk是一个开源的远程桌面软件&#xff0c;它允许用户通过互联网在不同设备之间共享桌面和控制权限。这款软件以最少的配置提供了自托管和安全保障&#xff0c;是一个类似于TeamViewer的开源替代品​ (RustDesk)​。RustDesk支持在Windows、macOS、Linux、iOS、Android以及…