为什么Rust在Windows上链接失败?

7

我在我的电脑上下载并安装了Rust和Cargo的夜间版本,并使用Cargo生成了一个新的二进制项目:

Cifram@Valyria ~
$ cargo new test --bin

然后我尝试使用全新、未受污染的 Rust 和 Cargo 安装来运行这个新项目,但是出现了以下错误:

Cifram@Valyria ~/test
$ cargo run --verbose
   Compiling test v0.0.1 (file:///C:/cygwin64/home/Cifram/test)
     Running `rustc C:\cygwin64\home\Cifram\test\src\main.rs --crate-name test --crate-type bin -g --out-dir C:\cygwin64\home\Cifram\test\target --dep-info C:\cygwin64\home\Cifram\test\target\.fingerprint\test-51757ad0485ed143\dep-bin-test -L C:\cygwin64\home\Cifram\test\target -L C:\cygwin64\home\Cifram\test\target\deps`
error: linking with `gcc` failed: exit code: 1
note: gcc '-m64' '-L' 'C:\Program Files (x86)\Rust\bin\rustlib\x86_64-w64-mingw32\lib' '-o' 'C:\cygwin64\home\Cifram\test\target\test.exe' 'C:\cygwin64\home\Cifram\test\target\test.o' '-Wl,--whole-archive' '-lmorestack' '-Wl,--no-whole-archive' '-fno-lto' '-fno-use-linker-plugin' '-Wl,--gc-sections' '-static-libgcc' '-Wl,--enable-long-section-names' '-Wl,--nxcompat' 'C:\Program Files (x86)\Rust\bin\rustlib\x86_64-w64-mingw32\lib\libnative-4e7c5e5c.rlib' 'C:\Program Files (x86)\Rust\bin\rustlib\x86_64-w64-mingw32\lib\libstd-4e7c5e5c.rlib' 'C:\Program Files (x86)\Rust\bin\rustlib\x86_64-w64-mingw32\lib\libsync-4e7c5e5c.rlib' 'C:\Program Files (x86)\Rust\bin\rustlib\x86_64-w64-mingw32\lib\librustrt-4e7c5e5c.rlib' 'C:\Program Files (x86)\Rust\bin\rustlib\x86_64-w64-mingw32\lib\libcollections-4e7c5e5c.rlib' 'C:\Program Files (x86)\Rust\bin\rustlib\x86_64-w64-mingw32\lib\liballoc-4e7c5e5c.rlib' 'C:\Program Files (x86)\Rust\bin\rustlib\x86_64-w64-mingw32\lib\libunicode-4e7c5e5c.rlib' 'C:\Program Files (x86)\Rust\bin\rustlib\x86_64-w64-mingw32\lib\liblibc-4e7c5e5c.rlib' 'C:\Program Files (x86)\Rust\bin\rustlib\x86_64-w64-mingw32\lib\librand-4e7c5e5c.rlib' 'C:\Program Files (x86)\Rust\bin\rustlib\x86_64-w64-mingw32\lib\libcore-4e7c5e5c.rlib' '-L' 'C:\cygwin64\home\Cifram\test\target' '-L' 'C:\cygwin64\home\Cifram\test\target\deps' '-L' 'C:\cygwin64\home\Cifram\test\.rust' '-L' 'C:\cygwin64\home\Cifram\test' '-Wl,--whole-archive' '-Wl,-Bstatic' '-Wl,--no-whole-archive' '-Wl,-Bdynamic' '-lws2_32' '-lcompiler-rt'
note: C:\cygwin64\home\Cifram\test\target\test.o: file not recognized: File format not recognized
collect2.exe: error: ld returned 1 exit status

error: aborting due to previous error
Could not compile `test`.

Caused by:
  Process didn't exit successfully: `rustc C:\cygwin64\home\Cifram\test\src\main.rs --crate-name test --crate-type bin -g --out-dir C:\cygwin64\home\Cifram\test\target --dep-info C:\cygwin64\home\Cifram\test\target\.fingerprint\test-51757ad0485ed143\dep-bin-test -L C:\cygwin64\home\Cifram\test\target -L C:\cygwin64\home\Cifram\test\target\deps` (status=101)

我不确定为什么rustc在调用gcc,因为我理解它是基于LLVM构建的。我确实安装了通过MinGW安装的gcc,所以我的第一个想法是可能那个gcc安装正在干扰。

Cifram@Valyria ~
$ gcc -v
Using built-in specs.
COLLECT_GCC=C:\MinGW\bin\gcc.exe
COLLECT_LTO_WRAPPER=c:/mingw/bin/../libexec/gcc/mingw32/4.8.1/lto-wrapper.exe
Target: mingw32
Configured with: ../gcc-4.8.1/configure --prefix=/mingw --host=mingw32 --build=mingw32 --without-pic --enable-shared --enable-static --with-gnu-ld --enable-lto --enable-libssp --disable-multilib --enable-languages=c,c++,fortran,objc,obj-c++,ada --disable-sjlj-exceptions --with-dwarf2 --disable-win32-registry --enable-libstdcxx-debug --enable-version-specific-runtime-libs --with-gmp=/usr/src/pkg/gmp-5.1.2-1-mingw32-src/bld --with-mpc=/usr/src/pkg/mpc-1.0.1-1-mingw32-src/bld --with-mpfr= --with-system-zlib --with-gnu-as --enable-decimal-float=yes --enable-libgomp --enable-threads --with-libiconv-prefix=/mingw32 --with-libintl-prefix=/mingw --disable-bootstrap LDFLAGS=-s CFLAGS=-D_USE_32BIT_TIME_T
Thread model: win32
gcc version 4.8.1 (GCC)

这是gcc的最新版本。但是,它可能不是rustc所期望的版本。因此,我从我的路径中移除了C:\MinGW\bin并再次尝试,结果如下:

Cifram@Valyria ~/test
$ cargo run --verbose
   Compiling test v0.0.1 (file:///C:/cygwin64/home/Cifram/test)
     Running `rustc C:\cygwin64\home\Cifram\test\src\main.rs --crate-name test --crate-type bin -g --out-dir C:\cygwin64\home\Cifram\test\target --dep-info C:\cygwin64\home\Cifram\test\target\.fingerprint\test-51757ad0485ed143\dep-bin-test -L C:\cygwin64\home\Cifram\test\target -L C:\cygwin64\home\Cifram\test\target\deps`
error: linking with `gcc` failed: exit code: 1
note: gcc '-m64' '-L' 'C:\Program Files (x86)\Rust\bin\rustlib\x86_64-w64-mingw32\lib' '-o' 'C:\cygwin64\home\Cifram\test\target\test.exe' 'C:\cygwin64\home\Cifram\test\target\test.o' '-Wl,--whole-archive' '-lmorestack' '-Wl,--no-whole-archive' '-fno-lto' '-fno-use-linker-plugin' '-Wl,--gc-sections' '-static-libgcc' '-Wl,--enable-long-section-names' '-Wl,--nxcompat' 'C:\Program Files (x86)\Rust\bin\rustlib\x86_64-w64-mingw32\lib\libnative-4e7c5e5c.rlib' 'C:\Program Files (x86)\Rust\bin\rustlib\x86_64-w64-mingw32\lib\libstd-4e7c5e5c.rlib' 'C:\Program Files (x86)\Rust\bin\rustlib\x86_64-w64-mingw32\lib\librand-4e7c5e5c.rlib' 'C:\Program Files (x86)\Rust\bin\rustlib\x86_64-w64-mingw32\lib\libsync-4e7c5e5c.rlib' 'C:\Program Files (x86)\Rust\bin\rustlib\x86_64-w64-mingw32\lib\librustrt-4e7c5e5c.rlib' 'C:\Program Files (x86)\Rust\bin\rustlib\x86_64-w64-mingw32\lib\libcollections-4e7c5e5c.rlib' 'C:\Program Files (x86)\Rust\bin\rustlib\x86_64-w64-mingw32\lib\liballoc-4e7c5e5c.rlib' 'C:\Program Files (x86)\Rust\bin\rustlib\x86_64-w64-mingw32\lib\liblibc-4e7c5e5c.rlib' 'C:\Program Files (x86)\Rust\bin\rustlib\x86_64-w64-mingw32\lib\libunicode-4e7c5e5c.rlib' 'C:\Program Files (x86)\Rust\bin\rustlib\x86_64-w64-mingw32\lib\libcore-4e7c5e5c.rlib' '-L' 'C:\cygwin64\home\Cifram\test\target' '-L' 'C:\cygwin64\home\Cifram\test\target\deps' '-L' 'C:\cygwin64\home\Cifram\test\.rust' '-L' 'C:\cygwin64\home\Cifram\test' '-Wl,--whole-archive' '-Wl,-Bstatic' '-Wl,--no-whole-archive' '-Wl,-Bdynamic' '-lws2_32' '-lcompiler-rt'
note: ld: this linker was not configured to use sysroots

error: aborting due to previous error
Could not compile `test`.

Caused by:
  Process didn't exit successfully: `rustc C:\cygwin64\home\Cifram\test\src\main.rs --crate-name test --crate-type bin -g --out-dir C:\cygwin64\home\Cifram\test\target --dep-info C:\cygwin64\home\Cifram\test\target\.fingerprint\test-51757ad0485ed143\dep-bin-test -L C:\cygwin64\home\Cifram\test\target -L C:\cygwin64\home\Cifram\test\target\deps` (status=101)

好的,这是一个略有不同但并不更好的错误。相同的gcc命令失败了,但是,在此之前的错误是:

C:\cygwin64\home\Cifram\test\target\test.o: file not recognized: File format not recognized

现在它是:

ld: this linker was not configured to use sysroots

我并不认为这两个都非常有意义。我尝试直接运行"rustc main.rs"。得到了相同的错误(除了它是“src\main.o”而不是“target\test.o”)。尝试在本机Windows命令行上完成所有操作,而不是使用cygwin。相同的错误。所以似乎不应该归咎于Cargo或cygwin。我还尝试下载Rust的最新“稳定”版本(0.12.0),但仍然遇到了相同的错误。我已经搜索了这些错误,但没有结果。所以我开始失去主意。
需要帮助吗?

2
根据Rust的维基,你应该从PATH中删除MinGW以使用Rust捆绑的gcc。在0.12之前的版本中,需要单独安装MinGW。我认为你的第一个错误是由于使用针对x86-64的Rust编译器目标和针对i386的链接器。至于你的第二个错误,我不知道。 - Francis Gagné
啊,谢谢提供链接!这至少解决了难题的一部分。虽然很不方便,当我使用Rust时不能在路径中使用gcc。这使得编译任何我想要在Rust中链接的C库(例如SDL2)变得非常麻烦。 - Michael Powell
3个回答

4

成功了!问题原来是我在cygwin里也安装了ld。据我所知,它使用的是随rustc一起发布的gcc版本,但是该gcc却调用了C:\ cygwin64 \ bin \ ld.exe,而不是自己内部的ld。

只要我删除了ld,一切就正常了。

顺便说一句,这强化了我在评论中提出的观点:显然我不能同时在同一台机器上进行Rust开发和C / C ++开发。即使是编译我想在Rust中访问的C库,如SDL2或GLFW。这非常不方便。如果rustc需要特定版本的gcc和ld,并且附带正确版本,则不应默认调用系统版本。如果需要覆盖其gcc或ld版本,则应通过显式命令行选项来完成。

编辑:添加了一个遗漏的“not”,无意中颠倒了一个句子的含义。


2
“它应默认调用系统版本”=> 问题在于,在Windows上没有名为“系统版本”的GCC。有各种竞争版本(MinGW,MinGW-w64,Cygwin)。您确实可以在同一台计算机上进行Rust和C/C ++开发,但是您可能需要创建一些批处理文件,以便为每个设置环境变量(如果您使用命令解释器/ shell来调用编译器)。” - Francis Gagné
1
抱歉,我在那句话中漏掉了一个“不”字。已经修正。 - Michael Powell

3
作为一种替代方案,我在从我的Cygwin shell环境中调用Rust时操纵了路径变量。根据我理解的方式,Rust将使用系统路径搜索gcc,然后尝试使用它。通过操作路径来删除不需要的GCC,它将回退并使用Rust安装程序提供的那个。

PATH='/c/Program Files/Rust/bin' cargo build

*请使用正确的Cygwin路径来安装Rust。在我的系统中,这是/c/Program...


这个主意还不错。在Rust中被限制在gcc版本上是不幸的,但比起每次想要在Rust和C/C++开发之间切换时都需要重新调整路径来说,这还是更好的选择。 - Michael Powell

0
一个解决方案是在RUSTFLAGS变量中设置链接器路径,如下所示: RUSTFLAGS = -C linker=%RUST_HOME%\lib\rustlib\x86_64-pc-windows-gnu\bin\self-contained\ld.exe 这样你就可以在路径中同时拥有gcc和工作的rust编译器。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接