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 nix
sean "visibles"?
Probablemente, la secuencia de comandos de usuario a la instalación estándar de la nix
modifica .bash_profile
para 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 /nix
contrario, 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-jobs
y la build-cores
configuración en él).
fuente
nix-env
, por no mencionarnix.conf
. ¿Qué sistema operativo es este? Además, ¿quénix
significan referencias repetidas ? Solo he escuchado que se usa como abreviaturaUnix
, pero parece que lo está usando en un contexto más específico.nix
es 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).guix
es 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
nix
debe haber instalado la versión de laglibc
cual es utilizada por sulibgmp
!Y de hecho, el
glibc
denix
está ahí:Probablemente,
glibc
no estaba disponible para el usuario, así que cuando ejecuté mi binario, el sistemaglibc
se cargó primero. Prueba:Ok, también podemos intentar hacer
glibc
visible para el usuario:Entonces todo está mal:
Por lo tanto, parece que no es un trabajo fácil si desea cargar bibliotecas
nix
cuando 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
glibc
enLD_LIBRARY_PATH
, porqueld-linux-x86-64.so.2
no 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
patchelf
página)Del mismo modo, puede cambiar la
RPATH
ruta de búsqueda del enlazador incrustada en ejecutables y bibliotecas dinámicas:Esto hace que el vinculador dinámico busque
/opt/my-libs/lib
y busque/foo/lib
las 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.so
archivos se almacenan en~/.nix-profile/lib/
.Si instala paquetes globalmente al especificarlos
/etc/nixos/configuration.nix
,.so
puede 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
glibc
globalmente. También puede modificar el segundo comando si tiene paquetes instalados tanto globalmente como por usuario:Es posible que el
.so
archivo 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
.so
archivo e instalar el paquete correspondiente e intentar ejecutar su archivo ejecutable con un personalizadoLD_LIBRARY_PATH
nuevamente.fuente