Skip to content

Windows: rustc should prefer bundled linker and libs. #18325

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

Closed
vadimcn opened this issue Oct 25, 2014 · 13 comments · Fixed by #18797
Closed

Windows: rustc should prefer bundled linker and libs. #18325

vadimcn opened this issue Oct 25, 2014 · 13 comments · Fixed by #18797
Labels
O-windows Operating system: Windows P-medium Medium priority
Milestone

Comments

@vadimcn
Copy link
Contributor

vadimcn commented Oct 25, 2014

Linking may fail when an incompatible installation of MinGW is on the PATH, because rustc ends up running external linker instead of the bundled one.

I keep seeing people running into this problem when using WIndows installer. The solution it to run rustc in a console with stripped-down PATH, but this workaround is very nonobvious. I am afraid this will negatively affect perception of quality of our Windows distribution because many early adopters will have some version of mingw already installed on their machines.

I think the earlier decision to make rustc prefer bundled binaries (#17412) was the correct one. We should un-revert 94f0532, and fix cargo build instead.

@vadimcn
Copy link
Contributor Author

vadimcn commented Oct 25, 2014

cc #17442, #17726, rust-lang/cargo#620

@vadimcn
Copy link
Contributor Author

vadimcn commented Oct 25, 2014

Regarding cargo, I think we can take one of the following approaches:

  • Use the snapshot compiler.
  • Specify linker path explicitly via -Clinker=....
  • Delete/rename rustlib/<triple>/gcc directory after installing.
  • Add a new command line flag to rustc for controlling this behavior. Perhaps something like -Cprefer-system-linker?

cc @brson, @alexcrichton

@alexcrichton
Copy link
Member

Issues like #17726 are definitely quite worrying, but I would see this as more than just a problem with Cargo but also extending to any project relying on libs installed on windows by some compiler toolchain. The bundled gcc doesn't know anything about system lookup paths, and I see this as akin to saying we should run gcc on unix with no default lookup paths (which would likely be disastrous).

I suspect that there are other projects which rely on libs coming from a MinGW, and this seems similar to relying on randomly installed libraries on unix systems, so I'm not sure if it's necessarily a bad thing.

Do we know why the error in #17726 is occurring? It looks like there's an incompatibility with the MinGW installation, but do we know precisely what it is? I was under the impression that linkers were intended to interoperate well...

@brson
Copy link
Contributor

brson commented Oct 27, 2014

I don't really want gcc to be able to find arbitrary mingw libraries because I don't want Rust users on Windows to depend on mingw (imagine cargo packages that expect mingw libs but only a fraction of windows users actually have it installed). I've misunderstood the implications of this issue before, but my inclination is to do the revert and make the cargo build do the extra work to get at the libs it needs.

@brson
Copy link
Contributor

brson commented Oct 27, 2014

Nominating since this issue gets hit pretty often and is the last major usability problem on windows.

@vadimcn
Copy link
Contributor Author

vadimcn commented Oct 27, 2014

The bundled gcc doesn't know anything about system lookup paths, and I see this as akin to saying we should run gcc on unix with no default lookup paths (which would likely be disastrous).

Not quite: mingw gcc has a default library search path built-it, and it is expressed relative to the gcc.exe installation point. So the one we bundle is going to look for libraries only under rustlib\x86_64-w64-mingw32\gcc\lib (unless we supply more via -L, of course).

Do we know why the error in #17726 is occurring? It looks like there's an incompatibility with the MinGW installation, but do we know precisely what it is? I was under the impression that linkers were intended to interoperate well...

This is mostly about library compatibility, not about linker. GCC may emit references to library symbols, that may not exist/be buggy in older versions of mingw.
This particular one probably happened because the developer had installed mingw with sjlj exception handling, which defines _Unwind_SjLj_Resume instead of _Unwind_Resume.

@pnkfelix
Copy link
Member

pnkfelix commented Nov 6, 2014

Assigning P-high, 1.0.

@pnkfelix pnkfelix added P-medium Medium priority and removed I-nominated labels Nov 6, 2014
@pnkfelix pnkfelix added this to the 1.0 milestone Nov 6, 2014
@brson
Copy link
Contributor

brson commented Nov 6, 2014

@vadimcn Not being able to access the full set of mingw libs means that people can't link to random GNU libs (which I'm in favor of). I'm unclear on whether it also prevents people from linking to various windows system libraries (I have this vague idea that mingw includes artifacts that make the linker able to link to e.g. gdi32.dll). Is there any concern there?

