Unable to load dynamic library 'XXX.so' - libYYY.so: undefined symbol: ZZZ
configure・make・make installまでは問題なく進んだのに、Apacheを起動しようとすると「Unable to load dynamic library」が発生。よくある話ですね(ホントか?)。
今回はPHP4.4.6+libsablotで発生しました。ズルしてsablotronをrpmからインストールしようとしたのが敗因。
次のような環境で、
- CentOS4.4
- Apache2.2.4(src)
- PHP4.4.6(src)
- sablotron1.0.3(rpm。http://dag.wieers.com/rpm/packages/sablotron/)
- js1.5(rpm。http://dag.wieers.com/rpm/packages/js/)
configureオプションを
# for PHP4 ./configure \ --with-apxs2=/usr/local/apache2/bin/apxs \ --prefix=/usr/local/lib/php4 \ --with-pear=/usr/local/lib/php4/pear \ --with-config-file-path=/usr/local/lib/php4/ini/4.4.6 \ --with-config-file-scan-dir=/usr/local/lib/php4/ini.d \ --enable-zend-multibyte \ --enable-mbstring=shared \ --with-dom \ --with-dom-xslt \ --with-dom-exslt \ --with-gd=shared \ --with-jpeg-dir \ --with-png-dir \ --with-zlib-dir \ --with-ttf \ --with-freetype-dir \ --enable-gd-jis-conv \ --with-pspell=shared \ --enable-debug \ --with-openssl=shared \ --with-mysql=shared \ --with-curl=shared \ --enable-bcmath=shared \ --enable-pcntl=shared \ --enable-sockets=shared \ --with-oci8=shared,/usr/lib/oracle/xe/app/oracle/product/10.2.0/server/ \ --enable-sigchild \ --enable-xslt=shared \ --with-xslt-sablot
のようにしてbuildすると、Apache起動時に
Unable to load dynamic library '/usr/local/lib/php4/lib/php/extensions/debug-non-zts-20020429/xslt.so' - /usr/lib/libsablot.so.0: undefined symbol: JS_PropertyStub
てな具合でエラーになります(Apacheは起動します)。
今回使ったsablotronのrpmはjsに依存しているため、PHPをbuildする際、libjs.soをリンクしてやる(見えるようにしてやる)必要があります。ここでxslt.soを確認してみると、libjs.soとリンクしてないことが分かります。
$ ldd /usr/local/lib/php4/lib/php/extensions/debug-non-zts-20020429/xslt.so libsablot.so.0 => /usr/lib/libsablot.so.0 (0x00111000) libexpat.so.0 => /usr/lib/libexpat.so.0 (0x00631000) libc.so.6 => /lib/tls/libc.so.6 (0x001e9000) libstdc++.so.6 => /usr/lib/libstdc++.so.6 (0x00d00000) libm.so.6 => /lib/tls/libm.so.6 (0x006cc000) libgcc_s.so.1 => /lib/libgcc_s.so.1 (0x00387000) /lib/ld-linux.so.2 (0x00b64000) $
ということで、configureオプションに
--with-sablot-js
を追加して再buildすると
$ ldd /usr/local/lib/php4/lib/php/extensions/debug-non-zts-20020429/xslt.so libsablot.so.0 => /usr/lib/libsablot.so.0 (0x00a31000) libjs.so.1 => /usr/lib/libjs.so.1 (0x00111000) libexpat.so.0 => /usr/lib/libexpat.so.0 (0x00c37000) libc.so.6 => /lib/tls/libc.so.6 (0x0018e000) libstdc++.so.6 => /usr/lib/libstdc++.so.6 (0x00843000) libm.so.6 => /lib/tls/libm.so.6 (0x00ceb000) libgcc_s.so.1 => /lib/libgcc_s.so.1 (0x0091f000) /lib/ld-linux.so.2 (0x00b64000) $
という具合にlibjs.so(ただしくはlibjs.so.1)とリンクされて、Apacheも問題なく起動してxslt拡張モジュールが使えるようになります。
もう一つの解としては、「(soファイルで必要なライブラリがロードされてないので)そんなシンボル知らんわぃ」ということなので、Apacheを起動する前に必要なライブラリをロードしてやる、というのが考えられます。上記の場合、エラーの原因となっているシンボル「JS_PropertyStub」はlibjs.soの含まれていますので、libjs.soを事前にロードしてやるとヨサゲです。
$ nm /usr/lib/libjs.so | grep JS_PropertyStub
0000fd40 T JS_PropertyStub
$
ということで、apachectlと同じディレクトリにenvvarsファイルを作ってやり、そこでロードすることにしました。一番最後の「LD_PRELOAD」がそれです。
$ cat /usr/local/apache2/bin/envvars # Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # # # envvars-std - default environment variables for apachectl # # This file is generated from envvars-std.in # LD_LIBRARY_PATH="/usr/local/apache2/lib:$LD_LIBRARY_PATH" export LD_LIBRARY_PATH # export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/lib/php5/lib/php/extensions/debug-non-zts-20060613/:/usr/local/lib/php4/lib/php/extensions/debug-non-zts-20020429/ export TZ="Asia/Tokyo" export LD_PRELOAD=/usr/lib/libjs.so $
ちなみに、libjs.soはlibjs.so.1へのシンボリックリンクになってます。
$ LANG=C ls -l /usr/lib/libjs* -rwxr-xr-x 1 root root 695334 Nov 27 2005 /usr/lib/libjs.a lrwxrwxrwx 1 root root 10 Mar 30 11:55 /usr/lib/libjs.so -> libjs.so.1 -rwxr-xr-x 1 root root 1531088 Nov 27 2005 /usr/lib/libjs.so.1 [shimooka@hrimfaxi php-4.4.6]$
これで起動するとxslt.soもちゃんとロードされました。
まあ、面倒なので、configureオプションを付けてbuildした方が良いでしょうね。