Rust跨平台编译

news2024/11/22 22:10:59

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

大家好,我是「柒八九」。一个「专注于前端开发技术/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.coloradmin.cn/o/1592071.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

潍微科技-水务信息管理平台 ChangePwd SQL注入漏洞复现(CNVD-2024-14945)

0x01 产品简介 水务信息管理平台主要帮助水务企业实现水质状态监测、管网运行监控、水厂安全保障、用水实时监控以及排放有效监管,确保居民安全稳定用水、环境有效保护,全面提升水务管理效率。由山东潍微科技股份有限公司研发,近年来,公司全力拓展提升水务、水利信息化业务…

Java---搭建junit4.x单元测试环境,并进行测试

搭建junit4.x单元测试环境 1.选择Project Structure 2.选择Modules&#xff0c;选择要加入测试环境的模块&#xff0c;选择Dependencies,可以看到当前模块都有哪些依赖。 3.点击 后选择第一个 4.找到你安装IDEA的文件夹&#xff0c;进入到IntelliJ IDEA 2018.3.4\lib目录下…

18.java openCV4.x 入门- Imgproc之色彩映射及颜色空间转换

专栏简介 &#x1f492;个人主页 &#x1f4f0;专栏目录 点击上方查看更多内容 &#x1f4d6;心灵鸡汤&#x1f4d6;我们唯一拥有的就是今天&#xff0c;唯一能把握的也是今天建议把本文当作笔记来看&#xff0c;据说专栏目录里面有相应视频&#x1f92b; &#x1f9ed;文…

kvm虚拟机磁盘镜像加密

一、qcow2的aes加密 低版本的qemu能够支持对qcow2文件进行aes加密的方式&#xff0c;例如对一个已经存在的磁盘文件test.qcow2&#xff0c;可以将其转换为经过加密的qcow2文件。 qemu-img convert -O qcow2 --object secret,idsec0,data123456 -o encryptionon,encrypt.key-s…

为数据穿上安全的外衣——零售电商场景下的数据安全体系建设

在电子商务交易过程中&#xff0c;会涉及大量的个人和财务数据的传输和处理&#xff0c;随着电子商务的发展&#xff0c;数据安全风险也成为一个备受关注的问题。 而跨境电商&#xff0c;属于出海业务&#xff0c;涉及到海外不同国家的政策法规&#xff0c;且数据作为电商的业…

linux安装texlive程序

tex 是文本格式渲染语言&#xff0c; 对数学公式特别友好&#xff0c;所以前沿的科研者基本都要掌握 tex 基本功。Latex 是一款优秀的tex渲染程序&#xff0c;可以直接输出PDF等格式文件。 texlive 是 Latex程序及其周边的一个非常优秀的程序管理包&#xff0c;随着社区的发展…

【InternLM 实战营第二期-笔记4】XTuner 微调个人小助手认知

书生浦语是上海人工智能实验室和商汤科技联合研发的一款大模型,很高兴能参与本次第二期训练营&#xff0c;我也将会通过笔记博客的方式记录学习的过程与遇到的问题&#xff0c;并为代码添加注释&#xff0c;希望可以帮助到你们。 记得点赞哟(๑ゝω╹๑) XTuner 微调个人小助手…

计算机网络之同轴电缆,集线器,网桥,交换机,路由器

ping的过程 两台主机用交叉线连接&#xff0c;通过88.2ping88.3发现底层是先经过广播&#xff0c;通过arp协议&#xff0c;告诉我要找的ip是88.3,然后88.3主机收到后就把自己的mac地址发送回去&#xff0c;同理88.2发现是发给自己的后就进行接收&#xff0c;有了mac地址然后再通…

56、巴利亚多利德大学、马德里卡洛斯三世研究所:EEG-Inception-多时间尺度与空间卷积巧妙交叉堆叠,终达SOTA!

本次讲解一下于2020年发表在IEEE TRANSACTIONS ON NEURAL SYSTEMS AND REHABILITATION ENGINEERING上的专门处理EEG信号的EEG-Inception模型&#xff0c;该模型与EEGNet、EEG-ITNet、EEGNex、EEGFBCNet等模型均是专门处理EEG的SOTA。 我看到有很多同学刚入门&#xff0c;不太会…

