在Windows下给PHP装扩展的难度不怎么好衡量。要说难的话,流行的扩展一般都有编译好的库,下回来用就是,方便的很;要说简单的话,下载扩展的PHP版本、线程安全设置、调试设置、编译器版本都要符合才能用,然后从VC11(VS 2012)开始PHP 5.4、5.5又有了32位和64位的分别……就算像Xdebug这样的流行扩展,也得防着一不留神下错了文件——当然,这只是略麻烦一点,不过对于一些不怎么流行的扩展,在Windows上安装还真是不简单的活:嗯,最麻烦的就是,你得自己编译。

在Windows下编译PHP和扩展比*nix下麻烦很多。在*nix下,你需要的只是“phpize”、“./configure –enable-XXX”、“make”——在Windows下可没有phpize这么好用的东西。

需要的文件

  • 编译器。这里以VC++ 11(Visual Studio 2012)为例,它可以编译PHP 5.5(官方支持)和5.4(可用)。对应地,VC++ 9(Visual Studio 2008 SP1,需要Windows SDK 6.1)可以编译PHP 5.4(官方支持)和5.3(官方支持)。PHP的官方Wiki上有详细的编译器支持列表(英文)。
  • PHP源代码。推荐从官网下载。
  • PHP SDK。需要从这里下载两个压缩包:deps-5.5-vc11-x86.7z(下载对应版本的依赖包)和 php-sdk-binary-tools-20110915.zip(sdk,有更新的文件可以下新的)。
  • PHP扩展的源码和依赖文件,如果你需要编译PHP扩展。

编译步骤

1. 准备工作文件夹

把压缩包php-sdk-binary-tools-20110915.zip的内容解压到一个文件夹,例如 D:\php-sdk\。
打开“VS2012 x86 Native Tools Command Prompt”,cd到刚刚建立的文件夹,执行以下命令:

bin\phpsdk_setvars.bat
bin\phpsdk_buildtree.bat phpdev

把D:\php-sdk\phpenv\下的vc9文件夹复制一份,重命名为vc11。(不复制直接改名也可以,或者直接在vc9里面编译应该也没问题。)现在你应该有了一个类似这样的文件夹结构:

D:\php-sdk\
 |--bin\
 |--phpdev\
 |   |--vc6\
 |   |--vc8\
 |   |--vc9\
 |   |   |--x64\
 |   |   |--x86\
 |   |       |--deps\
 |   |--vc11\
 |       |--x64\ 
 |       |--x86\
 |           |--deps\
 |               |--bin\
 |               |--include\
 |               |--lib\
 |--script\
 |--share\

把依赖包deps-5.5-vc11-x86.7z解压到D:\php-sdk\phpenv\vc11\x86\,将其中的deps文件夹与现有的deps文件夹合并。这个文件夹用来放置编译PHP和扩展需要的依赖文件,包括库文件、头文件甚至是依赖的二进制文件。
把php的源代码压缩包的内容解压到D:\php-sdk\phpenv\vc11\x86\,得到一个类似D:\php-sdk\phpdev\vc11\x86\php-5.5.3-src\的文件夹。

2. 生成configure脚本

cd到D:\php-sdk\phpdev\vc11\x86\php-5.5.3-src\,执行以下命令:

buildconf

3. 配置编译选项

使用–help查看可用的选项。下面是一个我用的开启了大多数PHP自带扩展的命令。

configure --help
configure --enable-cli-win32 --with-bz2 --with-curl --with-dba --enable-fileinfo --with-gettext --with-gmp --with-ldap --enable-mbstring --enable-mbregex --with-mcrypt --with-openssl --with-pgsql --enable-sockets --with-sqlite3 --with-config-file-scan-dir --with-tidy --enable-exif --with-mysql --with-mysqli --enable-pdo --with-pdo-mysql --with-pdo-pgsql --with-pdo-sqlite --enable-soap --with-xmlrpc --with-xsl

4. 编译PHP

运行下面两条命令,编译PHP、生成zip压缩包。

nmake
nmake snap

最后在D:\php-sdk\phpdev\vc11\x86\php-5.5.3-src\Release_TS\下得到一个压缩包php-5.5.3-Win32-VC11-x86.zip,即是我们编译并打包好的PHP。把这个压缩包解压到别处即可开始使用;如果运行时提示需要某dll,一般在D:\php-sdk\phpdev\vc11\x86\deps\bin\下面可以找到它。
我按照上面的配置参数,打包了一份可用的PHP 5.3.3,可以到我的SkyDrive下载。相关的配置命令和phpinfo可以在这里查看。

5. 编译PHP扩展

PHP扩展的编译方式和PHP的编译方式大同小异。
首先确定扩展的源代码和依赖文件已经正确放在了相关文件夹。扩展的源代码文件夹需要放在D:\php-sdk\phpdev\vc11\x86\php-5.5.3-src\ext\下,依赖文件的位置和编译PHP时相同。
然后清理一下上次编译的工作文件夹,因为我们要调整配置选项(–force选项可以不带)。

nmake clean
buildconf --force
configure --help

这次我要编译的是PHP扩展test_helpers,一个添加了一些用于测试的函数的扩展。比如说,通过这个扩展,你可以重载exit()、die()系统函数和new关键字,在为一些遗留代码编写测试时非常好用。
选项 --enable-test_helpers
可以看到,buildconf之后,configure –help输出的选项里已经有了–enable-test_helpers。

configure --disable-all --enable-cli --enable-test_helpers=shared
nmake

我禁用了所有的其他扩展,只保留了命令行(CLI)的SAPI。标记为shared表示编译动态链接库,与static相对。
在configure输出的末尾是当前编译配置的状态:
编译配置的状态
编译出来的文件同样在Release_TS文件夹下。和我们需要的扩展有关的是四个文件:php_test_helpers.dll,php_test_helpers.dll.res,php_test_helpers.exp和php_test_helpers.lib。
复制php_test_helpers.dll到你的PHP的ext目录,修改你的php.ini,添加extension=php_test_helpers.dll,再执行一下php -m看一下加载的模块:
PHP当前加载的扩展
可以看出……test_helpers已经加载了。

这儿有个问题,这样编译出来的php_test_helpers.dll不能作为Zend Extension被加载——在Ubuntu下是可以的,我还没搞清楚原因,调查中……有了结果我再来更新这段。根据作者Sebastian Bergmann(牛人啊,也是phpunit的作者)的说明,由于都重载了ZEND_NEW的关系,test_helpers和Xdebug(等类似扩展)有些兼容问题,workaround是作为Zend Extension并且在Xdebug之后加载。下图展示了在Ubuntu上开启了workaround和在Windows上未开启workaround的phpinfo()信息。
在Ubuntu上开启了workaround的phpinfo()信息
在Windows上未开启workaround的phpinfo()信息
我打包了一份编译出来的test_helpers,可以到我的SkyDrive下载(为PHP 5.5-线程安全-VC11-非调试发布版本-32位而编译,其他版本不保证可用)。下载之后可以跑一下我的TestHelpers.php项目里面的示例和单元测试来验证。 (由于上文所述的原因,执行单元测试时请禁用代码覆盖率检测和Xdebug。)

参考