J'utilise nix
en "mode mono-utilisateur" dans un système où je ne suis pas root (voir ci-dessous pour une description de ma configuration nix).
Je voulais exécuter rapidement l'un de mes fichiers binaires qui est lié dynamiquement à une bibliothèque absente du système.
J'ai donc installé la bibliothèque avec nix
:
$ nix-env -qa 'gmp'
gmp-4.3.2
gmp-5.1.3
$ nix-env -i gmp-5.1.3
Mais la bibliothèque n'est toujours pas trouvée par l'éditeur de liens:
$ 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)
$
Regardez, il est présent dans le système de fichiers:
$ 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
$
Que dois-je faire pour que les bibliothèques installées par nix
soient "visibles"?
Probablement, le script d'installation utilisateur standard de nix
modifie .bash_profile
pour l'ajouter bin/
à PATH
, mais ne fait pas quelque chose d'analogue pour les bibliothèques.
Ma configuration nix:
La seule chose que j'ai demandé à la racine de faire pour moi était mkdir -m 0755 /nix && chown ivan /nix
:, sinon j'ai suivi la procédure d'installation standard de nix simple. Alors maintenant, je peux utiliser des programmes personnalisés à partir de packages nix. Je ne pouvais pas le faire correctement sans aucune aide de la racine, c'est-à-dire sans /nix/
, car il /nix/
n'était pas disponible pour moi; Je pourrais bien sûr utiliser un autre répertoire, mais les packages binaires pré-construits ne seraient pas valides et tous les packages devraient être reconstruits, selon la documentation de nix. Dans mon cas, c'était plus simple de /nix/
me demander .
J'ai également ajouté ~/.bash_profile
:
export NIX_CONF_DIR=/nix/etc/nix
afin que je puisse éditer nix.conf
. (Il était censé être contrôlé /etc/
par la racine sinon. Je l'ai fait parce que je le voulais build-max-jobs
et les build-cores
paramètres.)
la source
nix-env
, sans parlernix.conf
. De quel OS s'agit-il? Aussi, que voulez-vous répéter les référencesnix
? Je ne l'ai jamais entendu que utilisé comme abréviationUnix
, mais il semble que vous l'utilisiez dans un contexte plus spécifique.nix
est un gestionnaire de packages moderne , et nixOS est une distribution, et Hydra est un système pour reconstruire constamment des packages nix, et nixOps est un outil pour gérer une infrastructure (un réseau de plusieurs hôtes) de manière déclarative, et disNix pour gérer un ensemble de services de manière déclarative (au-dessus d'une infrastructure).guix
est une progéniture GNU denix
, avec une distribution (promu comme 100% libre IICguix
.Réponses:
TL; DR
La solution de travail utilise
patchelf
(si vous devez faire face à des versions de glibc non correspondantes: dans le système hôte et les bibliothèques nix ont été liées), voir la deuxième moitié de mon histoire.Essayer l'approche habituelle
Essayer d'utiliser LD_LIBRARY_PATH
Eh bien, j'ai mis en place une variable d'environnement pour cela dans
~/.bash_profile
:Mais ce n'est pas tout!
Il existe maintenant des problèmes de liaison avec différentes versions de
libc
:Tri de 2 versions de glibc
L'erreur la plus surprenante ici est:
car
nix
doit avoir installé la versionglibc
qui est utilisée par sonlibgmp
!Et en effet, le
glibc
fromnix
est là:Probablement,
glibc
n'était pas disponible pour l'utilisateur, donc quand j'ai exécuté mon binaire, le système aglibc
été chargé en premier. Preuve:Ok, nous pouvons aussi essayer de rendre
glibc
visible à l'utilisateur:Alors tout va mal:
Donc, cela ne semble pas être une tâche facile si vous souhaitez charger des bibliothèques
nix
lors de l'exécution de vos propres binaires ...Pour l'instant, je commente
et faire dans la session shell:
Besoin de réfléchir davantage. (Lisez à propos __vdso_time: mode invalide pour la dlopen () : ayant une autre
glibc
enLD_LIBRARY_PATH
devrait accident, parce que votreld-linux-x86-64.so.2
ne correspondra pas à votrelibc.so.6
présence de plusieurs versions de glibc sur un seul système est possible, mais un peu délicat, comme expliqué dans cette réponse.).La solution recherchée: patchelf
Ainsi, le chemin vers l'éditeur de liens dynamique est codé en dur dans le binaire. Et l'éditeur de liens dynamique utilisé provient du système (de la glibc hôte), pas de nix. Et parce que l'éditeur de liens dynamique ne correspond pas à la glibc que nous voulons et devons utiliser, cela ne fonctionne pas.
Une solution simple et fonctionnelle est le patchelf .
Après ça, ça marche. Vous devez toujours jouer avec
LD_LIBRARY_PATH
.Si - comme dans mon cas imparfait - certaines des bibliothèques sont prises à partir de nix, mais d'autres à partir du système hôte (parce que je ne les ai pas installées avec
nix-env -i
), vous devez spécifier à la fois le chemin vers les bibliothèques nix, et vers les bibliothèques de votre système hôteLD_LIBRARY_PATH
(il remplace complètement le chemin de recherche par défaut).étape supplémentaire: patchelf pour le chemin de recherche de la bibliothèque
(à partir de la
patchelf
page)De même, vous pouvez modifier le
RPATH
, le chemin de recherche de l'éditeur de liens intégré dans les exécutables et les bibliothèques dynamiques:Cela oblige l'éditeur de liens dynamique à rechercher dans
/opt/my-libs/lib
et/foo/lib
pour les bibliothèques partagées nécessaires au programme. Bien sûr, vous pouvez également définir la variable d'environnementLD_LIBRARY_PATH
, mais cela est souvent gênant car il nécessite un script wrapper pour configurer l'environnement.la source
En plus du «mode mono-utilisateur» de Nix, je fournis une réponse aux utilisateurs de NixOS . Vous ne pouvez généralement pas exécuter de fichiers binaires sur NixOS.
Si vous installez des packages localement à l'aide de
nix-env -i
, tous vos.so
fichiers sont stockés dans~/.nix-profile/lib/
.Si vous installez des packages globalement en les spécifiant dans
/etc/nixos/configuration.nix
, vos.so
fichiers correspondants se trouvent dans/nix/var/nix/profiles/system/sw/lib/
. Plus correctement, seuls les liens symboliques vers les fichiers correspondants quelque part se/nix/store/
trouvent dans ce répertoire.Donc, si vous installez des packages à l'échelle mondiale, la solution d'Ivan Zakharyaschev devient:
Pour que la première commande fonctionne, vous devez installer
glibc
globalement. Vous pouvez également modifier la deuxième commande si des packages sont installés à la fois globalement et par utilisateur:Il se peut que le
.so
fichier nécessaire ne soit tout simplement pas installé dans le système, vous aurez donc une erreur comme:Je ne sais pas comment trouver un package correspondant pour un fichier manquant en général, mais vous pouvez rechercher le nom du
.so
fichier sur Google , installer le package correspondant et essayer d'exécuter à nouveau votre exécutable avec un fichier personnaliséLD_LIBRARY_PATH
.la source