TL; DR
A solução de trabalho está usando patchelf (se você tiver que lidar com versões glibc não correspondentes: no sistema host e com as bibliotecas nix vinculadas), veja a segunda metade da minha história.
Tentando a abordagem usual
Tentando usar o LD_LIBRARY_PATH
Bem, eu configurei uma variável de ambiente para isso em ~/.bash_profile :
NIX_LINK=/home/ivan/.nix-profile
export LD_LIBRARY_PATH="$NIX_LINK"/lib
mas isso não é tudo!
Agora existem problemas com links para versões diferentes de libc :
$ ldd -r ../valencies
../valencies: /lib64/libc.so.6: version 'GLIBC_2.15' not found (required by ../valencies)
../valencies: /lib64/libc.so.6: version 'GLIBC_2.14' not found (required by ../valencies)
../valencies: /lib64/libc.so.6: version 'GLIBC_2.14' not found (required by /home/ivan/.nix-profile/lib/libgmp.so.10)
linux-vdso.so.1 => (0x00007fff365ff000)
/usr/local/lib/libsnoopy.so (0x00007f56c72e6000)
libgmp.so.10 => /home/ivan/.nix-profile/lib/libgmp.so.10 (0x00007f56c7063000)
libffi.so.5 => /usr/lib64/libffi.so.5 (0x00007f56c6e54000)
libm.so.6 => /lib64/libm.so.6 (0x00007f56c6bd0000)
librt.so.1 => /lib64/librt.so.1 (0x00007f56c69c7000)
libdl.so.2 => /lib64/libdl.so.2 (0x00007f56c67c3000)
libpthread.so.0 => /lib64/libpthread.so.0 (0x00007f56c65a6000)
libc.so.6 => /lib64/libc.so.6 (0x00007f56c6211000)
/lib64/ld-linux-x86-64.so.2 (0x00007f56c74f1000)
symbol memcpy, version GLIBC_2.14 not defined in file libc.so.6 with link time reference (/home/ivan/.nix-profile/lib/libgmp.so.10)
symbol memcpy, version GLIBC_2.14 not defined in file libc.so.6 with link time reference (../valencies)
symbol __fdelt_chk, version GLIBC_2.15 not defined in file libc.so.6 with link time reference (../valencies)
$
Classificando duas versões do glibc
O erro mais surpreendente aqui é:
symbol memcpy, version GLIBC_2.14 not defined in file libc.so.6 with link time reference (/home/ivan/.nix-profile/lib/libgmp.so.10)
porque nix deve ter instalado a versão de glibc que é usada por seu libgmp !
E, de fato, o glibc de nix está lá:
$ ldd -r /home/ivan/.nix-profile/lib/libgmp.so.10
linux-vdso.so.1 => (0x00007fff0f1ff000)
/usr/local/lib/libsnoopy.so (0x00007f06e9919000)
libc.so.6 => /nix/store/93zfs0zzndi7pkjkjxawlafdj8m90kg5-glibc-2.20/lib/libc.so.6 (0x00007f06e957c000)
libdl.so.2 => /lib64/libdl.so.2 (0x00007f06e9371000)
/lib64/ld-linux-x86-64.so.2 (0x00007f06e9da7000)
symbol _dl_find_dso_for_object, version GLIBC_PRIVATE not defined in file ld-linux-x86-64.so.2 with link time reference (/nix/store/93zfs0zzndi7pkjkjxawlafdj8m90kg5-glibc-2.20/lib/libc.so.6)
/home/ivan/.nix-profile/lib/libgmp.so.10: error while loading shared libraries: __vdso_time: invalid mode for dlopen(): Invalid argument
$
Provavelmente, glibc não estava disponível para o usuário, portanto, quando executei meu binário, o glibc do sistema foi carregado primeiro. Prova:
$ ls ~/.nix-profile/lib/*libc*
ls: cannot access /home/ivan/.nix-profile/lib/*libc*: No such file or directory
$
Ok, podemos tentar tornar glibc visível para o usuário também:
$ nix-env -i glibc
Então tudo está mal:
$ ldd -r ../valencies
/bin/bash: error while loading shared libraries: __vdso_time: invalid mode for dlopen(): Invalid argument
$ /bin/echo ok
/bin/echo: error while loading shared libraries: __vdso_time: invalid mode for dlopen(): Invalid argument
$
Portanto, parece não ser uma tarefa fácil se você quiser carregar bibliotecas de nix ao executar seus próprios binários ...
Por enquanto, estou comentando
export LD_LIBRARY_PATH="$NIX_LINK"/lib
e fazendo na sessão de shell:
$ unset LD_LIBRARY_PATH
$ export LD_LIBRARY_PATH
Precisa pensar mais. (Leia sobre __vdso_time: modo inválido para dlopen () : espera-se que outro glibc in LD_LIBRARY_PATH falhe, porque o seu ld-linux-x86-64.so.2 não corresponderá ao seu libc.so.6 . Ter várias versões do glibc em um único sistema é possível, mas um pouco complicado, conforme explicado nesta resposta.
A solução necessária: patchelf
Assim, o caminho para o vinculador dinâmico é codificado no binário. E o linker dinâmico usado é do sistema (do host glibc), não do nix. E como o vinculador dinâmico não corresponde ao glibc que queremos e precisamos usar, ele não funciona.
Uma solução simples e funcional é fixada .
patchelf --set-interpreter /home/ivan/.nix-profile/lib/ld-linux-x86-64.so.2 ../valencies
Depois disso, funciona. Você ainda precisa mexer com LD_LIBRARY_PATH .
$ LD_LIBRARY_PATH=/home/ivan/.nix-profile/lib:/lib64/:/usr/lib64/ ../valencies
Se - como no meu caso imperfeito - algumas das bibliotecas são retiradas do nix, mas algumas são tiradas do sistema host (porque eu não as instalei com nix-env -i ), você tem que especifique o caminho para as bibliotecas nix e para as bibliotecas do sistema host em LD_LIBRARY_PATH (substitui completamente o caminho de pesquisa padrão).
etapa adicional: patchelf para o caminho de pesquisa da biblioteca
(da página patchelf )
Da mesma forma, você pode alterar o RPATH , o caminho de pesquisa do vinculador incorporado em bibliotecas executáveis e dinâmicas:
patchelf --set-rpath /opt/my-libs/lib:/foo/lib program
Isso faz com que o vinculador dinâmico pesquise /opt/my-libs/lib e /foo/lib nas bibliotecas compartilhadas necessárias ao programa. É claro que você também pode definir a variável de ambiente LD_LIBRARY_PATH , mas isso geralmente é inconveniente, pois exige um script de wrapper para configurar o ambiente.