简体   繁体   English

从 Linux 到 Windows 交叉编译 Rust 应用程序

[英]Cross-compile a Rust application from Linux to Windows

Basically I'm trying to compile the simplest code to Windows while I am developing on Linux.基本上,当我在 Linux 上开发时,我试图将最简单的代码编译到 Windows。

fn main() {
    println!("Hello, and bye.")
}

I found these commands by searching the internet:我通过搜索互联网找到了这些命令:

rustc --target=i686-w64-mingw32-gcc  main.rs
rustc --target=i686_pc_windows_gnu -C linker=i686-w64-mingw32-gcc  main.rs

Sadly, none of them work.可悲的是,它们都不起作用。 It gives me an error about the std crate missing它给了我一个关于缺少 std crate 的错误

$ rustc --target=i686_pc_windows_gnu -C linker=i686-w64-mingw32-gcc  main.rs 

main.rs:1:1: 1:1 error: can't find crate for `std`
main.rs:1 fn main() {
          ^
error: aborting due to previous error

Is there a way to compile code on Linux that will run on Windows?有没有办法在 Linux 上编译可以在 Windows 上运行的代码?

Other answers, while technically correct, are more difficult than they need to be.其他答案虽然在技术上是正确的,但比他们需要的要困难得多。 There's no need to use rustc (in fact it's discouraged, just use cargo ), you only need rustup , cargo and your distribution's mingw-w64.没有必要使用rustc (实际上不鼓励使用,只使用cargo ),你只需要rustupcargo和你的发行版的 mingw-w64。

