目前我正在尝试在一些 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 库和相应的软链接都位于 /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 配置;只有其中的一个 /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的国际延伸的源文件(EXT /国际/石墨烯/ grapheme_string.c)

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

到现在为止有没有特定版本的代码。 grapheme_string.c看起来是一样的,你是否使用ICU 3.4或4.2 ICU。在什么地方ubrk_close_4_2从何而来?点击 当您运行 “的./configure ... --with-ICU-DIR =在/ usr /本地/ ICU” 命令被执行的文件转/国际/ config.m4中。在这个过程中的ICU配置被称为获得包括编译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。海湾合作委员会(apperently)没有找到的Unicode / ubrk.h在它的默认目录,所以搜索在附加包括由ICU_INCS在那里找到了ICU 4.2包含文件提供的目录文件。 统一字符编码/ 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(氢)所取代。

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 /本地/ 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 。结果 加载程序将遵循syml墨和负载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结果。 打开生成文件(在源顶层目录)在文本编辑器,搜索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 /本地/ ICU / LIB / libicuio.so.42

(留下任何-lm -pthread ...,因为它们是)。重新编译。结果 这种“告诉”海湾合作委员会/连接器不要搜索的.so文件,但使用的特定的人。结果应该是一样的,如果你的库路径是工作(怎么一回事,因为SONAME的)。结果 但是每次运行时的./configure你必须应用“修复”了。

解决方法二:删除其他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 由安装该库的任何程序运行,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 的“make check”目标。尝试编译/运行 ICU 附带的测试套件,或者尝试编译并运行一个简单的 ICU 示例。 本次演讲(PPT) 有一些简单的例子。

编辑

我想我明白了。看起来 php-intl 仅适用于 libicu 3.6 或 3.8。我在 google 上搜索了 Linux 发行版的 php-intl,它们都依赖于 libicu 3.8,即使它们也提供 libicu 4.0 或更高版本。这 intl 成为 php 本身的一部分之前的最后一个变更日志 表示相同。

我建议安装 libicu 3.8 并重试。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top