用intl-support安装PHP 5.3.0时遇到困难

目前我正在尝试在某些Linuxtesting服务器上安装PHP 5.3.0。 正如我们急切地等待ext / intl,我们想看看它提供的function。 我使用以下参数成功运行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 

没有帮助。

任何人都可以指点我一些解决scheme? 我很无知 – 而且我也不是真正的专家

编辑:

我只是重新检查,并确保各种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运行吨testing – 所有这些成功:

 [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,正如我在构build过程中所写的那样,unit testing和安装都很顺利。

 /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的评论:

不,没有涉及编译器的切换 – 我直接依次运行两个构build过程。 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版本; 至less部分(没有其他的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 

所以问题似乎是,如何获得新的libpath进入构build过程? 顺便说一句,我从你的答案中学到了很多东西 – 谢谢大家。

我也试着编译你的简单的testing程序 – 它也失败了相同的未定义的引用错误,很可能是由于PHP不会编译相同的原因。

我怎样才能摆脱对libpath中旧的icu库的引用,或者如何优先考虑新的icu库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(apperently)没有在默认目录中找到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的引用。
所以包含部分工作。 它确实找到了你的icu 4.2版本,并使用它的头文件。 到现在为止还挺好。
现在是链接器部分。 在你的情况ICU_LIBS包含

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

-licuuc告诉gcc“找到一个名为”icuuc“的库,并使用它”。 然后,gcc在LIB路径中搜索具有与“icuuc”匹配的特定命名方案的文件。
在这种情况下,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,这是gcc在提供-licuuc时正在寻找的文件。 链接器遵循符号链接并使用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 …就像它们一样)。 再次编译。
这个“告诉”gcc / linker不搜索.so文件,而是使用特定的文件。 结果应该和你的库路径工作一样(使用SONAME)。
但是每次运行./configure时都必须重新应用“修复”。

第二种解决方案:删除其他libicuXY.so符号链接(这里是“备份”一词),只保留libicuXY.so-> libicuXY.so.42.0.1链接。 如果没有其他libicuuc.so – >> libicuuc.so.34.xy链接gcc / linker找不到它们,不会链接到旧版本。
同样因为已经链接到旧版本的SONAME属性二进制文件仍然会运行,因为“他们的”加载器将搜索(仍然存在的)libicuXY.so.34文件。
这将影响所有后续的链接器运行,也就是说,如果您构建另一个使用较旧的包含文件的项目,则会以相反的方式运行相同的问题。 头文件和共享对象(在链接时)必须匹配。

ld很可能不知道在哪里找到这些库。 您将不得不更新LD_LIBRARY_PATH(每次),或者让ldconfig了解您的新库。

你可以:

  • 将其安装在/ usr / local / lib或/ usr / lib中
  • 将其位置添加到/etc/ld.so.conf,然后重新运行/ sbin / ldconfig

现在,即使ldconfig是通过安装该库来运行的,ldconfig也不知道它的位置,因为/ usr / local / icu / lib不在其范围内。 如果该库安装到/ 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} 

如果这没有帮助,我可以想到两件事情要尝试:

  1. 图书馆是在正确的地方? 也许你的安装移到别的地方了,比如/usr/local/lib/icu呢?
  2. ICU工作吗? 尝试ICU的“检查”目标。 尝试编译/运行ICU附带的测试套件,或尝试编译和运行一个简单的ICU示例。 这个演示文稿(PPT)有一些微不足道的例子。

编辑

我想我明白了。 它看起来像php-intl只适用于libicu 3.6或3.8。 我已经搜索了Linux发行版运行php-intl,他们都依赖于libicu 3.8,即使他们也运输libicu 4.0或更高版本。 intl成为php本身的一部分之前的最后更新日志表明相同。

我建议安装libicu 3.8并重试。