百分百源码网-让建站变得如此简单! 登录 注册 签到领金币!

主页 | 如何升级VIP | TAG标签

当前位置: 主页>网站教程>网页制作> 编译PHP扩展的办法
分享文章到:

编译PHP扩展的办法

发布时间:09/01 来源:未知 浏览: 关键词:

从 PECL 安置扩展

PECL,PHP 扩展社区库,供给了大量的 PHP 扩展。当扩展从主 PHP 发行版中删除,它们平常还在 PECL中。一样,此刻与 PHP 绑缚一起的很多扩展之前都是 PECL 扩展。

除非你在 PHP 构建的配置步骤指定 --without-pear,不然 make install 将PECL 作为 PEAR 的一部分下载并安置。你可以在 $PREFIX/bin 名目下寻到 pecl 足本。此刻安置扩展很简便,就像运转 pecl install EXTNAME 一样,例如:

~/myphp> bin/pecl install apcu

该命令将下载、编译并安置 APCu 扩展。结果会是 apcu.so 文件在扩展名目下,可以通过传递 extension=apcu.so 配置选项来加载此文件。

虽然 pecl install 对终端会员非常利便,但扩展开发人员对它没什么乐趣。鄙人面,我们将会说明两种手动构建扩展的方式:通过将其导入主要的 PHP 源码树(同意静态链接)或通过外部构建(仅同享)。

增加扩展到 PHP 源码树

第三方扩展和绑缚在 PHP 的扩展之间没有基本上的不同。因此你可以通过复制外部扩展到 PHP 源码树,并和平常的构建历程一样来构建。我们以APCu 作为例子来演示。

第一,你要把扩展的源代码放到 PHP 源码树的 ext/EXTNAME 名目。假如扩展可通过 Git 获得,就像从 ext/ 中克隆仓库一样简便:

~/php-src/ext> git clone https://github.com/krakjoe/apcu.git

或者你也可以下载源码紧缩包并解压它:

/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。为了确保配置文件已经从新生成,倡议事先删除它:

~/php-src> rm configure && ./buildconf --force

此刻你可以使用 ./config.nice 足本将 APCu 增加到你的现有配置,或者从全新的配置行开端:

~/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 构建的足本类似:第一,通过$PREFIX/lib/php/build 复制文件导入 PHP 构建系统到你的扩展中。这些文件是 acinclude.m4(PHP 的 M4宏)、phpize.m4(它会在你的扩展中重命名为 configure.in 并包括主要的构建说明)和 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/ 名目寻到)到准确的扩展名目。

由于在 phpize 阶段还复制了 run-tests.php 文件,因此你可以使用 make test(或显示调取 run-tests)运转扩展测试。

删除已编译对象的 make clean 也是可用的,并且同意你增量构建失败时强迫从新构建扩展。 别的 phpize 供给了一个清算选项 phpize --clean。该命令将删除所有 phpize 导入的文件和通过 /configure 足本生成的文件。

显示关于扩展的信息

PHP CLI 二进制文件供给了几个选项来显示关于扩展的信息。你已经知道 -m,该命令会列出所有已经下载的扩展。你可以利用它来肯定扩展可否准确下载了:

~/myphp/bin> ./php -dextension=apcu.so -m | grep apcu
apcu

还有其他一些以 --r 开头的参数都是具有 Reflection 功效。例如,你可以使用 --ri 去显示扩展的配置:

~/myphp/bin> ./php -dextension=apcu.so --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 参数列出扩展增加的所有初始设定、常数、函数和类:

~/myphp/bin> ./php -dextension=apcu.so --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.so --rz "Zend OPcache"
Zend Extension [ Zend OPcache 7.0.3-dev Copyright (c) 1999-2013 by Zend Technologies <http://www.zend.com/> ]

如你所见, 该命令没有显示有用的信息。由于 opcache 同时注册了一般扩展和 Zend 扩展, 前者包括所有初始配置、常量和函数。因此在这个非凡的案例中,你依然需要使用 --re。其他 Zend 扩展通过 --rz 可得到信息。

扩展 API 兼容性

扩展对5个主要因素非常敏锐。假如它们不适宜,则该扩展将不会加载到 PHP中,并将无用:

  • PHP Api 版本
  • Zend 模块 Api 编号
  • Zend 扩展 Api 编号
  • 调试模式
  • 线程平安

phpize 工具可让你回想它们的一些信息。所以,假如你在调试模式下构建 PHP,并试图加载和使用非调试模式构建的扩展,那它将没法工作。其他检查也一样。

PHP Api 版本 是内部 API 版本号,Zend 模块 Api 编号Zend 扩展 Api 编号 离别与 PHP 扩展和 Zend 扩展 API 有关。

那些编号随后作为 C 宏传递给正在构建的扩展,以便它本身可以检查那些参数,并在 C 预处置器 #ifdef 的根基上采纳不一样的代码途径。当那些编号作为宏传给扩展代码,它们会被写在扩展构造中,以便你每次尝试在 PHP 二进制文件中加载该扩展时,都将对比 PHP 二进制文件本身的编号停止检查。假如不匹配,那么该扩展不会被加载,并显示一条错误信息。

假如我们看一下扩展的 C 构造,它看起来像这样:

zend_module_entry foo_module_entry = {
    STANDARD_MODULE_HEADER,
    "foo",
    foo_functions,
    PHP_MINIT(foo),
    PHP_MSHUTDOWN(foo),
    NULL,
    NULL,
    PHP_MINFO(foo),
    PHP_FOO_VERSION,
    STANDARD_MODULE_PROPERTIES
};

至今,对我们来说有味的是 STANDARD_MODULE_HEADER 宏。假如我们扩展它,我们可以看到:

#define STANDARD_MODULE_HEADER_EX sizeof(zend_module_entry), ZEND_MODULE_API_NO, ZEND_DEBUG, USING_ZTS
#define STANDARD_MODULE_HEADER STANDARD_MODULE_HEADER_EX, NULL, NULL

留意 ZEND_MODULE_API_NOZEND_DEBUGUSING_ZTS 是怎样使用的。

假如查看 PHP 扩展的默许名目,它应当像 no-debug-non-zts-20090626。如你所料,该名目由不一样的部分组成:调试模式,其次是线程平安信息,然后是Zend 模块 Api 编号。所以默许状况下,PHP 试图帮你阅读扩展。

留意

平常,当你成为一位内部开发人员或扩展开发人员,必需使用调试参数,并且假如必需处置 Windows 平台,线程也会显示出来。你可以针对那些参数的多种状况屡次编译统一扩展。
记住,每次新的 PHP 主要/次要版本都会更换参数,比方 PHP Api 版本,这就是为什么你需要针对新的 PHP 版本从新编译的缘由。

> /path/to/php70/bin/phpize -v
Configuring for:
PHP Api Version:         20151012
Zend Module Api No:      20151012
Zend Extension Api No:   320151012

> /path/to/php71/bin/phpize -v
Configuring for:
PHP Api Version:         20160303
Zend Module Api No:      20160303
Zend Extension Api No:   320160303

> /path/to/php56/bin/phpize -v
Configuring for:
PHP Api Version:         20131106
Zend Module Api No:      20131226
Zend Extension Api No:   220131226

留意

Zend 模块 Api 编号 本身是使用 年 月 日 的日期格局构建。这是 API 更换和并被标志的日期。Zend 扩展 Api 编号 是 Zend 版本,其次是 Zend 模块 Api 编号

留意

数字太多?是的,一个 API 编号绑定一个 PHP 版本,对任何人来说都足够了,并且可以简化对 PHP 的懂得。不幸的是,除了 PHP 版本本身,还增添了3种不一样的 API 编号。你应当寻哪一个?答案是任何一个:当 PHP 版本演化时,它们三种同时演化。由于历史缘由,我们有三种不一样编号。

但是,你是一位 C开发人员,不是吗?为什么不按照这些数字构建一个“兼容的”头文件?我们在我们的扩展中使用了相似这些:

#include "php.h"
#include "Zend/zend_extensions.h"

#define PHP_5_5_X_API_NO            220121212
#define PHP_5_6_X_API_NO            220131226

#define PHP_7_0_X_API_NO            320151012
#define PHP_7_1_X_API_NO            320160303
#define PHP_7_2_X_API_NO            320160731

#define IS_PHP_72          ZEND_EXTENSION_API_NO == PHP_7_2_X_API_NO
#define IS_AT_LEAST_PHP_72 ZEND_EXTENSION_API_NO >= PHP_7_2_X_API_NO

#define IS_PHP_71          ZEND_EXTENSION_API_NO == PHP_7_1_X_API_NO
#define IS_AT_LEAST_PHP_71 ZEND_EXTENSION_API_NO >= PHP_7_1_X_API_NO

#define IS_PHP_70          ZEND_EXTENSION_API_NO == PHP_7_0_X_API_NO
#define IS_AT_LEAST_PHP_70 ZEND_EXTENSION_API_NO >= PHP_7_0_X_API_NO

#define IS_PHP_56          ZEND_EXTENSION_API_NO == PHP_5_6_X_API_NO
#define IS_AT_LEAST_PHP_56 (ZEND_EXTENSION_API_NO >= PHP_5_6_X_API_NO && ZEND_EXTENSION_API_NO < PHP_7_0_X_API_NO)

#define IS_PHP_55          ZEND_EXTENSION_API_NO == PHP_5_5_X_API_NO
#define IS_AT_LEAST_PHP_55 (ZEND_EXTENSION_API_NO >= PHP_5_5_X_API_NO && ZEND_EXTENSION_API_NO < PHP_7_0_X_API_NO)

#if ZEND_EXTENSION_API_NO >= PHP_7_0_X_API_NO
#define IS_PHP_7 1
#define IS_PHP_5 0
#else
#define IS_PHP_7 0
#define IS_PHP_5 1
#endif

看见了?

或者更简便(更好)的是使用 PHP_VERSION_ID ,这你大概更熟知:

#if PHP_VERSION_ID >= 50600
打赏

打赏

取消

感谢您的支持,我会继续努力的!

扫码支持
扫码打赏,你说多少就多少

打开支付宝扫一扫,即可进行扫码打赏哦

百分百源码网 建议打赏1~10元,土豪随意,感谢您的阅读!

共有160人阅读,期待你的评论!发表评论
昵称: 网址: 验证码: 点击我更换图片
最新评论

本文标签

广告赞助

能出一分力是一分吧!

订阅获得更多模板

本文标签

广告赞助

订阅获得更多模板