Сборка расширений PHP¶
Теперь, когда вы знаете, как собрать сам PHP, мы перейдём к сборке дополнительных расширений. Мы обсудим, как работает процесс сборки и какие опции для этого доступны.
Загрузка разделяемых расширений¶
Как вы уже знаете из предыдущего раздела, расширения PHP могут быть либо статически встроены в бинарный файл PHP,
либо собраны в разделяемый объект (.so). Статическая линковка используется по умолчанию для большинства
поставляемых в комплекте расширений, тогда как разделяемые объекты можно создать, явно передав
--enable-EXTNAME=shared или --with-EXTNAME=shared скрипту ./configure.
В то время как статические расширения всегда доступны, разделяемые расширения необходимо загружать с помощью ini-опций
extension или zend_extension. Обе опции принимают либо абсолютный путь к файлу .so, либо путь
относительно настройки extension_dir.
В качестве примера рассмотрим сборку PHP, выполненную со следующей строкой configure:
~/php-src> ./configure --prefix=$HOME/myphp \
--enable-debug --enable-maintainer-zts \
--enable-opcache --with-gmp=shared
В этом случае и расширение opcache, и расширение GMP собираются в разделяемые объекты, расположенные в директории
modules/. Вы можете загрузить оба, либо изменив extension_dir, либо передав абсолютные пути:
~/php-src> sapi/cli/php -dzend_extension=`pwd`/modules/opcache.so \
-dextension=`pwd`/modules/gmp.so
# or
~/php-src> sapi/cli/php -dextension_dir=`pwd`/modules \
-dzend_extension=opcache.so -dextension=gmp.so
# or (since PHP 7.2 the .so is optional)
~/php-src> sapi/cli/php -dextension_dir=`pwd`/modules \
-dzend_extension=opcache -dextension=gmp
На этапе make install оба файла .so будут перемещены в директорию расширений вашей установки PHP, которую
можно найти с помощью команды php-config --extension-dir. Для указанных выше опций сборки это будет
/home/myuser/myphp/lib/php/extensions/no-debug-non-zts-MODULE_API. Это значение также будет значением по
умолчанию для ini-опции extension_dir, так что указывать её явно не придётся, и вы сможете загружать расширения
напрямую:
~/myphp> bin/php -dzend_extension=opcache -dextension=gmp
Остаётся один вопрос: какой механизм следует использовать? Разделяемые объекты позволяют иметь базовый бинарный файл PHP и загружать дополнительные расширения через php.ini. Дистрибутивы используют это, предоставляя “голый” пакет PHP и распространяя расширения как отдельные пакеты. С другой стороны, если вы собираете собственный бинарный файл PHP, вам, вероятно, это не нужно, потому что вы уже знаете, какие расширения вам требуются.
Как правило, статическая линковка используется для расширений, поставляемых вместе с самим PHP, а разделяемые расширения — для всего остального. Причина проста: собрать внешнее расширение как разделяемый объект проще (или, по крайней мере, это менее навязчиво), как вы увидите далее. Другое преимущество в том, что вы можете обновить расширение без пересборки PHP.
Note
Если вам нужна информация о различии между расширениями и Zend-расширениями, вы можете заглянуть в соответствующую главу.
Установка расширений из PECL¶
PECL, PHP Extension Community Library, предлагает большое количество расширений для PHP. Когда расширения удаляются из основного дистрибутива PHP, они обычно продолжают существовать в PECL. Аналогично, многие расширения, которые сейчас поставляются в комплекте с PHP, ранее были расширениями PECL.
Если вы указали --with-pear на этапе конфигурации вашей сборки PHP, make install загрузит и установит PECL как
часть PEAR. Вы найдёте скрипт pecl в директории $PREFIX/bin. Теперь установка расширений сводится к простому
запуску pecl install EXTNAME, например:
~/myphp> bin/pecl install apcu
Эта команда загрузит, скомпилирует и установит расширение APCu. Результатом будет файл apcu.so в вашей директории
расширений, который затем можно загрузить, передав ini-опцию extension=apcu.
Хотя pecl install очень удобен для конечного пользователя, разработчикам расширений он мало интересен. Далее мы
опишем два способа собрать расширения вручную: либо путём импорта в основное дерево исходного кода PHP (это позволяет
статическую линковку), либо путём внешней сборки (только разделяемая).
Добавление расширений в дерево исходного кода PHP¶
Между сторонним расширением и расширением, поставляемым в комплекте с PHP, нет фундаментальной разницы. Поэтому собрать внешнее расширение можно просто скопировав его в дерево исходного кода PHP и затем воспользовавшись обычной процедурой сборки. Продемонстрируем это на примере APCu.
Прежде всего вам нужно поместить исходный код расширения в директорию ext/EXTNAME вашего дерева исходного кода
PHP. Если расширение доступно через git, это делается так же просто, как клонирование репозитория внутри ext/:
~/php-src/ext> git clone https://github.com/krakjoe/apcu.git
В качестве альтернативы можно также загрузить исходный tar-архив и распаковать его:
/tmp> wget http://pecl.php.net/get/apcu-4.0.2.tgz
/tmp> tar xzf apcu-4.0.2.tgz
/tmp> mkdir ~/php-src/ext/apcu
/tmp> cp -r apcu-4.0.2/. ~/php-src/ext/apcu
Расширение будет содержать файл config.m4, который задаёт специфичные для расширения инструкции сборки для
использования autoconf-ом. Чтобы включить их в скрипт ./configure, нужно снова запустить ./buildconf. Чтобы
убедиться, что файл configure действительно будет пересоздан, рекомендуется предварительно удалить его:
~/php-src> rm configure && ./buildconf
Теперь можно использовать скрипт ./config.nice, чтобы добавить APCu к существующей конфигурации, либо начать
заново с совершенно новой строкой configure:
~/php-src> ./config.nice --enable-apcu
# or
~/php-src> ./configure --enable-apcu # --other-options
Наконец, выполните make -jN для непосредственной сборки. Поскольку мы не использовали --enable-apcu=shared,
расширение статически линкуется в бинарный файл PHP, то есть никаких дополнительных действий для его использования не
требуется. Разумеется, вы также можете воспользоваться make install для установки полученных бинарных файлов.
Сборка расширений с помощью phpize¶
Расширения также можно собирать отдельно от PHP, используя скрипт phpize, который уже упоминался в разделе
Сборка PHP.
phpize играет роль, похожую на скрипт ./buildconf, используемый при сборке PHP: сначала он импортирует
систему сборки PHP в ваше расширение, копируя файлы из $PREFIX/lib/php/build. Среди этих файлов — php.m4
(M4-макросы PHP), phpize.m4 (который будет переименован в configure.ac внутри вашего расширения и содержит
основные инструкции сборки) и run-tests.php.
Затем phpize вызовет autoconf для генерации файла ./configure, который можно использовать для настройки
сборки расширения. Обратите внимание, что передавать ему --enable-apcu не нужно, так как это подразумевается
неявно. Вместо этого следует использовать --with-php-config, чтобы указать путь к вашему скрипту
php-config:
/tmp/apcu-4.0.2> ~/myphp/bin/phpize
Configuring for:
PHP Api Version: 20121113
Zend Module Api No: 20121113
Zend Extension Api No: 220121113
/tmp/apcu-4.0.2> ./configure --with-php-config=$HOME/myphp/bin/php-config
/tmp/apcu-4.0.2> make -jN && make install
При сборке расширений всегда следует указывать опцию --with-php-config (если у вас не единственная глобальная
установка PHP) — иначе ./configure не сможет правильно определить, под какую версию PHP и с какими флагами
собирать. Указание скрипта php-config также гарантирует, что make install переместит сгенерированный файл
.so (который можно найти в директории modules/) в правильную директорию расширений.
Поскольку файл run-tests.php также был скопирован на этапе phpize, вы можете запускать тесты расширения с
помощью make test (либо явным вызовом run-tests.php).
Также доступна цель make clean для удаления скомпилированных объектов, которая позволяет принудительно выполнить
полную пересборку расширения, если инкрементальная сборка не удалась после изменения. Кроме того, phpize предоставляет
опцию очистки через phpize --clean. Она удалит все файлы, импортированные phpize, а также файлы, созданные
скриптом ./configure.
Вывод информации о расширениях¶
Бинарный файл PHP CLI предоставляет несколько опций для отображения информации о расширениях. Вы уже знаете про
-m, которая выводит список всех загруженных расширений. С её помощью можно убедиться, что расширение загрузилось
корректно:
~/myphp/bin> ./php -dextension=apcu -m | grep apcu
apcu
Есть ещё несколько переключателей, начинающихся с --r, которые предоставляют доступ к функциональности
Reflection. Например, можно использовать --ri, чтобы вывести конфигурацию расширения:
~/myphp/bin> ./php -dextension=apcu --ri apcu
apcu
APCu Support => disabled
Version => 4.0.2
APCu Debugging => Disabled
MMAP Support => Enabled
MMAP File Mask =>
Serialization Support => broken
Revision => $Revision: 328290 $
Build Date => Jan 1 2014 16:40:00
Directive => Local Value => Master Value
apc.enabled => On => On
apc.shm_segments => 1 => 1
apc.shm_size => 32M => 32M
apc.entries_hint => 4096 => 4096
apc.gc_ttl => 3600 => 3600
apc.ttl => 0 => 0
# ...
Переключатель --re выводит список всех ini-настроек, констант, функций и классов, добавленных расширением:
~/myphp/bin> ./php -dextension=apcu --re apcu
Extension [ <persistent> extension #27 apcu version 4.0.2 ] {
- INI {
Entry [ apc.enabled <SYSTEM> ]
Current = '1'
}
Entry [ apc.shm_segments <SYSTEM> ]
Current = '1'
}
# ...
}
- Constants [1] {
Constant [ boolean APCU_APC_FULL_BC ] { 1 }
}
- Functions {
Function [ <internal:apcu> function apcu_cache_info ] {
- Parameters [2] {
Parameter #0 [ <optional> $type ]
Parameter #1 [ <optional> $limited ]
}
}
# ...
}
}
Переключатель --re работает только для обычных расширений, для Zend-расширений используется --rz. Это можно
проверить на opcache:
~/myphp/bin> ./php -dzend_extension=opcache --rz "Zend OPcache"
Zend Extension [ Zend OPcache 7.0.3-dev Copyright (c) 1999-2013 by Zend Technologies <http://www.zend.com/> ]
Как видите, это не выводит никакой полезной информации. Причина в том, что opcache регистрирует и обычное расширение,
и Zend-расширение, причём первое содержит все ini-настройки, константы и функции. Так что в этом конкретном случае
всё равно нужно использовать --re. Другие Zend-расширения делают свою информацию доступной через --rz.