Проблема, устанавливающая PHP 5.3.0 с intl-поддержкой

Я также склонен помещать свои модульные тесты в сам файл, как Jeremy Cantrell выше примечаний, хотя я склонен не помещать тестовую функцию в основную часть, а скорее помещают все в

if __name__ == '__main__':
   do tests...

блок. Это заканчивает тем, что добавило документацию к файлу как 'пример кода' для того, как использовать файл Python, который Вы тестируете.

я должен добавить, я склонен писать очень трудные модули/классы. Если бы Ваши модули требуют очень больших количеств тестов, можно поместить их в другого, но даже тогда, я все еще добавил бы:

if __name__ == '__main__':
   import tests.thisModule
   tests.thisModule.runtests

Это позволяет, кто-либо читающий Ваш исходный код знает, где искать тестовый код.

5
задан Community 23 May 2017 в 12:08
поделиться

3 ответа

Проблема, похоже, в том, что двоичный файл связан с неправильными (совместно используемыми) файлами библиотеки.
Сначала длинное скучное объяснение того, в чем, на мой взгляд, проблема. Имейте в виду, что я не эксперт по 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_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 / компоновщику не искать файлы .so, а использовать определенные. Результат должен быть таким же, как если бы путь к вашей библиотеке работал (из-за SONAME).
Но каждый раз, когда вы запускаете ./configure, вам нужно снова применять «исправление».

Второе решение: Удалите другие символические ссылки libicuXY.so (здесь на ум приходит слово «резервное копирование»), оставьте только libicuXY.so -> libicuXY.so.42.0.1 ссылки. Если нет других ссылок libicuuc.so - >> libicuuc.so.34.xy, gcc / компоновщик не может их найти и не будет ссылаться на старые версии.
Опять же, из-за свойств SONAME двоичные файлы, которые уже были связаны со старой версией, все равно будут работать, потому что «их» загрузчик будет искать (все еще существующие) файлы libicuXY.so.34.
Это повлияет на все последующие запуски компоновщика, т.е. если вы создадите другой проект, который использует более старые включаемые файлы, вы столкнетесь с той же проблемой в обратном направлении. Файлы заголовков и общие объекты (во время связывания) должны совпадать.

6
ответ дан 14 December 2019 в 13:44
поделиться

Когда вы вызываете

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) есть несколько тривиальных примеров.

EDIT

Думаю, я понял это. Похоже, php-intl работает только с libicu 3.6 или 3.8. Я постоянно гуглил дистрибутив Linux, поставляющий php-intl, и все они зависят от libicu 3.8, даже если они также поставляют libicu 4.0 или новее. Последний список изменений перед тем, как intl стал частью самого php , указывает на то же самое.

Я предлагаю установить libicu 3.8 и попробовать еще раз.

0
ответ дан 14 December 2019 в 13:44
поделиться

Есть хороший шанс, что 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 вручную.

Я рекомендую просто переустановить библиотеку в / usr / local / lib и запустив ldconfig перед изменением ld.so.conf, однако изменение этого файла не является большим табу, если вы просто хотите, чтобы он работал.

0
ответ дан 14 December 2019 в 13:44
поделиться
Другие вопросы по тегам:

Похожие вопросы: