Estoy usando el nix"modo de usuario único" en un sistema en el que no soy la raíz (ver más abajo para una descripción de mi configuración de nix).
Quería ejecutar rápidamente uno de mis archivos binarios que está vinculado dinámicamente con una biblioteca que está ausente en el sistema.
Entonces, instalé la biblioteca con nix:
$ nix-env -qa 'gmp'
gmp-4.3.2
gmp-5.1.3
$ nix-env -i gmp-5.1.3
Pero el enlazador todavía no encuentra la biblioteca:
$ 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)
$ 
Mira, está presente en el sistema de archivos:
$ 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
$ 
¿Qué hago para que las bibliotecas instaladas por nixsean "visibles"?
Probablemente, la secuencia de comandos de usuario a la instalación estándar de la nixmodifica .bash_profilepara añadir su bin/dentro PATH, pero no hace algo similar para las bibliotecas.
Mi configuración de nix:
Lo único que le pedí a la raíz que hiciera por mí fue: de lo mkdir -m 0755 /nix && chown ivan /nixcontrario, he seguido el procedimiento estándar de instalación de nix simple. Entonces ahora puedo usar programas personalizados de paquetes nix. No podría hacer esto bien sin ninguna ayuda de la raíz, es decir, sin /nix/, porque /nix/no estaba disponible para mí; Por supuesto, podría usar otro directorio, pero los paquetes binarios precompilados no serían válidos y todos los paquetes tendrían que reconstruirse, de acuerdo con la documentación de nix. En mi caso, fue más sencillo preguntar /nix/por mí.
Otra cosa que he hecho es agregar a ~/.bash_profile:
export NIX_CONF_DIR=/nix/etc/nix
para que yo pueda editar nix.conf. (De lo /etc/contrario, se suponía que estaba controlado por la raíz . Lo hice porque quería build-max-jobsy la build-coresconfiguración en él).
fuente

nix-env, por no mencionarnix.conf. ¿Qué sistema operativo es este? Además, ¿quénixsignifican referencias repetidas ? Solo he escuchado que se usa como abreviaturaUnix, pero parece que lo está usando en un contexto más específico.nixes un administrador de paquetes moderno , y nixOS es una distribución, y Hydra es un sistema para reconstruir constantemente paquetes de nix, y nixOps es una herramienta para administrar una infraestructura (una red de varios hosts) declarativamente, y disNix para administrar un conjunto de servicios declarativamente (encima de una infraestructura).guixes una descendencia de GNUnix, con una distribución (promovida como 100% libre IICguix.Respuestas:
TL; DR
La solución de trabajo está utilizando
patchelf(si tiene que lidiar con versiones de glibc que no coinciden: en el sistema host y con el que se han vinculado las bibliotecas nix), vea la segunda mitad de mi historia.Intentando el enfoque habitual
Intentando usar LD_LIBRARY_PATH
Bueno, he configurado una variable de entorno para esto en
~/.bash_profile:¡pero eso no es todo!
Ahora hay problemas al vincular con diferentes versiones de
libc:Clasificando 2 versiones de glibc
El error más sorprendente aquí es:
porque
nixdebe haber instalado la versión de laglibccual es utilizada por sulibgmp!Y de hecho, el
glibcdenixestá ahí:Probablemente,
glibcno estaba disponible para el usuario, así que cuando ejecuté mi binario, el sistemaglibcse cargó primero. Prueba:Ok, también podemos intentar hacer
glibcvisible para el usuario:Entonces todo está mal:
Por lo tanto, parece que no es un trabajo fácil si desea cargar bibliotecas
nixcuando ejecuta sus propios binarios ...Por ahora, estoy comentando
y haciendo en la sesión de shell:
Necesito pensar más. (Lea acerca de __vdso_time: modo no válido para dlopen () : se espera que se bloquee otro
glibcenLD_LIBRARY_PATH, porqueld-linux-x86-64.so.2no coincidirá con sulibc.so.6. Tener múltiples versiones de glibc en un solo sistema es posible, pero un poco complicado, como se explica en esta respuesta).La solución necesaria: parchelf
Entonces, la ruta al enlazador dinámico está codificada en el binario. Y el enlazador dinámico que se usa es del sistema (del host glibc), no de nix. Y debido a que el enlazador dinámico no coincide con el glibc que queremos y necesitamos usar, no funciona.
Una solución simple y funcional es parchelf .
Después de eso, funciona. Sin embargo, aún debes jugar con ellos
LD_LIBRARY_PATH.Si, como en mi caso imperfecto, algunas de las bibliotecas se toman de nix, pero algunas se toman del sistema host (porque no las he instalado
nix-env -i), debe especificar tanto la ruta a las librerías de nix, y en las bibliotecas de su sistema hostLD_LIBRARY_PATH(anula por completo la ruta de búsqueda predeterminada).paso adicional: patchelf para la ruta de búsqueda de la biblioteca
(de la
patchelfpágina)Del mismo modo, puede cambiar la
RPATHruta de búsqueda del enlazador incrustada en ejecutables y bibliotecas dinámicas:Esto hace que el vinculador dinámico busque
/opt/my-libs/liby busque/foo/liblas bibliotecas compartidas que necesita el programa. Por supuesto, también puede establecer la variable de entornoLD_LIBRARY_PATH, pero eso a menudo es inconveniente ya que requiere un script de contenedor para configurar el entorno.fuente
Además del "modo de usuario único" de Nix, proporciono una respuesta para los usuarios de NixOS . Por lo general , no puede ejecutar archivos binarios en NixOS.
Si instala paquetes utilizando localmente
nix-env -i, todos sus.soarchivos se almacenan en~/.nix-profile/lib/.Si instala paquetes globalmente al especificarlos
/etc/nixos/configuration.nix,.sopuede encontrar sus archivos correspondientes en/nix/var/nix/profiles/system/sw/lib/. Más correctamente, solo los enlaces simbólicos a los archivos correspondientes en algún lugar/nix/store/están en ese directorio.Entonces, si instala paquetes globalmente, la solución de Ivan Zakharyaschev se convierte en:
Para que el primer comando funcione, deberá instalarlo
glibcglobalmente. También puede modificar el segundo comando si tiene paquetes instalados tanto globalmente como por usuario:Es posible que el
.soarchivo necesario simplemente no esté instalado en el sistema, por lo que tendrá un error como:No estoy seguro de cómo encontrar un paquete correspondiente para un archivo que falta en general, pero puede buscar en Google el nombre del
.soarchivo e instalar el paquete correspondiente e intentar ejecutar su archivo ejecutable con un personalizadoLD_LIBRARY_PATHnuevamente.fuente