无法使用intl-support安装PHP 5.3.0

Ste*_*rig 5 php linux installation intl

目前我正在尝试在某些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
Run Code Online (Sandbox Code Playgroud)

ICU 4.2位于/usr/local/icu和PHP 5.2.9编译完美(没有int-和icu-options).但是当我编译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'
Run Code Online (Sandbox Code Playgroud)

我很确定它与找不到共享库有关.设置

export LD_LIBRARY_PATH=/usr/local/icu/lib
Run Code Online (Sandbox Code Playgroud)

没有帮助.

谁能指点我一些解决方案?我很无能 - 我不是这些事情的真正专家......

编辑:

我只是重新检查并确保各种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
Run Code Online (Sandbox Code Playgroud)

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'
Run Code Online (Sandbox Code Playgroud)

编辑:回答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
Run Code Online (Sandbox Code Playgroud)

关于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
Run Code Online (Sandbox Code Playgroud)

不知道这些信息是否有帮助.

编辑VolkerK的edit1和edit2:

我认为有一点问题 - 系统上确实存在另一个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
Run Code Online (Sandbox Code Playgroud)

gcc -lpthread -lm -L/usr/local/icu/lib -licui18n -licuuc -licudata -lpthread -lm -licuio -print-file-name=libicuuc.so.42回归

libicuuc.so.42
Run Code Online (Sandbox Code Playgroud)

所以问题似乎是,如何将新的lib-path引入构建过程?顺便说一句,我从你的答案中学到了很多 - 谢谢你们所有人.

我也尝试编译你的简单测试程序 - 它也失败了同样的未定义引用错误,很可能是由于PHP无法编译的原因.

如何摆脱lib-path中对旧icu-library的引用,或者如何确定新icu-library-path的优先级?

Vol*_*erK 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);
   ...
Run Code Online (Sandbox Code Playgroud)

到目前为止,还没有特定于版本的代码.无论您使用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`
Run Code Online (Sandbox Code Playgroud)

被执行.您自己尝试过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);
   ...
Run Code Online (Sandbox Code Playgroud)

现在您有一个特定于版本的依赖项,即对某些库必须解析的ubrk_close_4_2的引用.
所以包含部分确实有效.它确实找到了你的icu 4.2版本并使用了它的头文件.到现在为止还挺好.
现在为链接器部分.在你的情况下ICU_LIBS包含

-lpthread -lm -L/usr/local/icu/lib -licui18n -licuuc -licudata -lpthread -lm -licuio
Run Code Online (Sandbox Code Playgroud)

-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
Run Code Online (Sandbox Code Playgroud)

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 /链接器不要搜索.so文件,而是使用特定文件.结果应该与您的库路径工作相同(由于SONAME).
但每次运行./configure时,都必须再次应用"修复".

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