A certain engineer "COMPLEX"

開発メモ その192 Linuxの共有オブジェクト(so)ファイルの名前を変更する

soファイルの名前を変えても別プログラムからリンクがうまくいかなかった問題での対応。

Introduction


NVIDIA Caffeを改造したライブラリを作っているのですが、都合上オリジナルのNVIDIA Caffe (libcaffe.so) と共存させる必要があり、その改造Caffe (以下libcaffemod.so) をシステムにインストールします。
オリジナルのNVIDIA Caffeの出力は下記。

単純にファイル名を変えて、システム (/usr/lib/x86_64-linux-gnu/)にインストールしたところでうまく動きません。
というのも、単純に名前を変えてリンクしようとしてもうまくいきません。

例えば、下記の簡単なプログラム。

これに、libcaffe.so.0.17.3をlibcaffemod.soに名前を変えてコピーしリンクさせてみます。
CMakeLists.txtは下記。

実行してみます。単純にCaffeのバージョンを出力するだけです。

ではリンクしているsoファイルは何になるか?

名前変更前にリンクしています。
動いているのはリンク先の同じディレクトリにオリジナルのlibcaffeが存在するからです。
libcaffe.soを全部削除するとプログラムが動かなくなります。

どうするべきか。

How to?


共有オブジェクトファイルは内部に共有オブジェクトの名前を保持しています。
これが原因で、リンク先がファイル名変更前になっていたのです。
下記は名前だけ変更したlibcaffemod.soの内部に保持した名前を確認しています。

正攻法はNVIDIA CaffeのMakefileやCMakeLists.txtを書き換えて、正しい名前で出力するようにするべきです。
が、単純に変更してもうまくビルドできませんでした。
なので別の方法を。

PatchELF

PatchELFというLinuxの ELF (Executable and Linkable Format)ファイル を操作するツールを使います。

A small utility to modify the dynamic linker and RPATH of ELF executables - NixOS/patchelf

バイナリで配布はされていないのでソースからビルドします。
最新版を使ってください。少し古い版の0.8はうまく動きませんでした。

make installはしてもしなくても。
同じディレクトリのsrc配下にバイナリが生成されるので。

これを使って先のlibcaffemod.soを変更します。
--set-sonameコマンドを使います。最初の引数が新しい名前、最後が対象ファイルのパスです。

見事に変更されました。
一度サンプルプログラムのbuildを削除してからビルドし直して、lddでリンク先を確認してみます。

きちんと変わっていますね。

コメントを残す

メールアドレスが公開されることはありません。

%d人のブロガーが「いいね」をつけました。