Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

rustdoc beta linking trouble in MinGW #41607

Closed
tspiteri opened this issue Apr 28, 2017 · 27 comments
Closed

rustdoc beta linking trouble in MinGW #41607

tspiteri opened this issue Apr 28, 2017 · 27 comments
Assignees
Labels
A-linkage Area: linking into static, shared libraries and binaries C-bug Category: This is a bug. P-medium Medium priority regression-from-stable-to-stable Performance or correctness regression from one stable version to another. T-dev-tools Relevant to the dev-tools subteam, which will review and decide on the PR/issue. T-rustdoc Relevant to the rustdoc team, which will review and decide on the PR/issue.

Comments

@tspiteri
Copy link
Contributor

I have a crate rugflo which depends on a crate gmp-mpfr-sys. The gmp-mpfr-sys crate includes three C libraries that are compiled during crate compilation. One of the C libraries apparently makes use of __emutls_get_address, and the rugflo crate makes use of this library.

If I run

cargo +beta test -p rugflo

the #[test] tests succeed, but the inline documentation tests fail. On stable, both #[test] and inline documentation tests succeed. I'm including part of the error message below.

This is on the beta-x86_64-pc-windows-gnu toolchain, with beta version 1.18.0-beta.1 (4dce672 2017-04-25).

failures:

---- src\float.rs - float::Float::assign_str (line 1566) stdout ----
	error: linking with `gcc` failed: exit code: 1
  |
  = note: "gcc" "-Wl,--enable-long-section-names" "-fno-use-linker-plugin" "-Wl,--nxcompat" "-nostdlib" "-m64" "C:\\Users\\Trevor\\.rustup\\toolchains\\beta-x86_64-pc-windows-gnu\\lib\\rustlib\\x86_64-pc-windows-gnu\\lib\\crt2.o" "C:\\Users\\Trevor\\.rustup\\toolchains\\beta-x86_64-pc-windows-gnu\\lib\\rustlib\\x86_64-pc-windows-gnu\\lib\\rsbegin.o" "-L" "C:\\Users\\Trevor\\.rustup\\toolchains\\beta-x86_64-pc-windows-gnu\\lib\\rustlib\\x86_64-pc-windows-gnu\\lib" "C:\\Users\\Trevor\\AppData\\Local\\Temp\\rustdoctest.SrhC8rnnvQEZ\\rust_out.0.o" "-o" "C:\\Users\\Trevor\\AppData\\Local\\Temp\\rustdoctest.SrhC8rnnvQEZ\\rust_out.exe" "-Wl,--gc-sections" "-nodefaultlibs" "-L" "c:\\Users\\Trevor\\projects\\t\\target\\debug\\deps" "-L" "c:\\Users\\Trevor\\projects\\t\\target\\debug\\build\\gmp-mpfr-sys-0cc9b17adf0b6ee9\\out\\lib" "-L" "C:\\Users\\Trevor\\.rustup\\toolchains\\beta-x86_64-pc-windows-gnu\\lib\\rustlib\\x86_64-pc-windows-gnu\\lib" "-Wl,-Bstatic" "C:\\Users\\Trevor\\projects\\t\\target\\debug\\deps\\librugflo-b0b353c1d0de4acc.rlib" "C:\\Users\\Trevor\\projects\\t\\target\\debug\\deps\\librugrat-06b8c4776c6f6356.rlib" "C:\\Users\\Trevor\\projects\\t\\target\\debug\\deps\\librugint-0f0e67a952d13d05.rlib" "C:\\Users\\Trevor\\projects\\t\\target\\debug\\deps\\libgmp_mpfr_sys-ec78d94836c71bdb.rlib" "C:\\Users\\Trevor\\projects\\t\\target\\debug\\deps\\librand-76456d761c2cb637.rlib" "-L" "C:\\Users\\Trevor\\.rustup\\toolchains\\beta-x86_64-pc-windows-gnu\\lib\\rustlib\\x86_64-pc-windows-gnu\\lib" "-Wl,-Bdynamic" "-l" "std-e2451a256f66ac19" "-Wl,-Bstatic" "C:\\Users\\Trevor\\.rustup\\toolchains\\beta-x86_64-pc-windows-gnu\\lib\\rustlib\\x86_64-pc-windows-gnu\\lib\\libcompiler_builtins-91b619d34dd1f5aa.rlib" "-Wl,-Bdynamic" "-l" "advapi32" "-l" "advapi32" "-l" "ws2_32" "-l" "userenv" "-l" "shell32" "-lmingwex" "-lmingw32" "-lgcc" "-lmsvcrt" "-luser32" "-lkernel32" "C:\\Users\\Trevor\\.rustup\\toolchains\\beta-x86_64-pc-windows-gnu\\lib\\rustlib\\x86_64-pc-windows-gnu\\lib\\rsend.o"
  = note: C:\Users\Trevor\projects\t\target\debug\deps\libgmp_mpfr_sys-ec78d94836c71bdb.rlib(exceptions.o):exceptions.c:(.text+0xc): undefined reference to `__emutls_get_address'
          C:\Users\Trevor\projects\t\target\debug\deps\libgmp_mpfr_sys-ec78d94836c71bdb.rlib(exceptions.o):exceptions.c:(.text+0x42): undefined reference to `__emutls_get_address'
          C:\Users\Trevor\projects\t\target\debug\deps\libgmp_mpfr_sys-ec78d94836c71bdb.rlib(exceptions.o):exceptions.c:(.text+0x7c): undefined reference to `__emutls_get_address'
          C:\Users\Trevor\projects\t\target\debug\deps\libgmp_mpfr_sys-ec78d94836c71bdb.rlib(exceptions.o):exceptions.c:(.text+0xb2): undefined reference to `__emutls_get_address'
          C:\Users\Trevor\projects\t\target\debug\deps\libgmp_mpfr_sys-ec78d94836c71bdb.rlib(exceptions.o):exceptions.c:(.text+0xec): undefined reference to `__emutls_get_address'
          C:\Users\Trevor\projects\t\target\debug\deps\libgmp_mpfr_sys-ec78d94836c71bdb.rlib(exceptions.o):exceptions.c:(.text+0x10c): more undefined references to `__emutls_get_address' follow
          

error: aborting due to previous error

thread 'rustc' panicked at 'Box<Any>', src\librustc_errors\lib.rs:453
note: Run with `RUST_BACKTRACE=1` for a backtrace.
thread 'rustc' panicked at 'couldn't compile the test', src\librustdoc\test.rs:273

---- src\float.rs - float::Constant (line 130) stdout ----
	error: linking with `gcc` failed: exit code: 1
  |

...
(repetitions)
...

thread 'rustc' panicked at 'Box<Any>', src\librustc_errors\lib.rs:453
thread 'rustc' panicked at 'couldn't compile the test', src\librustdoc\test.rs:273


failures:
    src\float.rs - float::Constant (line 130)
    src\float.rs - float::Float::assign_random_bits_round (line 1237)
    src\float.rs - float::Float::assign_random_cont_round (line 1344)
    src\float.rs - float::Float::assign_str (line 1566)
    src\float.rs - float::Float::assign_str_radix (line 1583)
    src\float.rs - float::Float::assign_str_radix_round (line 1625)
    src\float.rs - float::Float::assign_str_round (line 1605)
    src\float.rs - float::Float::to_integer_exp (line 344)
    src\float.rs - float::Float::to_string_radix (line 1463)
    src\float.rs - float::Rational::assign (line 2090)
    src\float.rs - float::Rational::from (line 2033)
    src\float.rs - float::Round::Nearest (line 92)
    src\lib.rs -  (line 51)

test result: FAILED. 0 passed; 13 failed; 0 ignored; 0 measured

error: test failed, to rerun pass '--doc'
@alexcrichton alexcrichton added regression-from-stable-to-beta Performance or correctness regression from stable to beta. T-tools labels Apr 28, 2017
@alexcrichton
Copy link
Member

cc @vadimcn @brson

I wonder if this is related to the pthread business on beta? Or maybe this is just related to updating the MinGW compiler we're bundling?

@tspiteri do you have MinGW and/or MSYS installed? Or do you know if you're using the bundled version of gcc that comes with Rust itself?

@tspiteri
Copy link
Contributor Author

I have MinGW and MSYS installed from the msys2.org (msys2.github.io) page. That is needed to build the copies of the GNU libraries GMP, MPFR and MPC in gmp-mpfr-sys.

@vadimcn
Copy link
Contributor

vadimcn commented Apr 28, 2017

@tspiteri: what does gcc --version -v say?

@tspiteri
Copy link
Contributor Author

The gcc version is

gcc.exe (Rev2, Built by MSYS2 project) 6.3.0
Copyright (C) 2016 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.


Using built-in specs.
COLLECT_GCC=C:\msys64\mingw64\bin\gcc.exe
COLLECT_LTO_WRAPPER=C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/6.3.0/lto-wrapper.exe
Target: x86_64-w64-mingw32
Configured with: ../gcc-6.3.0/configure --prefix=/mingw64 --with-local-prefix=/mingw64/local --build=x86_64-w64-mingw32 --host=x86_64-w64-mingw32 --target=x86_64-w64-mingw32 --with-native-system-header-dir=/mingw64/x86_64-w64-mingw32/include --libexecdir=/mingw64/lib --enable-bootstrap --with-arch=x86-64 --with-tune=generic --enable-languages=c,lto,c++,objc,obj-c++,fortran,ada --enable-shared --enable-static --enable-libatomic --enable-threads=posix --enable-graphite --enable-fully-dynamic-string --enable-libstdcxx-time=yes --disable-libstdcxx-pch --disable-libstdcxx-debug --disable-isl-version-check --enable-lto --enable-libgomp --disable-multilib --enable-checking=release --disable-rpath --disable-win32-registry --disable-nls --disable-werror --disable-symvers --with-libiconv --with-system-zlib --with-gmp=/mingw64 --with-mpfr=/mingw64 --with-mpc=/mingw64 --with-isl=/mingw64 --with-pkgversion='Rev2, Built by MSYS2 project' --with-bugurl=https://sourceforge.net/projects/msys2 --with-gnu-as --with-gnu-ld
Thread model: posix
gcc version 6.3.0 (Rev2, Built by MSYS2 project) 
COLLECT_GCC_OPTIONS='--version' '-v' '-mtune=generic' '-march=x86-64'
 C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/6.3.0/cc1.exe -quiet -v -iprefix C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/6.3.0/ -D_REENTRANT help-dummy -quiet -dumpbase help-dummy -mtune=generic -march=x86-64 -auxbase help-dummy -version --version -o C:\Users\Trevor\AppData\Local\Temp\ccCKrqi4.s
GNU C11 (Rev2, Built by MSYS2 project) version 6.3.0 (x86_64-w64-mingw32)
	compiled by GNU C version 6.3.0, GMP version 6.1.2, MPFR version 3.1.5-p2, MPC version 1.0.3, isl version 0.15
GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072
COLLECT_GCC_OPTIONS='--version' '-v' '-mtune=generic' '-march=x86-64'
 C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/6.3.0/../../../../x86_64-w64-mingw32/bin/as.exe -v --version -o C:\Users\Trevor\AppData\Local\Temp\ccqmG10X.o C:\Users\Trevor\AppData\Local\Temp\ccCKrqi4.s
GNU assembler (GNU Binutils) 2.28
Copyright (C) 2017 Free Software Foundation, Inc.
This program is free software; you may redistribute it under the terms of
the GNU General Public License version 3 or later.
This program has absolutely no warranty.
This assembler was configured for a target of `x86_64-w64-mingw32'.
GNU assembler version 2.28 (x86_64-w64-mingw32) using BFD version (GNU Binutils) 2.28
COMPILER_PATH=C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/6.3.0/;C:/msys64/mingw64/bin/../lib/gcc/;C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/6.3.0/../../../../x86_64-w64-mingw32/bin/
LIBRARY_PATH=C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/6.3.0/;C:/msys64/mingw64/bin/../lib/gcc/;C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/6.3.0/../../../../x86_64-w64-mingw32/lib/../lib/;C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/6.3.0/../../../../lib/;C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/6.3.0/../../../../x86_64-w64-mingw32/lib/;C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/6.3.0/../../../
COLLECT_GCC_OPTIONS='--version' '-v' '-mtune=generic' '-march=x86-64'
 C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/6.3.0/collect2.exe -plugin C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/6.3.0/liblto_plugin-0.dll -plugin-opt=C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/6.3.0/lto-wrapper.exe -plugin-opt=-fresolution=C:\Users\Trevor\AppData\Local\Temp\cckLQcNQ.res -plugin-opt=-pass-through=-lmingw32 -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lgcc_eh -plugin-opt=-pass-through=-lmoldname -plugin-opt=-pass-through=-lmingwex -plugin-opt=-pass-through=-lmsvcrt -plugin-opt=-pass-through=-lpthread -plugin-opt=-pass-through=-ladvapi32 -plugin-opt=-pass-through=-lshell32 -plugin-opt=-pass-through=-luser32 -plugin-opt=-pass-through=-lkernel32 -plugin-opt=-pass-through=-lmingw32 -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lgcc_eh -plugin-opt=-pass-through=-lmoldname -plugin-opt=-pass-through=-lmingwex -plugin-opt=-pass-through=-lmsvcrt -m i386pep -Bdynamic --version C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/6.3.0/../../../../x86_64-w64-mingw32/lib/../lib/crt2.o C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/6.3.0/crtbegin.o -LC:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/6.3.0 -LC:/msys64/mingw64/bin/../lib/gcc -LC:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/6.3.0/../../../../x86_64-w64-mingw32/lib/../lib -LC:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/6.3.0/../../../../lib -LC:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/6.3.0/../../../../x86_64-w64-mingw32/lib -LC:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/6.3.0/../../.. C:\Users\Trevor\AppData\Local\Temp\ccqmG10X.o -lmingw32 -lgcc -lgcc_eh -lmoldname -lmingwex -lmsvcrt -lpthread -ladvapi32 -lshell32 -luser32 -lkernel32 -lmingw32 -lgcc -lgcc_eh -lmoldname -lmingwex -lmsvcrt C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/6.3.0/../../../../x86_64-w64-mingw32/lib/../lib/default-manifest.o C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/6.3.0/crtend.o
collect2 version 6.3.0
C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/6.3.0/../../../../x86_64-w64-mingw32/bin/ld.exe -plugin C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/6.3.0/liblto_plugin-0.dll -plugin-opt=C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/6.3.0/lto-wrapper.exe -plugin-opt=-fresolution=C:\Users\Trevor\AppData\Local\Temp\cckLQcNQ.res -plugin-opt=-pass-through=-lmingw32 -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lgcc_eh -plugin-opt=-pass-through=-lmoldname -plugin-opt=-pass-through=-lmingwex -plugin-opt=-pass-through=-lmsvcrt -plugin-opt=-pass-through=-lpthread -plugin-opt=-pass-through=-ladvapi32 -plugin-opt=-pass-through=-lshell32 -plugin-opt=-pass-through=-luser32 -plugin-opt=-pass-through=-lkernel32 -plugin-opt=-pass-through=-lmingw32 -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lgcc_eh -plugin-opt=-pass-through=-lmoldname -plugin-opt=-pass-through=-lmingwex -plugin-opt=-pass-through=-lmsvcrt -m i386pep -Bdynamic --version C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/6.3.0/../../../../x86_64-w64-mingw32/lib/../lib/crt2.o C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/6.3.0/crtbegin.o -LC:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/6.3.0 -LC:/msys64/mingw64/bin/../lib/gcc -LC:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/6.3.0/../../../../x86_64-w64-mingw32/lib/../lib -LC:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/6.3.0/../../../../lib -LC:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/6.3.0/../../../../x86_64-w64-mingw32/lib -LC:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/6.3.0/../../.. C:\Users\Trevor\AppData\Local\Temp\ccqmG10X.o -lmingw32 -lgcc -lgcc_eh -lmoldname -lmingwex -lmsvcrt -lpthread -ladvapi32 -lshell32 -luser32 -lkernel32 -lmingw32 -lgcc -lgcc_eh -lmoldname -lmingwex -lmsvcrt C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/6.3.0/../../../../x86_64-w64-mingw32/lib/../lib/default-manifest.o C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/6.3.0/crtend.o
GNU ld (GNU Binutils) 2.28
Copyright (C) 2017 Free Software Foundation, Inc.
This program is free software; you may redistribute it under the terms of
the GNU General Public License version 3 or (at your option) a later version.
This program has absolutely no warranty.
COLLECT_GCC_OPTIONS='--version' '-v' '-mtune=generic' '-march=x86-64'

@tspiteri
Copy link
Contributor Author

tspiteri commented Apr 28, 2017

I've done some narrowing, and the problem is on nightly-2017-04-07-x86_64-pc-windows-gnu, but everything is fine on nightly-2017-04-06-x86_64-pc-windows-gnu. And the problem is only in the testing of inline docs. Other tests, as well as dependent applications, all run fine.

Edit: And the same happens for the i686 toolchain on a 32-bit MSYS shell. Everything works fine on nightly-2017-04-06-i686-pc-windows-gnu, but the issue is there on nightly-2017-04-07-i686-pc-windows-gnu.

@tspiteri
Copy link
Contributor Author

tspiteri commented May 2, 2017

I'm attaching a reduced test case. cargo +nightly-2017-04-06 test succeeds and cargo +nightly-2017-04-07 test fails on inline docs.

try.zip

@alexcrichton
Copy link
Member

Ok thanks for testing @tspiteri! @vadimcn that range of nightlies notably includes #40805 which I suspect is causing problems here.

After some investigation it seems that this is related to the switch to static-nobundle from the previous dylib link kind. The doc test is linking dynamically to libstd whereas the normal unit test is linking statically. This means that the normal doctest is not receiving the -lgcc -lpthread arguments, whereas the test executable is indeed receiving -lgcc -lpthread, explaining why the test executable links correctly but the doctest does not.

Essentially I believe these lines boil down to a regression.

I'm not really sure what to do about this situation. We've gotten ourselves into quite the quagmire with MinGW and the compiler. @vadimcn do you have thoughts?

@brson brson added P-medium Medium priority A-linkage Area: linking into static, shared libraries and binaries T-rustdoc Relevant to the rustdoc team, which will review and decide on the PR/issue. labels May 4, 2017
@alexcrichton
Copy link
Member

Ok so drilling more into this regression:

  • Win32 toolchains only require -lgcc_eh to be passed to keep working
  • Pthread toolchains require both -lgcc_eh and -lpthread
  • If you have the rust-mingw package installed, then that's now a pthread toolchain, which means it's basically impossible to get working. Even if you override -C linker it won't work because we bundle the pthread-requiring libs.

I honestly don't know what to do about this regression. @tspiteri my best suggestion to you is to uninstall the x86_64-pc-windows-gnu Rust compilers. Instead you'll typically get much better mileage from an x86_64-pc-windows-msvc compiler cross-compiling to x86_64-pc-windows-gnu. The downside of this approach is that you may need to install the VS build tools to work with plugins and such.

Other than that though the only way I can see to fix this is to switch from static-nobundle for these libs back to dylib. I don't really know if that will have a larger impact or fix this, it's unknown to me.

@alexcrichton
Copy link
Member

Also cc @rust-lang/tools, there may be more opinions on this as well.

@tspiteri
Copy link
Contributor Author

tspiteri commented May 5, 2017

About cross-compiling from x86_64-pc-windows-msvc to x86_64-pc-windows-gnu, stable-msvc (or nightly-2017-04-06-msvc) fails to compile the test executable, and beta-msvc (or nightly-2017-04-07-msvc) passes the test executable but is not even trying the doc test. Since the original issue was with the doc test, this seems to not fix anything, and only succeeds to the same level as cargo +beta test --lib succeeds. Am I missing something @alexcrichton? I'm including output of the four situations below.

  1. stable-gnu or nightly-2017-04-06-gnu. Works fine.
/c/try$ cargo clean
/c/try$ cargo +nightly-2017-04-06-gnu test
   Compiling try v0.1.0 (file:///C:/try)
    Finished dev [unoptimized + debuginfo] target(s) in 1.56 secs
     Running target\debug\deps\try-69341e42640d09fb.exe

running 1 test
test tests::t ... ok

test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured

   Doc-tests try

running 1 test
test src\lib.rs -  (line 3) ... ok

test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured
  1. beta-gnu or nightly-2017-04-07-gnu. Test executable fine, but fails doc test. This is the original reported regression.
/c/try$ cargo clean
/c/try$ cargo +nightly-2017-04-07-gnu test
   Compiling try v0.1.0 (file:///C:/try)
    Finished dev [unoptimized + debuginfo] target(s) in 1.44 secs
     Running target\debug\deps\try-ebd40fb5c9184741.exe

running 1 test
test tests::t ... ok

test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured

   Doc-tests try

running 1 test
test src\lib.rs -  (line 3) ... FAILED

failures:

---- src\lib.rs -  (line 3) stdout ----
	error: linking with `gcc` failed: exit code: 1
  |
  = note: "gcc" "-Wl,--enable-long-section-names" "-fno-use-linker-plugin" "-Wl,--nxcompat" "-nostdlib" "-m64" "C:\\Users\\Trevor\\.rustup\\toolchains\\nightly-2017-04-07-x86_64-pc-windows-gnu\\lib\\rustlib\\x86_64-pc-windows-gnu\\lib\\crt2.o" "C:\\Users\\Trevor\\.rustup\\toolchains\\nightly-2017-04-07-x86_64-pc-windows-gnu\\lib\\rustlib\\x86_64-pc-windows-gnu\\lib\\rsbegin.o" "-L" "C:\\Users\\Trevor\\.rustup\\toolchains\\nightly-2017-04-07-x86_64-pc-windows-gnu\\lib\\rustlib\\x86_64-pc-windows-gnu\\lib" "C:\\Users\\Trevor\\AppData\\Local\\Temp\\rustdoctest.Ll2ouv1FREn9\\rust_out.0.o" "-o" "C:\\Users\\Trevor\\AppData\\Local\\Temp\\rustdoctest.Ll2ouv1FREn9\\rust_out.exe" "-Wl,--gc-sections" "-nodefaultlibs" "-L" "C:\\try\\target\\debug\\deps" "-L" "C:\\try\\target\\debug\\build\\try-6cfbfcbf6205bd80\\out" "-L" "C:\\Users\\Trevor\\.rustup\\toolchains\\nightly-2017-04-07-x86_64-pc-windows-gnu\\lib\\rustlib\\x86_64-pc-windows-gnu\\lib" "-Wl,-Bstatic" "C:\\try\\target\\debug\\deps\\libtry-cca920ec7eb23b3b.rlib" "-L" "C:\\Users\\Trevor\\.rustup\\toolchains\\nightly-2017-04-07-x86_64-pc-windows-gnu\\lib\\rustlib\\x86_64-pc-windows-gnu\\lib" "-Wl,-Bdynamic" "-l" "std-e2451a256f66ac19" "-Wl,-Bstatic" "C:\\Users\\Trevor\\.rustup\\toolchains\\nightly-2017-04-07-x86_64-pc-windows-gnu\\lib\\rustlib\\x86_64-pc-windows-gnu\\lib\\libcompiler_builtins-91b619d34dd1f5aa.rlib" "-Wl,-Bdynamic" "-l" "advapi32" "-l" "ws2_32" "-l" "userenv" "-l" "shell32" "-lmingwex" "-lmingw32" "-lgcc" "-lmsvcrt" "-luser32" "-lkernel32" "C:\\Users\\Trevor\\.rustup\\toolchains\\nightly-2017-04-07-x86_64-pc-windows-gnu\\lib\\rustlib\\x86_64-pc-windows-gnu\\lib\\rsend.o"
  = note: C:\try\target\debug\deps\libtry-cca920ec7eb23b3b.rlib(trytls.o):trytls.c:(.text+0x13): undefined reference to `__emutls_get_address'
          

