質問

現在、Linux テストサーバーに PHP 5.3.0 をインストールしようとしています。私たちは ext/intl を待っていたので、それが提供する機能をチェックしたいと思います。私は走っています configure 次の引数で成功しました

./configure
    --with-apxs2=/usr/local/apache2/bin/apxs
    --prefix=/usr/local/php
    --with-zlib-dir=/usr/local/zlib
    --with-imap=/.../imap-2006k
    --with-imap-ssl
    --with-openssl=shared
    --with-iconv=shared
    --with-zlib=shared
    --with-curl=shared
    --with-curlwrappers
    --enable-exif
    --with-ldap=shared,/usr/local/openldap
    --with-ldap-sasl
    --enable-mbstring=shared
    --with-mcrypt
    --enable-soap=shared
    --enable-sockets
    --enable-zip=shared
    --enable-pdo=shared
    --with-pdo-sqlite=shared
    --with-sqlite=shared
    --with-mysql=shared,/usr/local/mysql
    --with-pdo-mysql=shared,/usr/local/mysql
    --with-mysqli=shared,/usr/local/mysql/bin/mysql_config
    --with-mhash=shared,/usr/local/mhash
    --with-libxml-dir=/usr/local/libxml2
    --with-xsl=shared,/usr/local/libxslt
    --enable-xmlreader=shared
    --enable-xmlwriter=shared
    --with-gmp=shared
    --with-icu-dir=/usr/local/icu
    --enable-intl

ICU 4.2 は次の場所にあります。 /usr/local/icu PHP 5.2.9 は (int- オプションと icu-option なしで) 完璧にコンパイルされました。しかし、PHP 5.3.0 ソースをコンパイルすると、次のようなエラー メッセージが大量に表示されます。