Add the target (you can also change this for whatever target you're cross compiling for):添加目标(您也可以为交叉编译的任何目标更改此设置):

rustup target add x86_64-pc-windows-gnu
rustup toolchain install stable-x86_64-pc-windows-gnu

You can build your crate easily with:您可以使用以下方法轻松构建板条箱:

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

No need for messing around with ~/.cargo/config or anything else.不需要搞乱~/.cargo/config或其他任何东西。

EDIT: Just wanted to add that while you can use the above it can also sometimes be a headache.编辑:只是想补充一点,虽然您可以使用上述内容,但有时也会令人头疼。 I wanted to add that the rust tools team also maintains a project called cross: https://github.com/rust-embedded/cross This might be another solution that you want to look into我想补充一点,rust 工具团队还维护一个名为 cross 的项目: https : //github.com/rust-embedded/cross这可能是您想要研究的另一个解决方案

The Rust distribution only provides compiled libraries for the host system. Rust 发行版只为宿主系统提供编译好的库。 However, according to Arch Linux's wiki page on Rust , you could copy the compiled libraries from the Windows packages in the download directory (note that there are i686 and x86-64 packages) in the appropriate place on your system (in /usr/lib/rustlib or /usr/local/lib/rustlib , depending on where Rust is installed), install mingw-w64-gcc and Wine and you should be able to cross-compile.但是,根据Arch Linux 上 Rust 的 wiki 页面,您可以从下载目录中的 Windows 包(注意有 i686 和 x86-64 包)中的适当位置(在/usr/lib/rustlib/usr/local/lib/rustlib ,取决于 Rust 的安装位置),安装 mingw-w64-gcc 和 Wine,你应该能够交叉编译。

If you're using Cargo, you can tell Cargo where to look for ar and the linker by adding this to ~/.cargo/config (where $ARCH is the architecture you use):如果你使用 Cargo,你可以告诉 Cargo 在哪里寻找ar和链接器,方法是将它添加到~/.cargo/config (其中$ARCH是你使用的架构):

[target.$ARCH-pc-windows-gnu]
linker = "/usr/bin/$ARCH-w64-mingw32-gcc"
ar = "/usr/$ARCH-w64-mingw32/bin/ar"

Note: the exact paths can vary based on your distribution.注意:确切的路径可能因您的分布而异。 Check the list of files for the mingw-w64 package(s) (GCC and binutils) in your distribution.检查您的发行版中 mingw-w64 包(GCC 和 binutils)的文件列表。

Then you can use Cargo like this:然后你可以像这样使用 Cargo:

$ # Build
$ cargo build --release --target "$ARCH-pc-windows-gnu"
$ # Run unit tests under wine
$ cargo test --target "$ARCH-pc-windows-gnu"

UPDATE 2019-06-11更新2019-06-11

This fails for me with:这对我来说失败了:

     Running `rustc --crate-name animation examples/animation.rs --color always --crate-type bin --emit=dep-info,link -C debuginfo=2 --cfg 'feature="default"' -C metadata=006e668c6384c29b -C extra-filename=-006e668c6384c29b --out-dir /home/roman/projects/rust-sdl2/target/x86_64-pc-windows-gnu/debug/examples --target x86_64-pc-windows-gnu -C ar=x86_64-w64-mingw32-gcc-ar -C linker=x86_64-w64-mingw32-gcc -C incremental=/home/roman/projects/rust-sdl2/target/x86_64-pc-windows-gnu/debug/incremental -L dependency=/home/roman/projects/rust-sdl2/target/x86_64-pc-windows-gnu/debug/deps -L dependency=/home/roman/projects/rust-sdl2/target/debug/deps --extern bitflags=/home/roman/projects/rust-sdl2/target/x86_64-pc-windows-gnu/debug/deps/libbitflags-2c7b3e3d10e1e0dd.rlib --extern lazy_static=/home/roman/projects/rust-sdl2/target/x86_64-pc-windows-gnu/debug/deps/liblazy_static-a80335916d5ac241.rlib --extern libc=/home/roman/projects/rust-sdl2/target/x86_64-pc-windows-gnu/debug/deps/liblibc-387157ce7a56c1ec.rlib --extern num=/home/roman/projects/rust-sdl2/target/x86_64-pc-windows-gnu/debug/deps/libnum-18ac2d75a7462b42.rlib --extern rand=/home/roman/projects/rust-sdl2/target/x86_64-pc-windows-gnu/debug/deps/librand-7cf254de4aeeab70.rlib --extern sdl2=/home/roman/projects/rust-sdl2/target/x86_64-pc-windows-gnu/debug/deps/libsdl2-3f37ebe30a087396.rlib --extern sdl2_sys=/home/roman/projects/rust-sdl2/target/x86_64-pc-windows-gnu/debug/deps/libsdl2_sys-3edefe52781ad7ef.rlib -L native=/home/roman/.cargo/registry/src/github.com-1ecc6299db9ec823/winapi-x86_64-pc-windows-gnu-0.4.0/lib`
error: linking with `x86_64-w64-mingw32-gcc` failed: exit code: 1

Maybe this will help https://github.com/rust-lang/rust/issues/44787也许这会有所帮助https://github.com/rust-lang/rust/issues/44787

Static compile sdl2静态编译 sdl2

There is option to static-compile sdl but it didn't work for me .有静态编译 sdl 的选项,但它对我不起作用

Also mixer is not included when used with bundled .当与 bundled 一起使用时,也不包括混合器

Let's cross-compile examples from rust-sdl2 project from Ubuntu to Windows x86_64让我们将 rust-sdl2 项目的示例从 Ubuntu 交叉编译到 Windows x86_64

In ~/.cargo/config~/.cargo/config

[target.x86_64-pc-windows-gnu]
linker = "x86_64-w64-mingw32-gcc"
ar = "x86_64-w64-mingw32-gcc-ar"

Then run this:然后运行这个:

sudo apt-get install gcc-mingw-w64-x86-64 -y
# use rustup to add target https://github.com/rust-lang/rustup.rs#cross-compilation
rustup target add x86_64-pc-windows-gnu

# Based on instructions from https://github.com/AngryLawyer/rust-sdl2/

# First we need sdl2 libs
# links to packages https://www.libsdl.org/download-2.0.php

sudo apt-get install libsdl2-dev -y
curl -s https://www.libsdl.org/release/SDL2-devel-2.0.9-mingw.tar.gz | tar xvz -C /tmp

# Prepare files for building

mkdir -p ~/projects
cd ~/projects
git clone https://github.com/Rust-SDL2/rust-sdl2
cd rust-sdl2
cp -r /tmp/SDL2-2.0.9/x86_64-w64-mingw32/lib/* ~/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-pc-windows-gnu/lib/
cp /tmp/SDL2-2.0.9/x86_64-w64-mingw32/bin/SDL2.dll .

Build examples at once一次构建示例

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

Or stop after first fail:或者在第一次失败后停止:

echo; for i in examples/*; do [ $? -eq 0 ] && cargo build --target=x86_64-pc-windows-gnu --verbose --example $(basename $i .rs); done

Run

cargo build will put binaries in target/x86_64-pc-windows-gnu/debug/examples/ cargo build将把二进制文件放在target/x86_64-pc-windows-gnu/debug/examples/

Copy needed files:复制所需文件:

cp /tmp/SDL2-2.0.4/x86_64-w64-mingw32/bin/SDL2.dll target/x86_64-pc-windows-gnu/debug/examples/
cp assets/sine.wav target/x86_64-pc-windows-gnu/debug/examples/

Then copy directory target/x86_64-pc-windows-gnu/debug/examples/ to your Windows machine and run exe files.然后将目录target/x86_64-pc-windows-gnu/debug/examples/复制到您的 Windows 机器并运行 exe 文件。

Run in cmd.exe在 cmd.exe 中运行

If you want to see the console output when running exe files, you may run them from cmd.exe .如果你想在运行 exe 文件时看到控制台输出,你可以从cmd.exe运行它们。

To open cmd.exe in current directory in file explorer, right click with shift on empty place in window and choose Open command window here .要在文件资源管理器中打开当前目录中的cmd.exe ,请右键单击窗口中的空白位置并按住 shift 并选择Open command window here

Backtraces with mingw should work now - if not use msvc https://github.com/rust-lang/rust/pull/39234使用 mingw 进行回溯现在应该可以使用 - 如果不使用 msvc https://github.com/rust-lang/rust/pull/39234

There is Docker based solution called cross .有一种基于Docker的解决方案,称为cross All the required tools are in virtualized environment so you don't need to install additional packages for your machine.所有必需的工具都在虚拟化环境中,因此您无需为您的机器安装额外的软件包。 See Supported targets list .请参阅支持的目标列表

From project's README:来自项目的自述文件:

Features特征

  • cross will provide all the ingredients needed for cross compilation without touching your system installation. cross将提供交叉编译所需的所有成分,而无需触及您的系统安装。
  • cross provides an environment, cross toolchain and cross compiled libraries, that produces the most portable binaries. cross提供了一个环境、交叉工具链和交叉编译的库,可以生成最便携的二进制文件。
  • “cross testing”, cross can test crates for architectures other than i686 and x86_64. “cross testing”, cross可以测试除 i686 和 x86_64 以外的架构的 crate。
  • The stable, beta and nightly channels are supported.支持稳定版、测试版和夜间频道。

Dependencies依赖关系

  • rustup
  • A Linux kernel with binfmt_misc support is required for cross testing.交叉测试需要一个支持binfmt_misc的 Linux 内核。

One of these container engines is required.需要这些容器引擎之一。 If both are installed, cross will default to docker.如果两者都安装, cross将默认为 docker。

  • Docker.码头工人。 Note that on Linux non-sudo users need to be in the docker group.请注意,在 Linux 上,非 sudo 用户需要在docker组中。 Read the official post-installation steps.阅读官方安装后步骤。 Requires version 1.24 or later.需要 1.24 或更高版本。
  • Podman.波德曼。 Requires version 1.6.3 or later.需要 1.6.3 或更高版本。

Installation安装

$ cargo install cross

Usage用法

cross has the exact same CLI as Cargo but as it relies on Docker you'll have to start the daemon before you can use it. cross具有与 Cargo 完全相同的 CLI,但由于它依赖于 Docker,因此您必须先启动守护程序,然后才能使用它。

# (ONCE PER BOOT)
# Start the Docker daemon, if it's not already running
$ sudo systemctl start docker

# MAGIC! This Just Works
$ cross build --target aarch64-unknown-linux-gnu

# EVEN MORE MAGICAL! This also Just Works
$ cross test --target mips64-unknown-linux-gnuabi64

# Obviously, this also Just Works
$ cross rustc --target powerpc-unknown-linux-gnu --release -- -C lto

The solution that worked for me was.对我有用的解决方案是。 It is similar to one of the accepted answers but I did not require to add the toolchain.它类似于接受的答案之一,但我不需要添加工具链。

rustup target add x86_64-pc-windows-gnu
cargo build --target x86_64-pc-windows-gnu

Refer to the documentation for more details.有关更多详细信息,请参阅文档

I've had success on Debian (testing) without using Mingw and Wine just following the official instructions .我在 Debian(测试)上取得了成功,而没有按照官方说明使用 Mingw 和 Wine They look scary, but in the end it didn't hurt that much.它们看起来很可怕,但最终并没有那么痛。

The official instructions also contain info on how to cross-compile C/C++ code.官方说明还包含有关如何交叉编译 C/C++ 代码的信息。 I haven't needed that, so it's something I haven't actually tested.我不需要那个,所以我还没有实际测试过。

A couple of remarks for individual points in the official instructions.对官方说明中个别要点的几点说明。 The numbers match the numbers in the official instructions .数字与官方说明中的数字相符。

  1. Debian: sudo apt-get install lld Debian: sudo apt-get install lld
  2. Make a symlink named lld-link to lld somewhere in your $PATH .在 $PATH 中的某处创建一个名为lld-link的符号lld-linklld Example: ln -s /usr/bin/lld local_bin/lld-link示例: ln -s /usr/bin/lld local_bin/lld-link
  3. I don't cross-compile C/C++, haven't used this point personally.我不会交叉编译C/C++,个人没用过这点。
  4. This is probably the most annoying part.这可能是最烦人的部分。 I installed Rust on a Windows box via rustup, and copied the libraries from the directories named in the official docs to the Linux box.我通过 rustup 在 Windows 机器上安装了 Rust,并将库从官方文档中指定的目录复制到 Linux 机器。 Beware, there were sometimes uppercase library filenames, but lld wants them all lowercase (Windows isn't case-sensitive, Linux is).请注意,有时会有大写的库文件名,但 lld 希望它们全部小写(Windows 不区分大小写,Linux 是)。 I've used the following to rename all files in current directory to lowercase:我使用以下命令将当前目录中的所有文件重命名为小写:

     for f in `find`; do mv -v "$f" "`echo $f | tr '[AZ]' '[az]'`"; done

    Personally, I've needed both Kit directories and just one of the VC dirs.就个人而言,我既需要Kit目录,也需要VC目录之一。

  5. I don't cross-compile C/C++, haven't used this point personally.我不会交叉编译C/C++,个人没用过这点。
  6. Just make $LIB_ROOT in the script at the end of this post point to the lib directory from point 3.只需在本文末尾的脚本$LIB_ROOT指向第 3 点的 lib 目录即可。
  7. Mandatory强制的
  8. I don't cross-compile C/C++, haven't used this point personally.我不会交叉编译C/C++,个人没用过这点。
  9. Depending the target architecture, either of the following:根据目标架构,以下任一项:
    • rustup target add i686-pc-windows-msvc
    • rustup target add x86_64-pc-windows-msvc

For cross-building itself, I'm using the following simple script (32-bit version):对于交叉构建本身,我使用以下简单脚本(32 位版本):

#!/bin/sh
# "cargo build" for the 32-bit Windows MSVC architecture.

# Set this to proper directory
LIB_ROOT=~/opt/rust-msvc

# The rest shouldn't need modifications
VS_LIBS="$LIB_ROOT/Microsoft Visual Studio 14.0/VC/lib/"
KIT_8_1_LIBS="$LIB_ROOT/Windows Kits/8.1/Lib/winv6.3/um/x86/"
KIT_10_LIBS="$LIB_ROOT/Windows Kits/10/Lib/10.0.10240.0/ucrt/x86/"
export LIB="$VS_LIBS;$KIT_8_1_LIBS;$KIT_10_LIBS"
cargo build --target=i686-pc-windows-msvc "$@"

I'm using the script the same way I would use cargo build我使用脚本的方式与使用cargo build方式相同

Hope that helps somebody!希望对某人有所帮助!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM