実行時にnixによってインストールされたライブラリを使用する方法


8

私が使用しているnix私はルートじゃないシステムで「シングルユーザモード」で(私のnixのセットアップの説明については以下を参照)。

システムに存在しないライブラリに動的にリンクされているバイナリの1つをすばやく実行したいと思っていました。

だから、私はライブラリをインストールしましたnix

$ nix-env -qa 'gmp'
gmp-4.3.2
gmp-5.1.3
$ nix-env -i gmp-5.1.3

しかし、ライブラリはまだリンカによって見つかりません:

$ 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)
$ 

見て、それはファイルシステムに存在します:

$ 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
$ 

によってインストールされたライブラリnixが「見える」ようにするにはどうすればよいですか?

おそらく、標準のユーザーがインストールスクリプトnix修正は、.bash_profileその追加するbin/にはPATH、しかし、ライブラリの類似した何かをしていません。

私のnixセットアップ:

rootに依頼した唯一のことは次のとおりですmkdir -m 0755 /nix && chown ivan /nix。それ以外の場合は、標準の単純なnixインストール手順に従いました。これで、nixパッケージのカスタムプログラムを使用できるようになりました。が利用できなかったため、ルートからの助けがなければ、つまりなしでは/nix/、これをうまく行うこと/nix/ができませんでした。もちろん、別のディレクトリを使用することもできますが、事前にビルドされたバイナリパッケージは有効ではなく、すべてのパッケージを再ビルドする必要があります。私の場合、私に依頼する方が簡単/nix/でした。

私がやったもう一つはに追加すること~/.bash_profileです:

export NIX_CONF_DIR=/nix/etc/nix

編集できるようにnix.conf。(それ/etc/以外の場合は、ルート制御されているはずでした。設定したかったので、それをbuild-max-jobs行いbuild-coresました。)


1
言うまでもありnix-envませんnix.conf。これはどんなOSですか?また、繰り返し参照はnixどういう意味ですか?の省略形として使用したと聞いたことUnixがありますが、より具体的なコンテキストで使用しているようです。
Faheem Mitha、2015年

3
@FaheemMithaタグに説明があると思ったので、投稿でこれを説明する必要はありません。しかし、どうやらタグには説明がありません。ああ、それで、私はいくつかのリンクを入れなければなりません。nix最新のパッケージマネージャーであり、nixOSはディストリビューションであり、Hydraはnixパッケージを常に再構築するためのシステムであり、nixOpsはインフラストラクチャ(複数のホストのネットワーク)を宣言的に管理し、disNixは一連のサービスを宣言的に管理するツールです(インフラストラクチャの上)。guixのGNUの子孫でありnix、ディストリビューション(100%libre IICとして昇格
imz-Ivan Zakharyaschev、2015年

1
そうですか。情報のおかげで。私はそれ以外は聞いたことがありませんguix
Faheem Mitha、2015年

回答:


7

TL; DR

作業ソリューションが使用していますpatchelf(一致しないglibcバージョンに対処する必要がある場合:ホストシステムで、1つのnixライブラリがリンクされている場合)、私の話の後半を参照してください。

通常のアプローチを試す

LD_LIBRARY_PATHを使用しようとしています

さて、私はこれのために環境変数を設定しました~/.bash_profile

NIX_LINK=/home/ivan/.nix-profile
export LD_LIBRARY_PATH="$NIX_LINK"/lib

しかしそれだけではありません!

の異なるバージョンとのリンクに問題があります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)
$ 

glibcの2つのバージョンを整理する

ここで最も驚くべきエラーは次のとおりです。

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)

によって使用nixされているバージョンがインストールされている必要があるためです!glibclibgmp

そして確かに、そこglibcからnixあります:

$ 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
$ 

おそらく、glibcユーザーは利用できなかったので、バイナリを実行すると、システムglibcが最初にロードされました。証明:

$ ls ~/.nix-profile/lib/*libc*
ls: cannot access /home/ivan/.nix-profile/lib/*libc*: No such file or directory
$ 

わかりglibcました、ユーザーにも見えるようにすることができます:

$ nix-env -i glibc

その後、すべてが悪いです:

$ 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
$ 

したがって、nix独自のバイナリを実行しているときにライブラリをロードするのは簡単な仕事ではないようです...

今はコメントアウトします

export LD_LIBRARY_PATH="$NIX_LINK"/lib

シェルセッションで行う:

$ unset LD_LIBRARY_PATH
$ export LD_LIBRARY_PATH

もっと考える必要があります。(__vdso_time:dlopen()の無効なモードについての説明:と一致しないため、別のglibcin LD_LIBRARY_PATHを使用するとクラッシュすることが予想されld-linux-x86-64.so.2ますlibc.so.6。単一のシステムで複数のバージョンのglibcを使用することは可能ですが、この回答で説明されているように少し注意が必要です。)

必要なソリューション:patchelf

そのため、ダイナミックリンカーへのパスはバイナリにハードコードされています。また、使用されている動的リンカーはシステムから(ホストglibcから)であり、nixからではありません。また、ダイナミックリンカーは、必要なglibcと一致しないため、機能しません。

シンプルで実用的なソリューションはpatchelfです。

patchelf --set-interpreter /home/ivan/.nix-profile/lib/ld-linux-x86-64.so.2 ../valencies

その後、それは動作します。あなたはまだいじる必要がありLD_LIBRARY_PATHます。

$ LD_LIBRARY_PATH=/home/ivan/.nix-profile/lib:/lib64/:/usr/lib64/ ../valencies

私の不完全なケースのように、一部のライブラリはnixから取得されますが、一部はホストシステムから取得されます(私はそれらをでインストールしていないためnix-env -i)、両方のnixライブラリへのパスを指定する必要があります。そして、ホストシステムのlibsにLD_LIBRARY_PATH(デフォルトの検索パスを完全に上書きします)。

追加の手順:ライブラリ検索パスのpatchelf

patchelfページから)

同様に、RPATH実行可能ファイルと動的ライブラリに埋め込まれたリンカー検索パスであるを変更できます。

patchelf --set-rpath /opt/my-libs/lib:/foo/lib program

これは、動的リンカがで検索する原因/opt/my-libs/lib/foo/libプログラムで必要とされる共有ライブラリのために。もちろん、環境変数を設定することもできますが、環境LD_LIBRARY_PATHを設定するためにラッパースクリプトが必要になるため、多くの場合不便です。


3

Nixの「シングルユーザーモード」に加えて、NixOSユーザーに回答を提供します。通常、NixOSではバイナリファイル実行できません

を使用してパッケージをローカルにインストールするとnix-env -i、すべての.soファイルがに保存され~/.nix-profile/lib/ます。

パッケージをで指定してグローバルにインストールする場合/etc/nixos/configuration.nix、対応する.soファイルはにあります/nix/var/nix/profiles/system/sw/lib/。より正確に/nix/store/は、そのディレクトリのどこかにある対応するファイルへのシンボリックリンクのみです。

したがって、パッケージをグローバルにインストールすると、Ivan Zakharyaschevのソリューションは次のようになります。

$ patchelf --set-interpreter /nix/var/nix/profiles/system/sw/lib/ld-linux-x86-64.so.2 ./YOUREXECUTABLE
$ LD_LIBRARY_PATH=/nix/var/nix/profiles/system/sw/lib ./YOUREXECUTABLE

最初のコマンドが機能するためには、glibcグローバルにインストールする必要があります。パッケージをグローバルとユーザーごとの両方にインストールしている場合は、2番目のコマンドを変更することもできます。

$ LD_LIBRARY_PATH=/home/YOURUSERNAME/.nix-profile/lib:/nix/var/nix/profiles/system/sw/lib ./YOUREXECUTABLE

必要な.soファイルがシステムにインストールされていない可能性があるため、次のようなエラーが発生します。

./YOUREXECUTABLE: error while loading shared libraries: libX11.so.6: cannot open shared object file: No such file or directory

不足しているファイルに対応するパッケージを見つける方法は一般的にわかりませんが、.soファイルの名前をグーグルして対応するパッケージをインストールし、カスタムで実行可能ファイルをLD_LIBRARY_PATHもう一度実行してみてください。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.