@klutzy
Copy link
Contributor

klutzy commented Nov 7, 2014

gcc needs lib###.a to recognize system library (###.dll), so make-win-dist.py picks up some of them.
We ship libkernel32.a, but we don't ship libold32.a or libgdi32.a so #17442, rust-lang/cargo#620, and #18617 occurs.

So, what's the role of bundle? I thought bundle is for providing "minimal" linking environment so that beginners can build hello-world without installing mingw-w64. In this scenario, if user want to do more than bundle can provide (e.g. gdi32), user must install mingw-w64. At least, this is current status.

Maybe we can bundle more system libs? x86_64-4.9.1-win32-seh-rt_v3-rev1/mingw64/x86_64-w64-mingw32/lib is 72M.

@klutzy
Copy link
Contributor

klutzy commented Nov 7, 2014

Preferring bundle means:

  1. Even if user has old mingw, rustc will not use it. This solves lots of of beginners' issues.
  2. However, if user really wants to use their own linker, user need to do something. This complicates build story.

So my suggestion is 1) prefer bundle and 2) add a flag to not use bundle at all (rather than changing preference). Maybe -C no-bundle or -C use-system-linker?

@vadimcn
Copy link
Contributor Author

vadimcn commented Nov 7, 2014

@klutzy: on the other hand, there are a few libs that need to be matched to the version of gcc that Rust was built with. It's mostly stuff like crt2.o and libgcc.a; possibly also libmingw32.a,libmingwex.a. So simply deferring to external linker probably isn't a good idea, unless we ensure that our bundled libs are being found first.

@brson: I kinda like the idea of shipping the minimal set of import libraries that is sufficient for linking Rust's standard library. We could add a few more common ones like gdi32, but everything is a bit much, IMHO.
For reference, here's the list of import libraries that D ships with: ctl3d32.lib, odbc32.lib, ws2_32.lib, oleaut32.lib, comctl32.lib, advapi32.lib,gdi32.lib, shell32.lib,rpc4.lib, wsock32.lib, winmm.lib, comdlg32.lib, ole32.lib, uuid.lib, winspool.lib, user32.lib, kernel32.lib.

Btw, mingw ld can also link to dlls directly, so in many cases adding -L %systemroot%\system32 to the command line is enough.

@blairn
Copy link

blairn commented Nov 10, 2014

ld can also link to dlls directly?
Is it possible to #link directly in them in source?
#[link(path = "%systemroot%\system32\gdi32.dll")] or something like that?

@brson
Copy link
Contributor

brson commented Nov 10, 2014

@vadimcn That D ships a set of system import libraries is encouraging. Though if mingw can link to dlls directly it's not clear why this is such a problem - if we were to just have rustc add the system32 path by default would this problem with windows import libraries go away completely?

bors added a commit that referenced this issue Nov 11, 2014
Based on Windows bundle feedback we got to date, 
- We *do* want to prefer the bundled linker: The external one might be for the wrong architecture (e.g. 32 bit vs 64 bit).  On the other hand, binutils don't add many new features these days, so using an older bundled linker is not likely to be a problem.
- We *do* want to prefer bundled libraries: The external ones might not have the symbols we expect (e.g. what's needed for DWARF exceptions vs SjLj).  Since `-L rustlib/<triple>/lib` appears first on the linker command line, it's a good place to keep our platform libs that we want to be found first.

Closes #18325, closes #17726.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
O-windows Operating system: Windows P-medium Medium priority
Projects
None yet
Development

Successfully merging a pull request may close this issue.

6 participants