もうずいぶん前になるが,研究室のサーバーに ATLAS を入れたとき,共有ライブラリをインストールしようと ldconfig を実行すると,次のように表示されて実行が失敗した.
$ ldconfig ldconfig: Can't link /usr/local/atlas/lib//usr/local/atlas/lib/libsatlas.so to libsatlas.so ldconfig: Can't link /usr/local/atlas/lib//usr/local/atlas/lib/libtatlas.so to libtatlas.so
そのときはとくに致命的でもなく,しばらく放置していたのだが,OS のアップグレードに合わせて ATLAS を入れ直すことになったので,ついでにこの問題の解決方法を探ってみることにした.
原因
configure を実行したあとにビルドディレクトリ下に生成される lib/Makefile の中に,次の記述がある.
LDTRY_WIN: $(LD) $(LDFLAGS) -shared -soname $(LIBINSTdir)/$(outso) -o $(outso) \ -rpath-link $(LIBINSTdir) --output-def=$(outdef) \ --whole-archive $(libas) --no-whole-archive $(LIBS)
ここで,ld がライブラリファイルを生成するときに,ファイル中に完全記述 soname(インストールディレクトリのパス + ライブラリ名)を記録している.このファイルをそのままインストールディレクトリに入れて ldconfig を実行すると,ldconfig はファイルのあるディレクトリのパス + ファイルに記録された完全記述 soname,つまりインストールディレクトリのパスが2回繰り返されたパスを探しに行ってしまい,サーチが失敗する.ld / ldconfig の知識が足りないのでこの理解でよいのか自信がないが,そうなっていると思えば納得できる.
対策
上のような状況を避けるためには,soname を記録しないでリンカを実行するのが手っ取り早いと思う.必要な static ライブラリは生成されているので,これを全部 ld に渡してやればよい.具体的な手順は次のようになる.
- とりあえず make を実行して ATLAS をビルドする.lib ディレクトリに生成物が出力される.
- 生成物のうち,共有ライブラリ(libsatlas.so,libtatlas.so)を削除しておく.
- 次のコマンドを実行して,soname のない共有ライブラリを新たに作成する.
$ ld -shared -o libsatlas.so \ --whole-archive libtstatlas.a libatlas.a liblapack.a \ --no-whole-archive libf77blas.a libcblas.a $ ld -shared -o libtatlas.so \ --whole-archive libtstatlas.a libatlas.a libptlapack.a \ --no-whole-archive libptf77blas.a libptcblas.a
- make install して,ldconfig を実行する.
ld につけるオプションは好みだが,心配なら Makefile と同じ指定をする.$LDFLAGS はビルドディレクトリ直下の Make.inc に書いてある.