-
Notifications
You must be signed in to change notification settings - Fork 12.7k
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
Prioritize target libs when there's multiple candidates #14650
Conversation
When multiple candidates for a library are found, if one (and only one) candidate lives in the target library path, prioritize that one. This allows `rustc -L /usr/local/lib lib.rs` to compile successfully, whereas today it complains about multiple candidates for e.g. libstd. Fixes rust-lang#13733, rust-lang#11195.
Would this also fix #13421? I'll test it. |
@japaric Probably. I'm assuming setting the LLVM root like that is adding |
A fact of bootstrapping is that the host libs have a chance of being different than the target libs, and the compiler is presenting to you a legitimate warning, as I stated in my earlier comment. I agree that this is a problem that needs to be fixed, but I do not believe this is the right way to do it. The solution I am thinking of is to change our distribution strategy to not use the stage2 host libs at all, but rather only install the stage2 target libs. |
@alexcrichton If we don't install the host libs, how do people compile syntax extensions? |
@alexcrichton The legitimate warning assumes both libraries are valid candidates. This PR here makes the assumption that if a given library is found in the target lib path, then it's the correct one to use and any alternative matching candidates can be ignored. This assumes, of course, that the target lib path is only searched when building target libraries, which seems like a safe assumption (if I'm building a syntax extension dylib, I would not expect the target lib path to be searched, because I only want to link against host libs). |
Just to be clear, I'll explain how I see this situation. The names "host lib" and "target lib" are misnomers here because this issue doesn't stem from cross compiling or host/targets at all. This issue is purely a staging problem. The stage1 compiler, In terms of a system installation, we install the stage1 artifacts to What I was saying is that we stop distributing the stage1 entirely. The stage2 artifacts are the only ones distributed, and they are all placed into You'll also note that this means that the stage2 artifacts, the stage3 compiler, will be linking to code that they didn't generate (an important property we had beforehand). Due to our need for syntax extensions, this is something that we already need to guarantee for the compiler to work properly, I believe. Now that we've got that out of the way, I will address your questions.
I think when you say host libs you are referring to the stage1 artifacts. Being able to compile syntax extensions doesn't really have anything to do with being able to find stage1 or stage2 artifacts. By not distributing stage1 artifacts, you will compile a syntax extension against the stage2 artifacts which are the exact libraries that stage2 artifact compiler is running with, so there is no problem here.
Yes, but assumptions always turn out to be wrong at some point. What you're trying to "fix" is something that I do not view as a problem to fix, but rather a fact of life with our current distribution and architecture. The compiler should need no changes to be able to pass
Can you rephrase this statement in terms of what I said above? There is no difference in host/target architecture, and the compiler today never links against the stage1 artifacts. |
FWIW, this didn't fix #13421. I made sure to remove my previous install, and then build and install rust with this patch applied, but when I tried to compile the patched rust (with the patched |
@alexcrichton I was under the impression that the I take it that when cross-compiling right now you end up with stage1 artifacts in Given your explanation, it does seem that the correct thing to do is to stop distributing the stage1 artifacts. Why do we do that right now? Also, is the stage2 rustc actually built from the stage2 libraries, or is the stage2 rustc used to build the stage2 libraries? I thought it was the latter, because I thought the stage0 rustc was the snapshot, which was then used to build the stage0 libraries, which build the stage1 rustc, etc. Incidentally, I'm not thrilled by the idea of putting all the stage2 artifacts in |
@japaric Can you run the final |
Yes.
I explained above as well, but it's to rely on the invariant that a compiler will never link code with a library that it did not itself generate. (more on this above) Note that if we don't install the stage1 artifacts, we are breaking this invariant, and I believe this to be ok.
I'd be careful on naming here, as I'm not precisely sure what you mean by "stage2 rustc". I'll try to explain though. I refer to the file With that in mind, the stage2 compiler is not built from the stage2 artifacts, but rather the stage1 artifacts. We currently install the stage2 compiler as
morestack/compiler-rt are a good point, and this alternative would involve installing nothing to This will be tricky, however, with dynamic linking. When the |
I think I misunderstood. I thought you were talking about how syntax extensions loaded into rustc need to be linking against the same libraries rustc itself links against, but now I realize you are talking about executables/libraries produced by rustc linking against other libraries that were produced by the same rustc. Maintaining that invariant would require installing both "target" and "host" libraries even when target == host. But even with that, preserving this invariant for syntax extensions is only possible if rustc itself links against libraries that it produced, which a) seems like a bad idea, and b) actually breaks the invariant for the previous stage. Which is to say, this invariant can't possibly hold everywhere.
I agree.
Ok, that's what I thought, but I wasn't entirely certain. What is stage3 used for? I have a full stage3 tree in my build dir, but there are no files in it.
Why? Can't we just adjust the path to point to the correct rustlib dir? I don't know how it works on other OS's, but on OS X it appears If other OS's use different approaches, surely there's a way to deal with that (for example, to rewrite[1] the paths that rustc uses when copying rustc from the stage2 artifacts into its build location). [1] OS X provides a tool |
@alexcrichton Incidentally, if we swap those two On that note, something to consider is making rustc explicitly take the first crate it finds, instead of special-casing the target lib dir. It would have to search the target lib dir first (right now it searches additional paths before the target lib dir, although I don't know why), but that shouldn't be a problem. |
Snapshots are stage3 compilers. I think that's the only use case of stage3
Interesting! Your findings surprise me, but I suppose I should have also seen that coming. I'll digress for a second to talk about rpaths: The rpath values are passed to the system linker via the So, with that in mind, what you discovered was first the relative path, then the absolute path (as expected). Note though that this absolute path is the absolute path with the If we were to not install libs into
The |
Why would you install to a different location than your Or are you talking right now about compiling third-party libraries and executables that depend on those libraries? If so, I take it you're saying that the prefix Of course, if we remove the I don't believe we need to modify the rpath in libraries with this approach.
Doesn't that mean we can basically just ignore windows? We just install the stage2 artifacts there instead of the stage1 artifacts. Although how do third-party executables find the rust libraries? Do they also have to be installed into
Two libraries with the same crate ID but different hashes in the same directory seems like a legitimate error. Two libraries with the same crate ID in two different directories (regardless of hash) is not necessarily an error. If I just installed a new version of libstd with a different ABI, it would presumably have a different hash, and live in the same directory as my old libstd. rustc can then report an error when I try and use it. But the only reason why this might cause a problem when considering different directories is precisely when making the switch to no longer installing stage1 artifacts, if the user passes |
The nightly installer is configured with some We cannot swap the order because then rust itself could not be built if rust is installed.
Not if we can find a solution for both worlds.
Can you define what you mean by "third-party executable"?
Neither do I, what I meant was that our distribution and organization strategy of libraries does affect windows.
This paragraph doesn't make sense to me, sorry. I'm assuming that we should remove stage1 artifacts, in which case the associated bug is fixed and this PR is not necessary. |
Huh, ok.
I see. Well, if we stop installing stage1 artifacts, then it doesn't really matter, except we'll need to teach the Makefile and nightly installer script to delete the old installed artifacts (as they won't be overwritten with new ones).
I didn't mean don't make this work on Windows, I mean, that it sounds like Windows isn't really affected by this change.
Executables built by users of rust, as opposed to the executables built when building rust itself (e.g.
It sounds to me like Windows does not have an issue that's equivalent to the
If we remove the stage1 artifacts, then the precise issue that prompted this PR is fixed, and yes, I suppose we can close the PR. But it's entirely possible for this issue to crop up again in the future with third-party libraries, just not I guess with the Rust standard libraries (e.g. with multiple |
If the libraries that are located have the exact same SVH, the compiler can safely choose either one because they should both have the same ABI in that case (if they were exactly duplicates). Ok, in that case, I'm going to close this for now, and open an issue about our distribution tactics. |
When multiple candidates for a library are found, if one (and only one)
candidate lives in the target library path, prioritize that one. This
allows
rustc -L /usr/local/lib lib.rs
to compile successfully, whereastoday it complains about multiple candidates for e.g. libstd.
Fixes #13733, #11195.