error: aborting due to previous error

thread 'rustc' panicked at 'Box<Any>', src\librustc_errors\lib.rs:453
note: Run with `RUST_BACKTRACE=1` for a backtrace.
thread 'rustc' panicked at 'couldn't compile the test', src\librustdoc\test.rs:270


failures:
    src\lib.rs -  (line 3)

test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured

error: test failed, to rerun pass '--doc'
  1. Cross compile from stable-msvc or nightly-2017-04-06-msvc. Fails to compile test executable.
/c/try$ cargo clean
/c/try$ cargo +nightly-2017-04-06-msvc test --target x86_64-pc-windows-gnu
   Compiling try v0.1.0 (file:///C:/try)
error: linking with `gcc` failed: exit code: 1
  |
  = note: "gcc" "-Wl,--enable-long-section-names" "-fno-use-linker-plugin" "-Wl,--nxcompat" "-nostdlib" "-m64" "C:\\Users\\Trevor\\.rustup\\toolchains\\nightly-2017-04-06-x86_64-pc-windows-msvc\\lib\\rustlib\\x86_64-pc-windows-gnu\\lib\\crt2.o" "C:\\Users\\Trevor\\.rustup\\toolchains\\nightly-2017-04-06-x86_64-pc-windows-msvc\\lib\\rustlib\\x86_64-pc-windows-gnu\\lib\\rsbegin.o" "-L" "C:\\Users\\Trevor\\.rustup\\toolchains\\nightly-2017-04-06-x86_64-pc-windows-msvc\\lib\\rustlib\\x86_64-pc-windows-gnu\\lib" "C:\\try\\target\\x86_64-pc-windows-gnu\\debug\\deps\\try-69341e42640d09fb.0.o" "-o" "C:\\try\\target\\x86_64-pc-windows-gnu\\debug\\deps\\try-69341e42640d09fb.exe" "-Wl,--gc-sections" "-nodefaultlibs" "-L" "C:\\try\\target\\x86_64-pc-windows-gnu\\debug\\deps" "-L" "C:\\try\\target\\debug\\deps" "-L" "C:\\try\\target\\x86_64-pc-windows-gnu\\debug\\build\\try-44fe5ac8b7af6654\\out" "-L" "C:\\Users\\Trevor\\.rustup\\toolchains\\nightly-2017-04-06-x86_64-pc-windows-msvc\\lib\\rustlib\\x86_64-pc-windows-gnu\\lib" "-Wl,-Bstatic" "-Wl,--whole-archive" "-l" "trytls" "-Wl,--no-whole-archive" "-Wl,-Bdynamic" "C:\\Users\\Trevor\\.rustup\\toolchains\\nightly-2017-04-06-x86_64-pc-windows-msvc\\lib\\rustlib\\x86_64-pc-windows-gnu\\lib\\libtest-4395313c6149eab1.rlib" "C:\\Users\\Trevor\\.rustup\\toolchains\\nightly-2017-04-06-x86_64-pc-windows-msvc\\lib\\rustlib\\x86_64-pc-windows-gnu\\lib\\libgetopts-43e5e3367717c4c8.rlib" "C:\\Users\\Trevor\\.rustup\\toolchains\\nightly-2017-04-06-x86_64-pc-windows-msvc\\lib\\rustlib\\x86_64-pc-windows-gnu\\lib\\libterm-94eca2ffe2bbb128.rlib" "C:\\Users\\Trevor\\.rustup\\toolchains\\nightly-2017-04-06-x86_64-pc-windows-msvc\\lib\\rustlib\\x86_64-pc-windows-gnu\\lib\\libstd-e2451a256f66ac19.rlib" "C:\\Users\\Trevor\\.rustup\\toolchains\\nightly-2017-04-06-x86_64-pc-windows-msvc\\lib\\rustlib\\x86_64-pc-windows-gnu\\lib\\libpanic_unwind-2d4bf02140c11dcb.rlib" "C:\\Users\\Trevor\\.rustup\\toolchains\\nightly-2017-04-06-x86_64-pc-windows-msvc\\lib\\rustlib\\x86_64-pc-windows-gnu\\lib\\libunwind-add7a84d7e82d084.rlib" "C:\\Users\\Trevor\\.rustup\\toolchains\\nightly-2017-04-06-x86_64-pc-windows-msvc\\lib\\rustlib\\x86_64-pc-windows-gnu\\lib\\liblibc-84688accbc86d6b7.rlib" "C:\\Users\\Trevor\\.rustup\\toolchains\\nightly-2017-04-06-x86_64-pc-windows-msvc\\lib\\rustlib\\x86_64-pc-windows-gnu\\lib\\librand-c279a51d66700350.rlib" "C:\\Users\\Trevor\\.rustup\\toolchains\\nightly-2017-04-06-x86_64-pc-windows-msvc\\lib\\rustlib\\x86_64-pc-windows-gnu\\lib\\libcollections-d7bf31a4ca1ea637.rlib" "C:\\Users\\Trevor\\.rustup\\toolchains\\nightly-2017-04-06-x86_64-pc-windows-msvc\\lib\\rustlib\\x86_64-pc-windows-gnu\\lib\\liballoc-fe2e68b21f0bdd7a.rlib" "C:\\Users\\Trevor\\.rustup\\toolchains\\nightly-2017-04-06-x86_64-pc-windows-msvc\\lib\\rustlib\\x86_64-pc-windows-gnu\\lib\\liballoc_system-7fc0381594c93f56.rlib" "C:\\Users\\Trevor\\.rustup\\toolchains\\nightly-2017-04-06-x86_64-pc-windows-msvc\\lib\\rustlib\\x86_64-pc-windows-gnu\\lib\\libstd_unicode-d367c3ba0db49600.rlib" "C:\\Users\\Trevor\\.rustup\\toolchains\\nightly-2017-04-06-x86_64-pc-windows-msvc\\lib\\rustlib\\x86_64-pc-windows-gnu\\lib\\libcore-ea9d77e7c23fe65c.rlib" "C:\\Users\\Trevor\\.rustup\\toolchains\\nightly-2017-04-06-x86_64-pc-windows-msvc\\lib\\rustlib\\x86_64-pc-windows-gnu\\lib\\libcompiler_builtins-91b619d34dd1f5aa.rlib" "-l" "kernel32" "-l" "advapi32" "-l" "ws2_32" "-l" "userenv" "-l" "shell32" "-l" "gcc_eh" "-lmingwex" "-lmingw32" "-lgcc" "-lmsvcrt" "-luser32" "-lkernel32" "C:\\Users\\Trevor\\.rustup\\toolchains\\nightly-2017-04-06-x86_64-pc-windows-msvc\\lib\\rustlib\\x86_64-pc-windows-gnu\\lib\\rsend.o"
  = note: C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/6.3.0/libgcc_eh.a(emutls.o):(.text+0x4e): undefined reference to `pthread_mutex_init'
          C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/6.3.0/libgcc_eh.a(emutls.o):(.text+0x61): undefined reference to `pthread_key_create'
          C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/6.3.0/libgcc_eh.a(emutls.o):(.text+0x9d): undefined reference to `pthread_getspecific'
          C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/6.3.0/libgcc_eh.a(emutls.o):(.text+0xe2): undefined reference to `pthread_once'
          C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/6.3.0/libgcc_eh.a(emutls.o):(.text+0xee): undefined reference to `pthread_mutex_lock'
          C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/6.3.0/libgcc_eh.a(emutls.o):(.text+0x107): undefined reference to `pthread_mutex_unlock'
          C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/6.3.0/libgcc_eh.a(emutls.o):(.text+0x13f): undefined reference to `pthread_setspecific'
          C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/6.3.0/libgcc_eh.a(emutls.o):(.text+0x1f4): undefined reference to `pthread_setspecific'
          collect2.exe: error: ld returned 1 exit status
          

error: aborting due to previous error

error: Could not compile `try`.

To learn more, run the command again with --verbose.
  1. Cross compile from beta-msvc or nightly-2017-04-07-msvc. Test executable fine, but doc test not attempted.
/c/try$ cargo clean
/c/try$ cargo +nightly-2017-04-07-msvc test --target x86_64-pc-windows-gnu
   Compiling try v0.1.0 (file:///C:/try)
    Finished dev [unoptimized + debuginfo] target(s) in 1.73 secs
     Running target\x86_64-pc-windows-gnu\debug\deps\try-ebd40fb5c9184741.exe

running 1 test
test tests::t ... ok

test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured

@vadimcn
Copy link
Contributor

vadimcn commented May 5, 2017

@tspiteri, does it link correctly if you declare a dependency on libpthread in gmp-mpfr-sys's build script?

@tspiteri
Copy link
Contributor Author

tspiteri commented May 5, 2017

@vadimcn, your suggestion works, though I needed gcc_eh, not pthread. In try/build.rs I added this line:

    println!("cargo:rustc-link-lib=static=gcc_eh");

and both cargo +stable-gnu test and cargo +beta-gnu test work for both the test executable and for the doc test.

Note that compiling gmp-mpfr-sys takes a long time to compile its three C libraries, and the crate in try.zip in #41607 (comment) shows the same regression. (In this case I also tested cargo +beta test -p rugflo after adding the gcc_eh line in gmp-mpfr-sys/build.rs just to make sure, and it worked.)

@vadimcn
Copy link
Contributor

vadimcn commented May 5, 2017

Okay, so here's what I think is happening:

  • The __emutls_get_address is exported from the libgcc_eh.a library. (A bit strange place for it, since libgcc_eh is supposed to be about exceptions and stack unwinding. I'd have expected TLS-related stuff to be in libpthread. But whatever).
  • The only standard crate that depends on libgcc_eh is panic_unwind, (to which it is specified as "static-nobundle" dependency, so only a reference is included in libpanic_unwind.rlib, not object files). I'll also note that "static-nobundle" was also made in [Windows] Enable building rustc with "pthreads" flavor of mingw. #40805, just for consistency with libpthread, without giving it much thought .
  • When linking statically, rustc adds -lgcc_eh to the linker command line to satisfy panic_unwind's dependency. Of course, this also satisfies references from other objects/libraries, such as gmp-mpfr-sys's.
  • When linking dynamically, -lgcc_eh is not added, because it had already been linked into std-xxxxxx.dll along with libpanic_unwind.

Since __emutls_get_address lives in libgcc_eh, I think we can eliminate any libpthread-related changes from suspicion of being the culprit and concentrate on libgcc_eh.

I've just compared an older nightly with latest and it looks like we've stopped emitting -lgcc_eh when linking dynamically. I am not entirely sure why did we ever emit it in the first place... According to my understanding of rust linkage, it should have had been either bundled into libpanic_unwind.rlib, or linked into std-xxxxxxx.dll. Another unintended "bug fix"?


In any event, I think we need to decide who should be responsible for bringing in the libraries required by C/C++ dependencies linked to Rust programs. I think it is still our long-term plan to stop linking any gcc libraries to pure-Rust programs? As we get better in this respect, more and more -sys crates will start failing to compile.

IMO, the cleanest approach would be for the gcc crate to somehow query the system compiler for a list of default libs it would have passed to the linker and emit them as cargo metadata.

Thoughts?

@tspiteri
Copy link
Contributor Author

tspiteri commented May 6, 2017

I just noticed that nightlies from nightly-2017-04-26-x86_64-pc-windows-gnu on also require a "cargo:rustc-link-lib=static=pthread". However, this will break current stable (1.17) with an error: could not find native static library `pthread`, perhaps an -L flag is missing? Interestingly, the i686 toolchain does not require the explicit pthread link.

My current build script workaround is this:

  1. If $HOST and $TARGET both end with "windows-gnu", print "cargo:rustc-link-lib=static=gcc-eh".
  2. If $HOST and $TARGET both end with "windows-gnu", and if rustc version ≥ 1.18, print "cargo:rustc-link-lib=static=pthread".

Edit: Attaching workaround: workaround-try.zip

@vadimcn
Copy link
Contributor

vadimcn commented May 6, 2017

Yeah, the old tool mingw chain did not bundle libpthread, AFAIR.

@vadimcn
Copy link
Contributor

vadimcn commented May 6, 2017

There short term solution might be too change rustc to always emit -lgcc_eh -lpthread, even though Rust crates don't need them.
This sucks, we did a bunch of work to be able to pass -nodefaultlibs to gcc. :(

@alexcrichton
Copy link
Member

@tspiteri ah yes sorry, I forgot about that! Cargo indeed does not run doctests on "cross compiles", e.g. where the host is not the exact same as the target.

@vadimcn yeah I'm not sure what the best solution is here. I think your diagnosis is indeed correct though! FWIW I think we pass -lgcc_eh everywhere before because it was defined with the "dylib" link kind in the panic_unwind crate (or std, I forget), and "dylib" deps propagate lots unlike staticlib/static-nobundle deps which don't propagate.

So some ways forward:

  • Do as you recommended by updating gcc. I... this sounds hard.
  • Switch back to the "dylib" link kind for gcc_eh and pthread.
  • Mark symbols like __emutls_get_address exported from std-*.dll
  • Change doctests to not link dynamically
  • Don't pass -nodefaultlibs on MinGW

I'm not really sure which is the best per-se. I agree that the "cleanest" is to update the gcc crate, but that also has some unfortunate side effects I think. It means that every crate compiled on MinGW will print out -lgcc_eh and then do a bunch of dynamic probing to maybe print out -lpthread as well. Every C crate at that point will then print out the runtime libs? This could be canonicalized in a shared dependency but in some sense that shared dep is std.

I'm not really sure if the -nodefaultlibs piece has really worked out over time. In practice everyone's compiling C and linking it, and we just need to work with that. In some sense that's the whole point of the pc-windows-gnu toolchain, linking with C code...

@tspiteri well in any case your crate can be fixed with these lines in the build script I believe:

println!("cargo:rustc-link-lib=static-nobundle=gcc_eh");
println!("cargo:rustc-link-lib=static-nobundle=pthread");

@vadimcn
Copy link
Contributor

vadimcn commented May 8, 2017

I'm not really sure if the -nodefaultlibs piece has really worked out over time. In practice everyone's compiling C and linking it, and we just need to work with that.

Well, it does work with pure-Rust software. The more complex projects usually do end up with C components, but this is by no means universal.

In some sense that's the whole point of the pc-windows-gnu toolchain, linking with C code...

As far as I'm concerned, the primary reason for pc-windows-gnu is to have a toolchain that does not depend on any 3-rd party software. See, for example, how pc-windows-msvc toolchain got borked by VS2017 changing its install directory structure.

I'm trying to imagine living in a world where we've eliminated/re-written all our GCC dependencies. Would we still want to be providing to the linker runtime dependencies for C components? What about other languages? (Say, people got into habit of linking together Rust and Go components).

Do as you recommended by updating gcc. I... this sounds hard.

Yes, I think this is what we should ultimately do.

It means that every crate compiled on MinGW will print out -lgcc_eh and then do a bunch of dynamic probing to maybe print out -lpthread as well.

Yes, messy. This sort of thing is the reason C software usually has configure scripts...

Every C crate at that point will then print out the runtime libs?

Not very tidy, but it would work, right?

This could be canonicalized in a shared dependency but in some sense that shared dep is std.

Possibly. But we need to make sure that these libs end up in the right spot on linker's command line. We want them after dependent C objects. AFAIK, right now such a dependency would get compiled before the dependent crates, and any cargo metadata it emits would precede the C objects, right?

Switch back to the "dylib" link kind for gcc_eh and pthread.

Maybe, though this would mean that even pure-Rust programs become dependent on libpthread1.dll.
A different compromise would be to keep panic_unwind as-is, but add -lgcc_eh -lpthread in link.rs around here (for -pc-windows-gnu only). This way only programs linking to C would have this dependency (Rust programs just wouldn't have any unresolved symbols left and so these libs would be dropped by the linker).

Mark symbols like __emutls_get_address exported from std-*.dll

Seems even worse from maintenance perspective than hardcoding dependencies in the gcc crate.

Change doctests to not link dynamically

There's probably other crates that are in the same boat.

Don't pass -nodefaultlibs on MinGW

Also possible, but that's just kicking bucket down the road. Relying on gcc to provide dependencies will make it harder later when we want to switch to direct invocation of ld and/or lld.

@alexcrichton
Copy link
Member

@vadimcn would you be willing to work on the changes to the gcc crate? I unfortunately probably don't have the time to do that depth of a change right now, and I'm afraid of leaking this regression in favor of an open bug.

@vadimcn
Copy link
Contributor

vadimcn commented May 12, 2017

Sure I'll take a look. I hope we can get away with hardcoding default libs per-target, or some such.

@steveklabnik steveklabnik added T-dev-tools Relevant to the dev-tools subteam, which will review and decide on the PR/issue. and removed T-tools labels May 18, 2017
@brson
Copy link
Contributor

brson commented May 25, 2017

Looks like this will hit 1.18.

@brson brson added the I-wrong label Jun 1, 2017
@brson brson added regression-from-stable-to-stable Performance or correctness regression from one stable version to another. and removed regression-from-stable-to-beta Performance or correctness regression from stable to beta. labels Jun 15, 2017
@brson
Copy link
Contributor

brson commented Jun 15, 2017

@vadimcn any updates?

@brson brson assigned vadimcn and unassigned alexcrichton Jun 15, 2017
@vadimcn
Copy link
Contributor

vadimcn commented Jun 15, 2017

AFAIR, we had a chat with @alexcrichton a little while back, and decided to let this be.
There had been only one report of such breakage and crates can fix it by providing the full set of their link-time dependencies instead of relying on rustc to add libraries for them.

@alexcrichton
Copy link
Member

@vadimcn did you want to open an issue for making the unwinder an isolated rlib (no external deps) and then tweaking our default inclusion of libraries?

@vadimcn
Copy link
Contributor

vadimcn commented Jun 16, 2017

@alexcrichton: I did some experiments and unfortunately it isn't as easy as it seemed at first sight. I am still thinking about it :).

@Mark-Simulacrum Mark-Simulacrum added C-bug Category: This is a bug. and removed I-wrong labels Jul 27, 2017
@mitsuhiko
Copy link
Contributor

I'm running into this with uchardet at the moment and the relevant flag (static-nobundle) requires nightly. Is there a chance to stabilize this feature or provide some other workaround?

@steveklabnik
Copy link
Member

Triage: given the discussion above, and that there hasn't been any other real comments on this issue (other than @mitsuhiko who seems to have fixed it), I'm going to give this a close. Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-linkage Area: linking into static, shared libraries and binaries C-bug Category: This is a bug. P-medium Medium priority regression-from-stable-to-stable Performance or correctness regression from one stable version to another. T-dev-tools Relevant to the dev-tools subteam, which will review and decide on the PR/issue. T-rustdoc Relevant to the rustdoc team, which will review and decide on the PR/issue.
Projects
None yet
Development

No branches or pull requests

7 participants