Nixpkgs: stdenv: principial linking problems when putting static and dynamic libraries into different directories

Created on 2 Jan 2016  路  9Comments  路  Source: NixOS/nixpkgs

I've recently been digging into link errors introduced by splitting outputs, and there's a general problem for which I don't see any easy solution (yet). It again stems from assumptions that stuff is in the same directory, in particular static and dynamic version of the same library.

When linking, ld checks directories specified by -L in order and prefers dynamic libs by default, but it does so in each folder separately, therefore when dynamic and static versions are separate, the preference is "given" by directory order.

The order isn't very easy to affect. For example gcc also passes ${stdenv.cc.cc.out}/lib by itself which currently contains some static libraries whose dynamic versions are split into a different output. Example: https://gist.github.com/vcunat/8e5d56eb4e5cf4a80944. I this case it wasn't possible to link against those libs, but I'm afraid there may be many hidden cases where static libraries were preferred unintentionally. Therefore I'd like to find a general solution instead of fixing up particular cases.

Any ideas? In the worst case we could patch ld to first search all dirs for dynamic version before trying static.

question mass-rebuild stale closure-size

Most helpful comment

2 random ideas i had

  • symlink the .so from ${static}/lib/ so you can put just the static output in -L and get both
  • buildEnv all of the inputs into a single path?

All 9 comments

Ok so if .a and .so are in the same directory it works. If they are in different directories it doesn't work.

However rather than only a simple assumption, it's also a good practical assumption. From an ld implementation view point, it would be a little hard to "merge" directories trying to find a proper order between .a and .so of the same library.

A possibility is the following, it's a little more disk expensive but might work: drv1 has only .so, drv2 has both .a and .so. That should solve the problem for dynamic, and well for static you have to fix a little the build process.

That would work, but it would link against paths that contain both *.a and *.so, which would defeat the purpose of splitting the outputs. Link scripts might be usable instead of symlinks; maybe that will be the easiest way in the end.

There's also libtool which explicitly requires both *.a and *.so be in the same directory, so it seems a good idea to approach it from that side.

So, linker scripts do allow to have a file containing INPUT(/path/to/something/to/link), but they don't solve this problem, unfortunately. When I do this with gcc, the linker leaves path to the _script_ in RPATH which fails on any run attempt (or ldd). Apparently this won't work for stuff found by -lfoo, only by adding files to be linked explicitly.

Now I'm thinking of patching ld to resolve symlinks, i.e. link against the canonized paths of libraries. Then that symlink approach should work. Also we could auto-symlink $dev/lib/* -> $lib/lib/* and thus avoid lots of errors, as not specifying the output would lead to extra retained runtime dependencies instead of errors.

Oh, the code in ld seems far messier than our nix's c++, for example. I'm giving up on that for now.

As long as people don't mess with default flags or search order, the dynamic ones come first in -L arguments (at least for gcc) and there's no problem. Even forcing static libs works, e.g. just by -static-libstdc++, because it rejects any dynamic libs while searching and finds static ones in further search paths.

(triage) Is this still an ongoing thing?

My last comment still holds AFAIK. It seems it doesn't get into our way as much as I assumed when first submitting the issue.

2 random ideas i had

  • symlink the .so from ${static}/lib/ so you can put just the static output in -L and get both
  • buildEnv all of the inputs into a single path?

Emscripten also only produces static archives, except its archives are meant to be .bc, naming them .a confuses things. Right now the current emscripten toolchain on nixpkgs puts its output as .a in the static directories. https://github.com/NixOS/nixpkgs/pull/16208

Thank you for your contributions.

This has been automatically marked as stale because it has had no activity for 180 days.

If this is still important to you, we ask that you leave a comment below. Your comment can be as simple as "still important to me". This lets people see that at least one person still cares about this. Someone will have to do this at most twice a year if there is no other activity.

Here are suggestions that might help resolve this more quickly:

  1. Search for maintainers and people that previously touched the related code and @ mention them in a comment.
  2. Ask on the NixOS Discourse.
  3. Ask on the #nixos channel on irc.freenode.net.
Was this page helpful?
0 / 5 - 0 ratings

Related issues

tomberek picture tomberek  路  3Comments

retrry picture retrry  路  3Comments

copumpkin picture copumpkin  路  3Comments

copumpkin picture copumpkin  路  3Comments

matthiasbeyer picture matthiasbeyer  路  3Comments