Also, I added three branches to the original project in question:
demo/failing-example
demo/working-counter-example
demo/full-working
You can see that when using gold linker in the executable only, things work correctly - demo/working-counter-example.
I'm not sure this is intentional, and I thought it's connected to the **actual bug I found, which is when you try to compile a project that has a dependency that uses gold linker, the aforementioned error occurs** - you can reproduce that with the project I added - https://github.com/ksaric/bronze-linker-client.
I hope this is clearer, and yes, I'm confused as well, this is kind of strange.
So here's my understanding when bug happens on GHC 8.0.2:
If library A is linked with gold and library B depends on A, no matter if B is specified to be linked with gold or not, B fails to detect that it should use the gold linker.
Right. And if you try to explicitly add gold linker flags to library B, it doesn't help, since GHC thinks (heh, I wish) that it doesn't need to use gold linker for project A, even if the project A has defined gold linker explicitly.
I'm looking at the example described in the ticket summary:
The issue here is that the library component was registered with (quoting ghc-pkg dump),
ld-options: -fuse-ld=gold
Consequently, when we go to link the executable GHC will add this flag to its usual link flags, the latter of which assume that we are using BFD ld.
Frankly, I don't see any better way to handle this beyond just teaching GHC to use ld when possible. I'm working on this (see #13541 (closed)) but unfortunately it isn't likely that this will make the already-terribly-late 8.2.1. We may be able to work it in to 8.2.2 if we hear very vocal support from users, however.
Consequently, when we go to link the executable GHC will add this flag to its usual link flags, the latter of which assume that we are using BFD ld.
I don't quite understand this. Isn't the key problem here that the concept of the "ld program" and the "ld-options" are unhealthily mixed up?
It seems to me that if one could explicitly distinguish "I want this linker" and "I want these ld-flags", the problem wouldn't exist, because then the choice of linker would not be propagated through ld-options.
In other words, isn't the problem here that we're linking through the compiler (e.g. gcc) instead of the actual linker binary? Because otherwise we'd not even be using the -fuse-ld flag.
(Another workaround might be to make ghc ignore the -fuse-ld flag as a flag that can traverse ld-options through build-depends, but that option seems more hacky than linking directly with a linker executable, if that is possible.)
I don't quite understand this. Isn't the key problem here that the concept of the "ld program" and the "ld-options" are unhealthily mixed up?
In other words, isn't the problem here that we're linking through the compiler (e.g. gcc) instead of the actual linker binary? Because otherwise we'd not even be using the -fuse-ld flag.
I've played around with the idea of involing ld ourselves and have concluded that it's almost certainly going to hurt more than it helps. Linking tends to be terribly platform specific and rather difficult to get right (see also: gcc -dumpspecs). Moreover, linkers on many platforms tend to be, shall we say, quirky. I don't see us being able to robustly implement the logic necessary to drive the linker as well as gcc.
Keep in mind that GHC is not only responsible for linking Haskell; we are often asked to link against native code, some of which may require peculiar linking behavior (e.g. one of those many rules seen in gcc -dumpspecs). This isn't to say that gcc's abstraction over linking is quite perfect; far from it. However, it's IMHO much better than having to dive into the muck ourselves.
Moreover, I don't think thinking ourselves would necessarily help the crux of this problem: the user essentially gave us conflicting linking options. Really, the user shouldn't have to give us *any* linker options in this case; ghc should just handle linker choice for you.