本文主要介绍phpredis在window下的编译(linux编译就很简单了,直接co源码,直接make,不值得啰嗦了,嗯嗯)
项目源地址:https://github.com/nicolasff/phpredis
编译工具:vs2010
编译版本:php5.4.*(PHP_API_VERSION:20100412) + phpredis2.2.1
编译前准备工作:
-
下载php源代码:http://www.php.net/downloads.php
-
下载php5ts.lib:http://windows.php.net/download/#php-5.4(下载对应版本的zip文件,php5ts.lib在压缩文件中dev目录下)
-
下载cygwin:http://cygwin.com/install.html
-
PHP 站点中的 win32 编译工具 http://www.php.net/extra/win32build.zip。
-
PHP 使用的 DNS 解析器的源代码:http://www.php.net/extra/bindlib_w32.zip。用这个替代 win32build.zip 中的 resolv.lib。
-
下载igbinary:https://github.com/remicollet/igbinary
目录结构
+-- php
| | +-- php-5.4.*
| | | +--ext
| | | | +--phpredis
| | | | | +-- igbinary
| | | | +-- ...
| | +-- ...
| | +-- win32build
| | +-- bindlib_w32
编译步骤:
一、安装cygwin
二、生成php编译环境
-
执行php-5.4.*目录中的buildconf.bat
-
执行php-5.4.*目录中的configure.bat
-
复制php5ts.lib到php-5.4.*目录下
三、用cygwin生成phpredis工程文件
-
修改php-5.4.*/ext/ext_skel_win32.php文件中的$cygwin_path(19行)为正确配置
-
在php-5.4.*/ext目录下执行php ext_skel_win32.php --extname=phpredis(注意,如果没有配置php的环境变量,php需要写全路径)
-
复制下载好的phpredis项目源代码到php-5.4.*/ext/phpredis目录中
-
复制下载好的igbinary到项目源代码php-5.4.*/ext/phpredis/igbinary目录中
四、使用vs2010导入phpredis项目
-
打开php5.4.*/ext/phpredis目录中的redis.dsp工程文件,打开项目
-
添加php-5.4.*/ext/phpredis/目录下所有的.h和.c文件到项目中(在解决方案资源管理器中右键“redis”项目->添加->现有项,快捷键shift+alt+a)
-
在解决方案资源管理器中右键“redis”项目->选择“属性”,打开“redis属性页”
-
在“redis属性页”界面中选择“配置属性”->c/c++->预处理器,选择右边界面中的“预处理器定义”,打开预处理器管理界面,删除其中的PHP_EXPORTS、ZEND_EXPORTS、LIBZEND_EXPORTS,添加HAVE_REDIS_IGBINARY。如下图:
-
在“redis属性页”界面中选择“配置属性”->链接器->输入,选择右边界面中的附加依赖项,打开“附加依赖项”管理界面,在输入框中添加php5ts.lib和ws2_32.lib。如下图:
-
至此phpredis项目配置完成,接下来就是编译了
五、编译项目
这时候理论上是可以直接点击编译,然后一路流畅的编译通过,不过如果是一路通畅的编译通过,我就不需要写这个文章废话了,因为写php扩展编译已经有很多高人写,而且写得很详细,比这篇详细多了。
六、phpredis项目文件修改
-
删除项目文件中PHPAPI,注意这个删除可以保证项目可以编译过,而且可以在实际开发中使用,但是我不知道这个意味着什么,欢迎高人拍。
-
编译中会有报一些“error c2275: *** 将此类型用作表达式非法”,这个报错是因为这些的写法是c99的标准,而vs2010不支持c99标准。因此,需要找到对应的行,把变量的声明调整放到函数的开头部分。
-
在redis.c文件中,查找atoll(val_str)函数修改为atol(val_str)(atoll为c99标准,vc2010不支持)。
-
修改vs安装目标下的vc/include/sys/stat.inl,vc/include/malloc.h文件中,把
#ifndef _STATIC_ASSERT
#define _STATIC_ASSERT(expr) typedef char __static_assert_t[ (expr) ]
#endif
修改为
#ifndef _STATIC_ASSERT
#ifdef PHP_WIN32
#define _STATIC_ASSERT(expr) typedef char __static_assert_t[ (expr)?(expr):1 ]
#else
#define _STATIC_ASSERT(expr) typedef char __static_assert_t[ (expr) ]
#endif
#endif
项目中编译过程中常见的错误和处理方法:
-
“error LNK2001: 无法解析的外部符号 _basic_globals_id”,问题在于,没有正确执行第四步中的第3小步
-
“LINK : fatal error LNK1181: 无法打开输入文件php5ts.lib”,问题在于没有把php5ts.lib复制到正确的目录下
-
“ error LNK2019: 无法解析的外部符号 __imp__setsockopt@20,该符号在函数 _redis_sock_connect 中被引用”问题在于没有在第四步的第4小步中添加ws2_32.lib
-
“error C2491: “redis_stream_close”: 不允许 dllimport 函数 的定义”,删除对应行前的PHPAPI