免费做网站软件,网站建设存在风险,wordpress为展示的作品投票,网站成品作业❝ 如果你感觉自己被困住了#xff0c;焦虑并充满消极情绪#xff0c;生命出现了停滞#xff0c;那么治疗方法很简单#xff1a;「做点什么」。 ❞ 大家好#xff0c;我是「柒八九」。一个「专注于前端开发技术/Rust及AI应用知识分享」的Coder 前言 之前我们不是写了一篇R… ❝ 如果你感觉自己被困住了焦虑并充满消极情绪生命出现了停滞那么治疗方法很简单「做点什么」。 ❞ 大家好我是「柒八九」。一个「专注于前端开发技术/Rust及AI应用知识分享」的Coder 前言 之前我们不是写了一篇Rust 赋能前端-开发一款属于你的前端脚手架,从系统架构角度带大家看如何从0到1构建一个功能完备的前端脚手架。因为内容包含很多有些同学说有点消化不了所以前段时间又写了几篇关于写脚手架可能会用到的技术。 如何在Rust中操作JSON Rust 写脚手架Clap你应该知道的二三事 有动手能力强的小伙伴就开始动手写自己的脚手架了。在他们写完功能后他们就想要把脚手架编译成二进制文件并且通过直接访问或者设置.bashrc等全局访问。更有甚者他们还想让自己的朋友使用。在实际操作过程中就会发生一个问题。 A同学用Mac构建了一个工具但是她想让B同学在Windows环境上使用。此时就会发生问题我们都知道Windows和Mac由于系统架构的不同在它们环境下编译的二进制文件是「不互通」的。 之前我们处理的方式就是采用「交叉编译」也就是大家说的跨平台编译。但是呢由于受文章内容的限制我们就一带而过没有过多的去解释。 而有的小伙伴想了解这方面的知识。所以今天我们就来聊聊--Rust跨平台编译 好了天不早了干点正事哇。 我们能所学到的知识点 ❝ 跨平台编译及其在Rust中的好处 Rust 目标三元组 Rust原生跨平台编译 项目初始化 从Mac到Windows环境的跨平台编译 如何编写特定于平台的代码 其他跨平台解决方案 ❞ 1. 跨平台编译及其在Rust中的好处 ❝ 跨平台编译是指能够在一个平台上编译源代码,生成可以在其他平台上运行的可执行文件或库文件。它的主要好处是可以显著提高代码的「可移植性」和「复用性」。 ❞ 在 Rust 中,跨平台编译有以下主要优势: 「无需依赖虚拟机」 不同于 Java 和 .NET 等需要虚拟机的语言,Rust 编译器「直接将代码编译为机器码」,因此可以直接在目标平台上运行,无需额外的运行时环境,提高了性能。 「静态链接」 Rust 默认静态链接所有依赖库,生成的可执行文件是独立的,无需依赖共享库即可运行,便于部署和分发。 「LLVM 支持」 Rust 使用 LLVM 作为编译器后端,LLVM 提供了强大的跨平台支持,能为多种 CPU 架构生成高质量的机器码。 「标准库的跨平台支持」 Rust 的标准库就设计为跨平台的,它利用了一些跨平台的抽象层,如跨平台系统调用接口,从而使标准库能够在不同操作系统上运行。 「编译时单元测试」 Rust 的单元测试在编译时就运行,可以确保在发布时,程序在不同平台上的行为是一致的。 需要说明的是,虽然 Rust 为跨平台编译提供了很好的支持,但由于不同平台的差异,仍然可能需要一些平台特定的代码。不过相比其他语言,Rust 的跨平台编译支持无疑更加方便和高效。 2. Rust 目标三元组 要进行跨平台编译我们需要知道我们要构建的平台的「目标三元组」target triple。Rust使用与LLVM[1]相同的格式。格式为archsub-vendor-sys-env。 例如 x86_64-unknown-linux-gnu代表一个64位 Linux机器 x86_64-pc-windows-gnu代表一个64位的 Windows机器 我们可以运行rustc --print target-list将打印出Rust支持的所有目标。这是一段又臭又长的数据信息。 确定我们关心的平台的目标三元组的两种最佳方法是 在该平台上运行 rustc -vV并查找以 host:开头的行——该行的其余部分将是 目标三元组 或者在 rust platform-support [2]页面中查找 下面一些比较常见的目标三元组 目标三元组名描述x86_64-unknown-linux-gnu64位Linux内核3.2glibc 2.17x86_64-pc-windows-gnu64位MinGWWindows 7x86_64-pc-windows-msvc64位MSVCWindows 7x86_64-apple-darwin64位macOS10.7Lionaarch64-unknown-linux-gnuARM64 Linux内核4.1glibc 2.17aarch64-apple-darwinARM64 macOS11.0Big Suraarch64-apple-iosARM64 iOSaarch64-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环境下运行的。就需要执行以下步骤 安装目标 mingw-w64 brew install mingw-w64 向 rustup 添加目标 rustup target add x86_64-pc-windows-gnu 创建 .cargo/config 将以下指令添加到 .cargo/config 中 [target.x86_64-pc-windows-gnu]linker x86_64-w64-mingw32-gcc 最后运行 cargo build --targetx86_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来探查我们的代码运行的系统信息。 我们可以使用cargo run来执行对应的代码。因为我的系统是mac所以CURRENT_PLATFORM对应的值为x86_64-apple-darwin。 我们可以通过rustc -vV进行查验。 如图所示通过current_platform返回的值和rustc的值是匹配的。大家可以在自己的电脑上运行上面的代码。 5. 从Mac到Windows环境的跨平台编译 通过上文我们已经得知Windows的目标三元组是x86_64-pc-windows-gnu那么我们就来开始我们的操作 - 在Mac中将代码编译到Windows环境中。 我们使用cross crate进行操作。 第一步是运行cargo install cross。这将把Cross安装到$HOME/.cargo/bin。 Cross通过使用一个带有适当工具链的镜像的容器引擎来工作。 由于我们是macOS所以我们选择使用Docker来进行处理。对于Linux它建议使用Podman[5]这是一个流行的Docker替代品。 使用cross进行交叉编译和cargo类似。也是需要指定需要编译的target cross run --target x86_64-pc-windows-gnu 第一次运行时会花费一些时间因为需要下载并启动适当的容器。 一旦完成我们就会看到对应的代码输出。正如上面图中的最后一行。我们看到cross_compile.exe正在Windows环境上运行 从上面的输出中可以看到编译后的.exe文件位于target/x86_64-pc-windows-gnu/debug。我们可以将其复制到Windows机器上运行会显示预期的输出。 执行完上述工作后我们就可以在Docker中查看对应的镜像信息。 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会得到这样的输出 要在Windows上运行测试语法与运行可执行文件非常相似 cross test --target x86_64-pc-windows-gnu 大约一分钟后我们会得到输出 很遗憾测试失败了 ❝ 测试不是在所有平台上都受支持。此外由于线程问题测试是顺序运行的这可能比在本机运行测试要慢得多。 ❞ 6. 如何编写特定于平台的代码 通常我们可能希望编写仅在一个平台上运行的代码。Rust通过cfg属性[6]使这变得简单。 让我们修改我们的程序添加一个仅在Windows上打印的消息。事实上我们甚至不会在非Windows平台上编译此代码 use current_platform::CURRENT_PLATFORM;#[cfg(target_oswindows)]fn windows_only() { println!(该方法只在windows环境被触发);}fn main() { println!(我用的电脑系统是{}!, CURRENT_PLATFORM); #[cfg(target_oswindows)] { windows_only(); }} 在这里我们将cfg属性应用于windows_only()函数以便它不会在非Windows平台上编译。但这意味着我们只能在Windows上调用它因此我们将相同的cfg属性应用于调用该函数的代码块。 实际上我们还可以将属性应用于其他位置如enum、struct和匹配表达式 在Mac上运行cargo run会得到以下输出 如我们所见上面的输出没有Windows特定的消息。但使用cross run --target x86_64-pc-windows-gnu会得到以下输出 由于编码的原因有些汉字没显示全但是这不是主要的核心点我们就不做处理了。 Rust还提供了一种根据平台信息按需应用属性的简单方法 7. 其他跨平台解决方案 上面我们介绍了两种跨平台编译的的方式 内置方式 cargo run --target xxx cross run --target xx 可以说上面的方式属于是N vs N的。也就是可以在多个平台进行互相编译。 其实还有很多解决的方案。只不过有些解决方案是1 vs N 或者是N vs 1的。 下面我们就简单的列举几个。 cargo-xwin [7]:将 Cargo 项目交叉编译为 Windows msvc 目标 cargo-zigbuild [8]:使用 zig 作为链接器编译 Cargo 项目。 后记 「分享是一种态度」。 「全文完既然看到这里了如果觉得不错随手点个赞和“在看”吧。」 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 多平台发布