ext/intl/grapheme/.libs/grapheme_util.o(.text+0xbab):/.../php-5.3.0/ext/intl/grapheme/grapheme_util.c:208: undefined reference to `ubrk_close_4_2'

共有ライブラリが見つからないことが関係していると確信しています。設定

export LD_LIBRARY_PATH=/usr/local/icu/lib

役に立ちません。

誰か私に解決策を教えてくれませんか?私はかなり無知で、これらのことについては本当の専門家ではありません...

編集:

再確認して、さまざまな icu ライブラリとそれぞれのソフト リンクがすべて次の場所にあることを確認しました。 /usr/local/icu/lib:

lrwxrwxrwx  1 root root       20 Jul  1 09:56 libicudata.so -> libicudata.so.42.0.1
lrwxrwxrwx  1 root root       20 Jul  1 09:56 libicudata.so.42 -> libicudata.so.42.0.1
-rw-r--r--  1 root root 16015140 Jul  1 09:56 libicudata.so.42.0.1
lrwxrwxrwx  1 root root       20 Jul  1 09:56 libicui18n.so -> libicui18n.so.42.0.1
lrwxrwxrwx  1 root root       20 Jul  1 09:56 libicui18n.so.42 -> libicui18n.so.42.0.1
-rwxr-xr-x  1 root root  2454770 Jul  1 09:56 libicui18n.so.42.0.1
lrwxrwxrwx  1 root root       18 Jul  1 09:56 libicuio.so -> libicuio.so.42.0.1
lrwxrwxrwx  1 root root       18 Jul  1 09:56 libicuio.so.42 -> libicuio.so.42.0.1
-rwxr-xr-x  1 root root    65299 Jul  1 09:56 libicuio.so.42.0.1
lrwxrwxrwx  1 root root       18 Jul  1 09:56 libicule.so -> libicule.so.42.0.1
lrwxrwxrwx  1 root root       18 Jul  1 09:56 libicule.so.42 -> libicule.so.42.0.1
-rwxr-xr-x  1 root root   356125 Jul  1 09:56 libicule.so.42.0.1
lrwxrwxrwx  1 root root       18 Jul  1 09:56 libiculx.so -> libiculx.so.42.0.1
lrwxrwxrwx  1 root root       18 Jul  1 09:56 libiculx.so.42 -> libiculx.so.42.0.1
-rwxr-xr-x  1 root root    75110 Jul  1 09:56 libiculx.so.42.0.1
lrwxrwxrwx  1 root root       18 Jul  1 09:56 libicutu.so -> libicutu.so.42.0.1
lrwxrwxrwx  1 root root       18 Jul  1 09:56 libicutu.so.42 -> libicutu.so.42.0.1
-rwxr-xr-x  1 root root   159330 Jul  1 09:56 libicutu.so.42.0.1
lrwxrwxrwx  1 root root       18 Jul  1 09:56 libicuuc.so -> libicuuc.so.42.0.1
lrwxrwxrwx  1 root root       18 Jul  1 09:56 libicuuc.so.42 -> libicuuc.so.42.0.1
-rwxr-xr-x  1 root root  1660769 Jul  1 09:56 libicuuc.so.42.0.1

make check 大量のテストを実行し、すべて成功しました。

[All tests passed successfully...]
Elapsed Time: 00:00:25.000
make[2]: Leaving directory `/.../icu-4.2/source/test/cintltst'
---------------
ALL TESTS SUMMARY:
All tests OK:  testdata intltest iotest cintltst
make[1]: Leaving directory `/.../icu-4.2/source/test'
make[1]: Entering directory `/.../icu-4.2/source'
verifying that icu-config --selfcheck can operate
verifying that make -f Makefile.inc selfcheck can operate
PASS: config selfcheck OK
make[1]: Leaving directory `/.../icu-4.2/source'

編集:VolkerK さんへの回答 質問

ICU 4.2 をソースからインストールしました。ビルド プロセスの上で書いたように、単体テストとインストールはすべて正常に完了しました。

/usr/local/icu/bin/icu-config --version
4.2.0.1

/usr/local/icu/bin/icu-config --prefix
/usr/local/icu

/usr/local/icu/bin/icu-config --cppflags-searchpath
-I/usr/local/icu/include

/usr/local/icu/bin/icu-config --ldflags --ldflags-icuio
-lpthread -lm   -L/usr/local/icu/lib -licui18n -licuuc -licudata  -lpthread -lm   -licuio

objdump -C /usr/local/icu/lib/libicuuc.so.42.0.1
// doesn't work because of unrecognized argument -C

VolkerK のコメントに関する編集:

いいえ、コンパイラの切り替えは関係しませんでした。両方のビルド プロセスを順番に直接実行しました。 objdump /usr/local/icu/lib/libicuuc.so.42.0.1 どちらも動作しませんが、なんとか実行できました

objdump -t /usr/local/icu/lib/libicuuc.so.42.0.1 | grep ubrk_close
00000000000d2484 g     F .text  000000000000002d              ubrk_close_4_2

この情報が役立つかどうかはわかりません。

VolkerK の編集 編集1と編集2:

確かにシステムには別の icu バージョンが存在します。少なくとも部分的には(たとえば、他の icu-config はありません。中のものだけ /usr/local/icu/bin).

gcc -lpthread -lm -L/usr/local/icu/lib -licui18n -licuuc -licudata -lpthread -lm -licuio -print-file-name=libicuuc.so 戻り値

/usr/lib64/gcc-lib/x86_64-suse-linux/3.3.5/../../../../lib64/libicuuc.so

その間 gcc -lpthread -lm -L/usr/local/icu/lib -licui18n -licuuc -licudata -lpthread -lm -licuio -print-file-name=libicuuc.so.42 戻り値

libicuuc.so.42

問題は、新しい lib-path をビルド プロセスにどのように入れるかということのようです。ところで、私は皆さんの回答から多くのことを学びました - 皆さんに感謝します。

簡単なテストプログラムもコンパイルしようとしましたが、同じエラーで失敗します。 未定義の参照 エラーが発生します。おそらく、PHP がコンパイルできないのと同じ理由が原因です。

lib-path 内の古い icu-library への参照を削除するにはどうすればよいですか? または、新しい icu-library-path に優先順位を付けるにはどうすればよいですか?

役に立ちましたか?

解決

問題は、バイナリが間違った (共有) ライブラリ ファイルにリンクされていることのようです。
まず、私が問題と考えているものについての長くて退屈な説明です。私は Linux の専門家ではないことに注意してください。私の思考の流れを理解していただき、それが実現可能かどうか、また私のどこが間違っているかを判断していただきたいのです。
最初の (粗い) 解決策は簡単に元に戻すことができます。別の ./configure を実行すると、すべての変更が履歴になります。かなり節約できると思います。

そもそも、なぜ icu 4-2 固有の依存関係があるのでしょうか?phpのintl拡張子のソースファイル(ext/intl/grapheme/grapheme_string.c)を見てみましょう。

#include <unicode/ubrk.h>
...
PHP_FUNCTION(grapheme_substr)
{
   ...
   ubrk_close(bi);
   ...

今のところ、バージョン固有のコードはありません。icu 3.4 を使用しても icu 4.2 を使用しても、grapheme_string.c は同じように見えます。ubrk_close_4_2 はどこから来たのでしょうか?
「./configure」を実行すると...--with-icu-dir=/usr/local/icu" コマンドでファイル ext/intl/config.m4 が実行されます。このプロセスでは、icu-config が呼び出され、php のビルドに必要なインクルード パスとライブラリ ファイルが取得されます。ICU インストールへのパスを提供しました。これは要約すると、

ICU_CONFIG="$PHP_ICU_DIR/bin/icu-config"
ICU_INCS=`$ICU_CONFIG --cppflags-searchpath`
ICU_LIBS=`$ICU_CONFIG --ldflags --ldflags-icuio`

が実行されます。あなたは icu-config を自分で試したことがあるので、それが何を出力するか、つまり ICU_INCS と ICU_LIBS に何が含まれているかを知っています。ICU_INCS と ICU_LIBS は、ファイルがコンパイル/リンクされるときに gcc に渡されます。gcc は (どうやら) デフォルト ディレクトリで unicode/ubrk.h を見つけられなかったため、ICU_INCS によって提供される追加のインクルード ディレクトリでファイルを検索し、そこで icu 4.2 インクルード ファイルを見つけました。unicode/ubrk.h には unicode/utypes.h がインクルードされ、さらに unicode/urename.h がインクルードされます。さらに、icu 4.2 ヘッダー ファイルがインクルードされます。この場合、unicode/urename.h には #define ubrk_close ubrk_close_4_2 が含まれています。
プリプロセッサが完了すると、ubrk_close(bi) は ubrk_close_4_2(bi) に置き換えられます。

PHP_FUNCTION(grapheme_substr)
{
   ...
   ubrk_close_4_2(bi);
   ...

これで、バージョン固有の依存関係、つまりライブラリが解決する必要がある ubrk_close_4_2 への参照ができました。
したがって、 include 部分は機能しました。確かに、icu 4.2 バージョンが検出され、そのヘッダー ファイルが使用されました。ここまでは順調ですね。
次にリンカー部分です。あなたの場合、ICU_LIBSには次のものが含まれます

-lpthread -lm -L/usr/local/icu/lib -licui18n -licuuc -licudata -lpthread -lm -licuio

-licuuc は gcc に「'icuuc' というライブラリを見つけてそれを使用してください」と指示します。次に、gcc は、「icuuc」に一致する特定の命名スキームを持つファイルの LIB パスを検索します。
この場合は libicuuc.so です。バージョン固有のファイル名は検索せず、libicuuc.so だけを検索することに注意してください。そのようなファイルが見つかると、別のファイルは検索されません。まず、gcc はデフォルトのパスを検索します。次に、追加のライブラリ パスを、gcc に提供された順序で検索します。つまり、

gcc -L/usr/lib -L/usr/local/lib -licuuc

そのようなファイルがあれば /usr/lib/libicuuc.so が見つかりますが、/usr/local/lib/libicuuc.so (もう) は見つかりません。つまり、デフォルトのパスまたはライブラリ パス ディレクティブの順序のいずれかが問題の原因である可能性があります。
プログラムが共有オブジェクトに対してリンクされると、「特別な」ローダーがコードに追加され、共有オブジェクトの名前が (リンク時に) プログラムに保存されます。
プログラムが実行されるたびに、まず (ランタイム) ローダーが共有オブジェクトを (名前で) 検索し、コードをロードして、いくつかのスタブ ジャンプ アドレスを置き換えます。
共有オブジェクトはリンカーに「伝える」ことができます(つまり、リンク時) 実行時にローダーが検索する共有オブジェクトの名前 (SONAME プロパティ)。質問文に記載されているディレクトリのリストを見てください。

lrwxrwxrwx  1 root root       18 Jul  1 09:56 libicuuc.so -> libicuuc.so.42.0.1
lrwxrwxrwx  1 root root       18 Jul  1 09:56 libicuuc.so.42 -> libicuuc.so.42.0.1
-rwxr-xr-x  1 root root  1660769 Jul  1 09:56 libicuuc.so.42.0.1

libicuuc.so、これは、-licuuc が指定された場合に gcc が探すファイルです。リンカーはシンボリックリンクに従い、libicuuc.so.42.0.1 を使用します。このファイルは、(実行時) ローダーが libicuuc.so.42 を探す必要があることをリンカーに「伝えます」。 http://userguide.icu-project.org/packaging#TOC-ICU-Versions.
ローダーはシンボリックリンクをたどって libicuuc.so.42.0.1 をロードします。あるいは、別のバグ修正がある場合は libicuuc.so.42.0.2、libicuuc.so.42.0.3、libicuuc.so.42 が指すものをロードします。libicuuc.so.42 は、常に、icu 4.2 シンボルをエクスポートする実際の共有オブジェクトを指す必要があります。コードは変更/修正されている可能性がありますが、エクスポートされたシンボルは同じままです。あなたの問題は、gcc が libicuuc.so->libicuuc.so.42.0.1 を見つけられず、(たとえば) libicuuc.so->libicuuc.so.34.x.y を見つけないことです。この libicuuc.so.34.x.y は icu 4.2 シンボルをエクスポートせず、ubrk_close_4_2 ではなく ubrk_close_3_4 を提供します。したがって、ubrk_close_4_2 -> 未解決の参照エラーは発生しません。

最初の「解決策」(粗雑な):./configure に魔法をかけてもらいましょう...Makefile を編集するだけです。
テキスト エディタで Makefile (ソースのトップ ディレクトリにある) を開き、INTL_SHARED_LIBADD= を検索して置換します。

-licui18n -licuuc -licudata -licuio

その行で

/usr/local/icu/lib/libicui18n.so.42 /usr/local/icu/lib/libicuuc.so.42 /usr/local/icu/lib/libicudata.so.42 /usr/local/icu/lib /libicuio.so.42

(-lm -pthread はそのままにしておきます...彼らはあるとして)。再度コンパイルします。
これは、gcc/リンカーに .so ファイルを検索せず、特定のファイルを使用するように「指示」します。結果は、(SONAME のおかげで) ライブラリ パスが機能している場合と同じになるはずです。
ただし、./configure を実行するたびに、「修正」を再度適用する必要があります。

2 番目の解決策:他の libicuXY.so シンボリックリンク (「バックアップ」という言葉が思い浮かぶのはここです) を削除し、libicuXY.so->libicuXY.so.42.0.1 リンクのみを保持します。他に libicuuc.so->>libicuuc.so.34.x.y リンクがない場合、gcc/リンカーはそれらを見つけることができず、古いバージョンに対してリンクしません。
繰り返しますが、SONAME プロパティのおかげで、古いバージョンに対して既にリンクされているバイナリは引き続き機能します。これは、「それらの」ローダーが (まだ存在する) libicuXY.so.34 ファイルを検索するためです。
これは、後続のすべてのリンカーの実行に影響します。古いインクルード ファイルを使用する別のプロジェクトをビルドすると、逆に同じ問題が発生します。ヘッダー ファイルと共有オブジェクト (リンク時) は一致する必要があります。

他のヒント

その可能性は十分にあります ld それらのライブラリがどこにあるのかわかりません。LD_LIBRARY_PATH を (毎回) 更新するか、ldconfig に新しいライブラリを認識させる必要があります。

次のいずれかを行うことができます。

  • /usr/local/lib または /usr/lib にインストールします。
  • その場所を /etc/ld.so.conf に追加し、/sbin/ldconfig を再実行します。

現時点では、ライブラリがインストールされているものによって ldconfig が実行されたとしても、/usr/local/icu/lib はスコープ内にないため、ldconfig はその場所を知りません。ライブラリが /usr/local/lib/icu にインストールされている場合、ldconfig はライブラリの場所を認識しているため、LD パスを手動で指定する必要はありません。

ld.so.conf を変更する前に、ライブラリを /usr/local/lib に再インストールし、ldconfig を実行することをお勧めします。ただし、単に機能させるだけであれば、そのファイルを変更することは大きなタブーではありません。

電話をかけるとき

export LD_LIBRARY_PATH=/usr/local/icu/lib

その場合、現在設定されているパスが上書きされます。したがって、ICU は見つかっても、必要な他のライブラリが見つからない可能性があります。代わりにこれを試してください:

export LD_LIBRARY_PATH=/usr/local/icu/lib:${LD_LIBRARY_PATH}

それでも解決しない場合は、次の 2 つのことを試すことができます。

  1. 図書館は正しい場所にありますか?おそらく、インストールした場所が別の場所に移動した可能性があります。 /usr/local/lib/icu その代わり?
  2. ICUは機能していますか?ICU の「make check」ターゲットを試してください。ICU に含まれているテスト スイートをコンパイル/実行してみるか、簡単な ICU サンプルをコンパイルして実行してみてください。 このプレゼンテーション(PPT) いくつかの簡単な例があります。

編集

私はそれを理解したと思います。php-intl は libicu 3.6 または 3.8 でのみ動作するようです。php-intl を出荷している Linux ディストリビューションをずっとグーグルで調べてみましたが、libicu 4.0 以降を出荷している場合でも、それらはすべて libicu 3.8 に依存しています。の intl が php 自体の一部になる前の最後の変更ログ は同じことを示します。

libicu 3.8 をインストールして再試行することをお勧めします。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top