-
Notifications
You must be signed in to change notification settings - Fork 697
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
Add extraLibDirs to runtime lib search paths of library #9554
Conversation
Yes!! |
8c266de
to
318b8e1
Compare
Fixes #7339 |
Should this change also be backported @Kleidukos ? Would require re-applying the change to |
@alt-romes ok, can I let you drive the backport? it's |
I'd need some instructions to do so, I haven't worked with |
fe6c577
to
f9ff63c
Compare
@alt-romes: You create a github comment, here, saying "@mergify backport 3.10". That's it. You can do it right now. |
@mergify backport 3.10 |
✅ Backports have been created
|
I'd be great if you could review this @andreabedini @gbaz |
I defer to my linking expert @angerman 😂 Edit: Reading #7339 it seems that @angerman and @bgamari where agreeing that the rpath logic should be left to GHC? From Ben's comment.
|
@andreabedini Yes and no. The rpath logic is not left to GHC, and even if an -rpath flag were to be added, it wouldn't be clear whether extra paths added through it should be handled via the macOS length limit workaround. In fact, I implemented the suggested -rpath flag, but it wasn't finished because it is unclear what semantics it should have. I've also posted a comment to @angerman's original MR which attempted something slightly orthogonal to this (#7094 (comment)), to explain how it relates to this one. Replying to what you quoted:
Indeed, Cabal already specifies runtime search paths and compile-time library paths to GHC, with information only cabal is aware of. This path extends the runtime search paths Cabal passes to GHC to include the extra-lib-dirs field which specifies paths where libraries will be found at runtime (the field itself unfortunately conflates compile time and load time paths).
It turns out that the Darwin workaround will only include in the RPATH entries of a dynlib the paths where libraries are found at runtime, in order to not include RPATHs to libraries which are never used by the library. However, sometimes, we really do want to specify the path to a directory where a library can be found at runtime, even if no library is found there at compile time. So, even if there were an -rpath flag, it is unclear if such a flag should go through Darwin's special rpath logic, or bypass it completely (again see !11801). |
Runtime search paths are hard. Here's the current picture to understand why this patch exists: * When linking a shared library, GHC will include in the rpath entries of the shared library all the paths listed in the library dirs section of the installed package info of all packages the shared library depends on. * On darwin, GHC has special logic to inject the library dirs listed in the installed dependent packages info into the rpath section instead of passing the dirs as -rpath flags to the linker. However, only the dirs where used libraries are found are actually injected. The others are ignored. This works around limitations of the darwin loader. * Cabal, in addition, passes directly to the linker (via -optl-Wl,-rpath,...) the library dirs of packages the shared library for the package being built depends on. * In a vanilla cabal installation, this will typically only be the path to the cabal store and the path to the installed GHC's boot libraries store. * When using nix there will a different library dir per installed package. Since these lib dirs are passed directly to the linker as rpaths, we bypass the darwin loader logic and, for very big packages, on darwin, we could end up reaching the load command limit and fail linking. We don't address this situation in this MR. When we specify `extra-lib-dirs` in Cabal, these extra-lib-dirs will be added to the library dirs listed in the installed package info of the library they were specified for. Furthermore, when building a shared library, extra-lib-dirs will be passed as `-L` flags to the linker invocation. However, the same extra-lib-dirs will not be passed as `-rpath` to the linker. The end situation is as follows: 1. The shared library `libA` built for a package `A` will be linked against some libraries `libExtra` found in extra-lib-dirs `extraA`. 2. The RPATH section of `A` will NOT contain `extraA`, because we don't pass -rpath extra-lib-dirs when linking the library, but it will depend on `libExtra`. 3. The installed package info of that package `A` will contain, in the library dirs section, the extra-lib-dirs `extraA` and the path to `libA`. 4. When a package `B` depends on package `A`, it will include in the RPATH section of the shared library `libB` the lib dirs from the installed package info of `A`, i.e. `/path/to/libA` and `extraA`, and depends on `libA` and, transitively, on `libExtra`. The conclusion is: 5. When we load `libB`, we will load `libA`, which is found in `/path/to/libA`, and, transitively, load `libExtra` which is found in `extraA` -- they are both found because both `/path/to/libA` and `extraA` are listed in the RPATH entries. 6. However, if we load `libA` directly we will /NOT/ find `libExtra`, because `extraA` is not included in the RPATH entries. So, ultimately, what this commit fixes, is the failure described in (6), caused by the incorrect behaviour of (2), by specifying `-rpath extra-lib-dirs` when linking the shared library of a package, to include the extra lib dirs in the RPATH entries of that shared library (even though dependents of this library would already get the extra-lib-dirs in their RPATH, the library itself didn't, resulting in cabal#7339 and ghc#19350) Fixes haskell#7339 Fixes ghc#19350
f9ff63c
to
addbcbf
Compare
@alt-romes Thank you for your very detailed reply! |
Add extraLibDirs to runtime lib search paths of library (backport #9554)
Runtime search paths are hard. Here's the current picture to understand why this patch exists:
When linking a shared library, GHC will include in the rpath entries of the shared library all the paths listed in the library dirs section of the installed package info of all packages the shared library depends on. * On darwin, GHC has special logic to inject the library dirs listed in the installed dependent packages info into the rpath section instead of passing the dirs as -rpath flags to the linker. However, only the dirs where used libraries are found are actually injected. The others are ignored. This works around limitations of the darwin loader.
Cabal, in addition, passes directly to the linker (via -optl-Wl,-rpath,...) the library dirs of packages the shared library for the package being built depends on. * In a vanilla cabal installation, this will typically only be the path to the cabal store and the path to the installed GHC's boot libraries store. * When using nix there will a different library dir per installed package. Since these lib dirs are passed directly to the linker as rpaths, we bypass the darwin loader logic and, for very big packages, on darwin, we could end up reaching the load command limit and fail linking. We don't address this situation in this MR.
When we specify
extra-lib-dirs
in Cabal, these extra-lib-dirs will be added to the library dirs listed in the installed package info of the library they were specified for. Furthermore, when building a shared library, extra-lib-dirs will be passed as-L
flags to the linker invocation. However, the same extra-lib-dirs will not be passed as-rpath
to the linker.The end situation is as follows:
The conclusion is:
So, ultimately, what this commit fixes, is the failure described in (6), caused by the incorrect behaviour of (2), by specifying
-rpath extra-lib-dirs
when linking the shared library of a package, to include the extra lib dirs in the RPATH entries of that shared library (even though dependents of this library would already get the extra-lib-dirs in their RPATH, the library itself didn't, resulting in cabal#7339 and ghc#19350)Fixes #7339
Fixes ghc#19350