代码之家  ›  专栏  ›  技术社区  ›  Stefan Gehrig

安装支持intl的PHP5.3.0时遇到问题

  •  5
  • Stefan Gehrig  · 技术社区  · 15 年前

    目前我正在尝试在一些Linux测试服务器上安装PHP5.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

    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'
    

    编辑:沃尔克的答案 questions

    我从源代码处安装了ICU4.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
    

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

    edit1 and edit2 :

    我认为这是问题所在——系统上确实有另一个icu版本;至少在部分中(例如,没有其他icu配置;只有 /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
    

    我还试图编译您的简单测试程序,但同样失败 符号未找到 错误,很可能是由于PHP无法编译的相同原因。

    如何在lib路径中删除对旧icu库的引用,或者如何对新icu库路径进行优先级排序?

    3 回复  |  直到 7 年前
        1
  •  6
  •   VolkerK    15 年前

    问题似乎是二进制文件链接到了错误的(共享)库文件。
    首先是对我认为问题所在的冗长乏味的解释。请记住,我不是linux专家。我真的希望你理解我的思路,这样你就可以决定这是否可行和/或我错在哪里。
    第一种(粗)溶液很容易可逆。运行另一个./configure,所有更改都是历史记录。我认为这是很好的保存。

    首先,为什么您有icu 4-2特定的依赖关系?让我们来看看PHP的Itl扩展的源文件(Ext/ItL/GraceMe/GrimeEythStudio.c)

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

    到目前为止,还没有特定于版本的代码。无论使用ICU3.4还是ICU4.2,grapheme_string.c看起来都是一样的。ubrk_close_4_2从哪里来?
    当您运行“/configure…--with icu dir=/usr/local/icu”命令时,将执行ext/intl/config.m4文件。在这个过程中,调用icu config来获取构建php所需的include路径和库文件。您提供了一条通向icu安装的路径,归结起来就是这样

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

    被执行。您自己已经尝试过icu配置,因此您知道它输出什么,以及icu INCS和icu LIBS包含什么。 在编译/链接文件时,ICU增量和ICU库被传递给gcc。gcc(显然)在其默认目录中没有找到unicode/ubrk.h,因此它在ICU_INCS提供的其他包含目录中搜索该文件,在该目录中找到了ICU 4.2包含文件。 unicode/ubrk.h包括unicode/utypes.h,其中包括unicode/urename.h,并且同样包括ICU4.2头文件。在本例中,unicode/urename.h包括#define ubrk_close 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 LIBS包含

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

    -licuuc告诉gcc“找到一个名为‘icuuc’的库并使用它”。gcc然后在库路径中搜索具有与“icuuc”匹配的特定命名方案的文件。
    在这种情况下,libicuuc.so。请注意,它不查找特定于版本的文件名,只查找libicuuc.so。一旦找到这样一个文件,它就不会再寻找另一个。首先,gcc在其默认路径中进行搜索。然后它搜索附加的库路径——按照它们提供给gcc的顺序。即。

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

    如果有这样一个文件而不是/usr/local/lib/libicuuc.so(不再),则将查找/usr/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将/应该始终指向导出ICU4.2符号的实际共享对象。代码可能已更改/修复,但导出的符号保持不变。

    第一个“解决方案”(原始):让/configure发挥它的魔力,然后。。。只需编辑Makefile。
    在文本编辑器中打开Makefile(在源代码顶部目录中),搜索INTL_SHARED_LIBADD=并替换

    -licui18n-licuuc-licudata-licuio

    在那一行

    (保留任何-lm-pthread…不变)。重新编译。
    这“告诉”gcc/链接器不要搜索.so文件,而是使用特定的文件。结果应该与库路径正常工作时的结果相同(因为SONAME)。
    但每次运行./configure时,都必须再次应用“修复”。

    第二种解决方案:删除其他libicuXY.so符号链接(这就是“备份”一词的由来),只保留libicuXY.so->libicuXY.so.42.0.1链接。如果没有其他libicuuc.so->&燃气轮机;libicuuc.so.34.x.y链接gcc/链接器找不到它们,也不会链接到旧版本。
    同样,由于SONAME属性,已链接到旧版本的二进制文件仍将运行,因为“它们的”加载程序将搜索(仍然存在)libicuXY.so.34文件。

        2
  •  0
  •   Tim Post Samir J M Araujo    15 年前

    ld

    您可以:

    • 在/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,但是如果您只是想让它工作,那么修改该文件并不是什么大禁忌。

        3
  •  0
  •   Sander Marechal    15 年前

    当你打电话的时候

    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. This presentation (PPT) 有几个小例子。

    last changelog before intl became part of php itself 表示相同。

    我建议安装libicu3.8并重试。