linux 安装 mingw_Rust Windows-GNU 版本与MSYS2-MINGW-W64 整合集成

更新:官方调整在2020年2月5日合并进master,之后的nightly版本能够自动检测MINGW-W64路径。期待登陆stable!

本文目的:

在Rust的windows下的gnu toolchain中使用MSYS2的MINGW-W64提供的编译好的/或者编译过程中需要类POSIX环境的那些C/C++库。

纯Rust程序不需要参看本文的内容。

依赖库里需要链接C/C++库的很可能需要——链接报错的典型提示如下:

undefined reference to `__imp___acrt_iob_func'
undefined reference to `__errno'

声明:

这里的内容本质上是一种临时措施。适用于对2017~2018年时期存在的一些不完美的状态进行临时修补。在未来某一时刻,本文内容将不再适用。届时作废。

1. 缘起

1.1 为数众多的编译器们

Rust 使用的链接器是系统提供的,而且Rust的标准库也对libc有依赖。在Linux/Mac等环境下,Rust会使用gcc执行链接。在Windows下,系统没有原生自带链接器。主流的免费C/C++工具链主要有五套,分别是Visual C++、Clang、Mingw-w64 GCC、MSYS2 GCC、CYGWIN GCC。(这里没有包含WSL的情况,也没有包含用的比较少的mingw32 GCC、msys 1.0 GCC、GCC-MCF等等。)

Rust 在Windows下的编译支持主要是两种,分别对应列表里的Visual C++ 和 Mingw-w64 GCC 两种,分别称作msvc 和 gnu 的target,同时有对应的toolchain。msvc的情况在这里不细说了。下面主要说下gnu。

1.2 MINGW-W64 也有很多种

首先要从MinGW说起,MinGW主要是想在Windows下提供一套完整的开源开发工具。使用的是微软的C运行时,然后把GCC、Binutils等等组件都做了源码改动,最终达到可以在Windows下使用的目的。原版的MinGW只有32位版本的。

后来有人从MinGW上fork出来了一个新项目,叫mingw-w64。它同时支持32位和64位平台。后来mingw-w64的活跃度要超过了原来的mingw,现在大家主要用的都是mingw-w64了。

mingw-w64 不是非要在windows上用的。它也有linux、mac版本,在这些平台上它起到交叉工具链的作用,可以从这些平台编译windows程序。

而在windows上运行的版本,提供的有几家,比较官方的是mingw-w64-builds(MinGW-builds),另外还有msys2(MSYS2 homepage)、win-builds(http://win-builds.org)等等。Rust的gnu版本构建时使用的是mingw-w64-builds。

1.3 MSYS2的优势

MSYS2 实际上主打的是MSYS 2.0,也就是Windows下的POSIX 应用级模拟层。它里面有三套环境:MSYS 2.0 和 Mingw-w64 32 位 和 Mingw-w64 64 位。它有很多优点,其中之一是使用了archlinux的包管理器pacman,另外它也自己编译提供了很多的常用的包,比如libpng、openssl等等。同一个软件经常是3份,对应上述的三个环境。实际上平时用起来算是比较方便的。

如果在Rust里使用这些C/C++库的话,如果你是64位target,应该使用Mingw-w64 64位环境下的包,如果是32位taget,则应该使用Mingw-w64 32位环境下的包。

总之,在结果上mingw-w64-builds的生态远远地落后于MSYS2。所以使用MSYS2是有一定的现实意义的。

1.4 问题——版本兼容性

如果两边能够完美整合,那么本文就不会存在了。在今天,Rust自带的mingw环境是来自于mingw-w64-builds的,版本低于当前的MSYS2版本。假如尝试链接MSYS2中Mingw-w64 环境的包到Rust程序中,往往就会链接报错,典型的提示如:

undefined reference to `__imp___acrt_iob_func'

2. 解决问题

2.1 问题分析

问题来源很简单,rust捆绑的mingw 运行时版本要旧于msys2自带mingw 运行时版本。

解决方法也很简单,让rust使用自己安装的msys2中带的mingw。

执行起来就要繁琐一些,主要分成三个部分

a. 移除rust-mingw。

b. 告诉rust使用自己安装的mingw。

c. 替换crt2.o 和 dllcrt2.o。

2.2 第一步:移除rust-mingw

以我的Windows环境为例,我的用户名是CrLF0710,用的是stable-gnu 64位工具链。

首先rustup实际上是不支持移除rust-mingw组件的,于是要先更改组件列表让它变成可选的,步骤如下:

a. 打开C:UsersCrLF0710.rustuptoolchainsstable-x86_64-pc-windows-gnulibrustlibmultirust-channel-manifest.toml

b. 搜索rust-mingw,会找到两处,分别是

[[pkg.rust.target.x86_64-pc-windows-gnu.components]]
pkg = "rust-mingw"
target = "x86_64-pc-windows-gnu"

[[pkg.rust.target.i686-pc-windows-gnu.components]]
pkg = "rust-mingw"
target = "i686-pc-windows-gnu"

我们要做的是把components 这个词替换成extensions 。注意小心修改。修改完成后保存。

然后打开命令提示符,rustup component remove rust-mingw,成功~

2.3 第二步:帮助rust找到自己安装的mingw

这次要修改的是C:UsersCrLF0710.cargoconfig

在其中添加

[target.x86_64-pc-windows-gnu]
linker = "C:UsersCrLF0710msys64mingw64bingcc.exe"
ar = "C:UsersCrLF0710msys64mingw64binar.exe"

其中C:UsersCrLF0710msys64 这一段请换成你的MSYS2 的安装路径。如果是32位的话,x86_64应该换成i686。

万一有人需要:在MSYS2.0 中安装这两个exe文件的方法是执行以下命令(以64位为例)。

pacman -S mingw-w64-x86_64-gcc  mingw-w64-x86_64-binutils

2.4 第三步:替换crt2.o 和 dllcrt2.o。

本来理想情况下前两步之后就应该完工了。实际上移除rust-mingw这步会留下两个文件crt2.o和dllcrt2.o。也是rust自带的那个老版本mingw的。而现在rust也没有办法为它们指定正确的路径。

我们在这里的解决办法就是:

a. 打开C:UsersCrLF0710msys64mingw64x86_64-w64-mingw32lib 目录,复制crt2.o 和 dllcrt2.o 文件

b. 打开C:UsersCrLF0710.rustuptoolchainsstable-x86_64-pc-windows-gnulibrustlibx86_64-pc-windows-gnulib 目录,粘贴替换。

2.5 大功告成

好啦,现在rust程序可以链接MSYS2的MINGW64环境预装好的那些库了。需要什么可以在MSYS2的shell下面 pacman 工具安装。

不过,以上的这些修改在下次的rustup update 中都会被撤销,所以,版本升级后还要重做一遍:(

相信在未来Rust官方会提供更好的整合方案。这里仅仅是临时的解决问题的手段,希望对大家有所帮助。谢谢大家。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值