Estou usando o nix
"modo de usuário único" em um sistema em que não sou o root (veja abaixo uma descrição da minha configuração do nix).
Eu queria executar rapidamente um dos meus binários que está dinamicamente vinculado a uma biblioteca que está ausente no sistema.
Então, eu instalei a biblioteca com nix
:
$ nix-env -qa 'gmp'
gmp-4.3.2
gmp-5.1.3
$ nix-env -i gmp-5.1.3
Mas a biblioteca ainda não foi encontrada pelo vinculador:
$ 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)
linux-vdso.so.1 => (0x00007fffbbf28000)
/usr/local/lib/libsnoopy.so (0x00007f4dcfbdc000)
libgmp.so.10 => not found
libffi.so.5 => /usr/lib64/libffi.so.5 (0x00007f4dcf9cc000)
libm.so.6 => /lib64/libm.so.6 (0x00007f4dcf748000)
librt.so.1 => /lib64/librt.so.1 (0x00007f4dcf540000)
libdl.so.2 => /lib64/libdl.so.2 (0x00007f4dcf33c000)
libpthread.so.0 => /lib64/libpthread.so.0 (0x00007f4dcf11f000)
libc.so.6 => /lib64/libc.so.6 (0x00007f4dced8b000)
/lib64/ld-linux-x86-64.so.2 (0x00007f4dcfde7000)
undefined symbol: __gmpz_gcd (../valencies)
undefined symbol: __gmpn_cmp (../valencies)
undefined symbol: __gmpz_mul (../valencies)
undefined symbol: __gmpz_fdiv_r (../valencies)
undefined symbol: __gmpz_fdiv_q_2exp (../valencies)
undefined symbol: __gmpz_com (../valencies)
undefined symbol: __gmpn_gcd_1 (../valencies)
undefined symbol: __gmpz_sub (../valencies)
symbol memcpy, version GLIBC_2.14 not defined in file libc.so.6 with link time reference (../valencies)
undefined symbol: __gmpz_fdiv_q (../valencies)
undefined symbol: __gmpz_fdiv_qr (../valencies)
undefined symbol: __gmpz_add (../valencies)
undefined symbol: __gmpz_init (../valencies)
undefined symbol: __gmpz_ior (../valencies)
undefined symbol: __gmpz_mul_2exp (../valencies)
undefined symbol: __gmpz_xor (../valencies)
undefined symbol: __gmpz_and (../valencies)
symbol __fdelt_chk, version GLIBC_2.15 not defined in file libc.so.6 with link time reference (../valencies)
undefined symbol: __gmpz_tdiv_qr (../valencies)
undefined symbol: __gmp_set_memory_functions (../valencies)
undefined symbol: __gmpz_tdiv_q (../valencies)
undefined symbol: __gmpz_divexact (../valencies)
undefined symbol: __gmpz_tdiv_r (../valencies)
$
Olha, ele está presente no sistema de arquivos:
$ find / -name 'libgmp.so.10' 2>/dev/null
/nix/store/mnmzq0qbrvw6dv1k2vj3cwz9ffdh05zr-user-environment/lib/libgmp.so.10
/nix/store/fnww2w81hv5v3dl9gsb7p4llb7z7krzd-gmp-5.1.3/lib/libgmp.so.10
$
O que faço para que as bibliotecas instaladas por nix
sejam "visíveis"?
Provavelmente, o script de instalação padrão do usuário nix
modifica .bash_profile
para adicionar o bin/
arquivo PATH
, mas não faz algo análogo às bibliotecas.
Minha configuração nix:
A única coisa que pedi para o root fazer por mim foi: mkdir -m 0755 /nix && chown ivan /nix
caso contrário, segui o procedimento de instalação simples padrão do nix. Então agora eu posso usar programas personalizados dos pacotes nix. Eu não poderia fazer isso muito bem sem nenhuma ajuda da raiz, ou seja, sem /nix/
, porque /nix/
não estava disponível para mim; É claro que eu poderia usar outro diretório, mas os pacotes binários pré-criados não seriam válidos e todos os pacotes teriam que ser reconstruídos, de acordo com a documentação do nix. No meu caso, era mais simples pedir /nix/
por mim.
Outra coisa que fiz foi adicionar a ~/.bash_profile
:
export NIX_CONF_DIR=/nix/etc/nix
para que eu possa editar nix.conf
. (Era para ser controlado pela raiz, /etc/
caso contrário. Fiz isso porque queria build-max-jobs
e build-cores
configurações nele.)
fonte
nix-env
, para não mencionarnix.conf
. Que SO é esse? Além disso, o que você repetiu referências paranix
significar? Eu só ouvi isso como abreviaçãoUnix
, mas parece que você está usando em um contexto mais específico.nix
é um gerenciador de pacotes moderno e o nixOS é uma distribuição, e o Hydra é um sistema para reconstruir constantemente pacotes nix, e o nixOps é uma ferramenta para gerenciar declaradamente uma infraestrutura (uma rede de vários hosts) e o disNix para gerenciar declarativamente um conjunto de serviços (em cima de uma infraestrutura).guix
é umnix
guix
.Respostas:
TL; DR
A solução de trabalho está sendo usada
patchelf
(se você tiver que lidar com versões glibc não correspondentes: no sistema host e nas quais uma nix libs foi vinculada), consulte a segunda metade da minha história.Tentando a abordagem usual
Tentando usar LD_LIBRARY_PATH
Bem, eu configurei uma variável de ambiente para isso em
~/.bash_profile
:Mas isso não é tudo!
Agora, há problemas ao vincular com diferentes versões do
libc
:Classificando 2 versões do glibc
O erro mais surpreendente aqui é:
porque
nix
deve ter instalado a versãoglibc
usada pelo seulibgmp
!E, de fato, o
glibc
denix
lá está:Provavelmente,
glibc
não estava disponível para o usuário; portanto, quando executei meu binário, o sistemaglibc
foi carregado primeiro. Prova:Ok, também podemos tentar tornar
glibc
visível o usuário:Então tudo está ruim:
Portanto, parece não ser uma tarefa fácil se você deseja carregar bibliotecas a partir da
nix
execução de seus próprios binários ...Por enquanto, estou comentando
e fazendo na sessão shell:
Precisa pensar mais. (Leia sobre __vdso_time: modo inválido para dlopen () : espera-se que outro
glibc
participeLD_LIBRARY_PATH
falhe, porque o seuld-linux-x86-64.so.2
não corresponderá ao seulibc.so.6
. É possível ter várias versões do glibc em um único sistema, mas um pouco complicado, conforme explicado nesta resposta.)A solução necessária: patchelf
Portanto, o caminho para o vinculador dinâmico é codificado no binário. E o vinculador dinâmico que está sendo 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 é remendar .
Depois disso, funciona. Você ainda precisa mexer com isso
LD_LIBRARY_PATH
.Se - como no meu caso imperfeito - algumas das bibliotecas são retiradas do nix, mas algumas são retiradas do sistema host (porque ainda não as instalei
nix-env -i
), você deve especificar o caminho para as bibliotecas do nix, e para as libs do seu sistema hostLD_LIBRARY_PATH
(substitui completamente o caminho de pesquisa padrão).etapa adicional: corrigir o caminho de pesquisa da biblioteca
(a partir da
patchelf
página)Da mesma forma, você pode alterar o
RPATH
caminho de pesquisa do vinculador incorporado aos executáveis e bibliotecas dinâmicas:Isso faz com que o vinculador dinâmico de pesquisa em
/opt/my-libs/lib
e/foo/lib
para as bibliotecas compartilhadas necessárias para programa. Obviamente, você também pode definir a variável de ambienteLD_LIBRARY_PATH
, mas isso costuma ser inconveniente, pois requer um script de wrapper para configurar o ambiente.fonte
Além do "modo de usuário único" do Nix, eu forneço uma resposta para os usuários do NixOS . Você geralmente não pode executar arquivos binários no NixOS.
Se você instalar pacotes localmente usando
nix-env -i
, todos os seus.so
arquivos serão armazenados~/.nix-profile/lib/
.Se você instalar pacotes globalmente especificando-os
/etc/nixos/configuration.nix
, seus.so
arquivos correspondentes poderão ser encontrados em/nix/var/nix/profiles/system/sw/lib/
. Mais corretamente, apenas links simbólicos para arquivos correspondentes em algum lugar/nix/store/
estão nesse diretório.Portanto, se você instalar pacotes globalmente, a solução de Ivan Zakharyaschev se tornará:
Para que o primeiro comando funcione, você precisará instalar
glibc
globalmente. Você também pode modificar o segundo comando se tiver pacotes instalados globalmente e por usuário:Pode ser que o
.so
arquivo necessário simplesmente não esteja instalado no sistema, então você terá um erro como:Não tenho certeza de como encontrar um pacote correspondente para um arquivo ausente em geral, mas você pode pesquisar no google o nome do
.so
arquivo, instalar o pacote correspondente e tentar executar o executável com um costumeLD_LIBRARY_PATH
novamente.fonte