5

現在、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 オプションなし)。しかし、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-libraries とそれぞれのソフト リンクがすべて次の場所にあることを確認しました/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 のedit1 および edit2の編集:

こすりがあると思います-実際、システムには別のicuバージョンがあります。少なくとも部分的に (たとえば、他の icu-config はありません。 の 1 つだけです/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 を優先するにはどうすればよいですか?

4

3 に答える 3

6

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

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

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

これまで、バージョン固有のコードはありません。grapheme_string.c は、icu 3.4 と icu 4.2 のどちらを使用しても同じように見えます。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 4.2 インクルード ファイルが見つかった ICU_INCS によって提供される追加のインクルード ディレクトリでファイルを検索しました。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 への参照ができました。
したがって、インクルード部分は機能しました。実際に 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.xy この libicuuc.so.34.xy は見つかりません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 ... はそのままにしておきます)。再度コンパイルします。
これは、.so ファイルを検索するのではなく、特定のファイルを使用するように gcc/リンカーに「指示」します。結果は、ライブラリ パスが機能していた場合と同じになるはずです (SONAME のため)。
ただし、./configure を実行するたびに、「修正」を再度適用する必要があります。

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

于 2009-07-11T17:34:57.343 に答える
0

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を実行することをお勧めします。ただし、ファイルを機能させたいだけの場合は、そのファイルを変更することはタブーではありません。

于 2009-07-08T00:36:48.083 に答える
0

電話すると

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

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

于 2009-07-06T07:40:23.367 に答える