C#学习:初始类与名称空间

本节内容&#xff1a; 1.初始类&#xff08;class&#xff09;与名称空间&#xff08;namespace&#xff09; 这个定义过于复杂。 类&#xff08;class&#xff09;构成程序的主体。具体的解释很复杂&#xff0c;要资深开发人才能看的懂&#xff0c;我们先记住这句话。 什么…

视频评论ID提取工具|视频关键词评论批量采集软件

视频评论ID提取工具&#xff1a;批量抓取视频评论 视频评论ID提取工具是一款功能强大的软件&#xff0c;可以帮助您批量抓取视频视频下的评论信息。通过输入关键词和评论监控词&#xff0c;即可进行评论的抓取&#xff0c;并提供评论昵称、评论日期、评论内容、命中关键词以及所…

【Qt】:对话框(一)

对话框 一.基本的对话框二.自定义对话框三.通过图形化界面自定义对话框四.关于对话框mode 对话框是GUI程序中不可或缺的组成部分。一些不适合在主窗口实现的功能组件可以设置在对话框中。对话框通常是一个顶层窗口&#xff0c;出现在程序最上层&#xff0c;用于实现短期任务或者…

腾讯云人脸服务开通详解:快速部署,畅享智能体验

请注意&#xff0c;在使用人脸识别服务时&#xff0c;需要确保遵守相关的法律法规和政策规定&#xff0c;保护用户的合法权益&#xff0c;并依法收集、使用、存储用户信息。此外&#xff0c;腾讯云每个月会提供一定次数的人脸识别调用机会&#xff0c;对于一般的小系统登录来说…

[StartingPoint][Tier2]Included

LXD https://www.hackingarticles.in/lxd-privilege-escalation/ Task 1 What service is running on the target machine over UDP? &#xff08;目标机器上通过UDP运行的服务是什么&#xff1f;&#xff09; $ nmap -sU 10.129.232.86 -p 69 tftp Task 2 What class o…

C++:构造函数、析构函数、拷贝构造函数

hello&#xff0c;各位小伙伴&#xff0c;本篇文章跟大家一起学习《C&#xff1a;构造函数、析构函数、拷贝构造函数》&#xff0c;感谢大家对我上一篇的支持&#xff0c;如有什么问题&#xff0c;还请多多指教 &#xff01; 如果本篇文章对你有帮助&#xff0c;还请各位点点赞…

Flutter中间镂空的二维码扫描控件

1、UI效果图&#xff1a; 2、中间镂空UI&#xff1a; class CenterTransparentMask extends CustomClipper<Path> {final double? width;CenterTransparentMask({this.width});overridePath getClip(Size size) {final path Path()..addRect(Rect.fromLTWH(0, 0, size…

K8s 部署 elasticsearch-7.14.0 集群 及 kibana 客户端

一、K8s 部署 elasticsearch-7.14.0 集群 安装规划 组件replicas类型es3StatefulSetkibana1Deployment 使用 k8s 版本为&#xff1a;v1.18.0 。 本次使用 OpenEBS 来作为存储引擎&#xff0c;OpenEBS 是一个开源的、可扩展的存储平台&#xff0c;它提供了一种简单的方式来创…

外贸公司应该怎么选择企业邮箱?哪个企业邮箱最好?

外贸公司业务的特殊性需要他们频繁进行跨国的沟通交流&#xff0c;那么外贸公司应该如何选择适合的企业邮箱呢&#xff1f;首先&#xff0c;传输邮件的稳定安全是前提&#xff0c;另外由于沟通多是国外客户&#xff0c;邮件的翻译也成为外贸公司企业邮箱的刚需。小编今天就详细…

linux——Bash特性

bash是一个命令解释器&#xff0c;其支持命令行展开&#xff5b;&#xff5d;写法 alias是命令别称&#xff0c;即为命令等同于&#xff0c;使用unalias对应命令可以取消该别称 alias可以对命令进行更改