2018-02-02 配置Windows下开发PHP扩展
写在前头
这个配置是基于windows的IIS部署php的情况下,开发php的扩展,编译出dll文件,供应php中代码可用function。
通过2天在baidu来回折腾,终于自己摸索出了工作方案,记录备忘,也可以被其他程序员参考 。
baidu上的内容,实在太模糊了,写到重点都没有。
关键要素
- 服务器OS:windows,开发机是windows10
- http服务:IIS
- php版本:VC14编译php7.1.*,x64,nts
- vs2015的开发IDE
环境是什么,决定了用什么方式进行开发,所以必须要想明白自己的环境状态。因为编译的扩展需要和编译的php主程序匹配,否则扩展是不能使用的。
要素 | 值 | 说明 |
---|---|---|
php版本 | 7.1.7 | 从微软的iis express上下载的,参考微软的start sql server by php on windows |
编译器 | VC14 | 使用vs2015 c++编译器 |
线程安全 | no | 非线程安全,匹配IIS上fast cgi的php版本都是NTS的编译的php |
编译环境 | X64 | 在64位环境中编译的可执行程序 |
环境准备
安装cygwin
下载地址:https://cygwin.com/install.html;
可以考虑在安装之后加载bison,因为php的编译过程可以使用。不安装也可以,php上下载的编译工具中自带。
安装vs2015 c++的开发IDE
实际不需要IDE,但是考虑到微软的东西,还是打包下载的比较保险。
vs2015中必须有C++的编译器即可。其他都不用。
我测试使用vs2017,但是编译后出问题,还是倒回vs2015,编译后可以使用。
部署php的sdk
下载地址:http://windows.php.net/downloads/php-sdk/
我使用了:deps-7.1-vc14-x64,php编译的依赖包。
还需要使用:php-sdk-binary-tools-20110915,注意是老版本了,没有具体的新版本,实际也可以用。
部署php的源代码
下载地址:http://windows.php.net/downloads/releases/
我使用了:php-7.1.2-src,虽然运行的php是7.1.7,但是实际测试,源码的版本只要小版本一致即可。根据php.net的说法,使用高版本的php源码是没有问题的。还没有时间做测试。
维护工作目录
- 解压php-sdk-binary-tools-20110915,形成一个tools目录
- 解压php源码,形成php7.1src目录
- 自建dev目录,届时可以存放扩展的代码
配置OS的PATH
- 配置php的运行目录,这样可以cmd中执行php.exe
- 配置tools目录
- 配置源码目录,因为编译过程需要使用源码内的一些bat
工作步骤
复制必要的文件到工作目录
- 使用VS2015的cmd工具
我的运行环境是php的x64nts,因此选择x64的cmd工具。在cmd中进入tools目录(解压php-sdk-binary-tools-20110915) - 执行tools的环境预设
cd bin
phpsdk_setvars.bat
phpsdk_buildtree.bat extdev
extdev是一个工作目录,这个可以自己定义,我这里就用这个。执行后,会在tools的并排目录里创建好extdev目录,内含多个vc**的目录。
由于工具是2011年的,因此没有VC14,需要自己维护一个VC14,再创建一个x64目录。虽然应该也配套建设x86,但是我的运行php的x64的,因此x86就不必了。
另外extdev的目录工具只是产生一套规范目录,与开发其实没有硬关系。可以cd..后做,也可以不用做。
-
创建deps环境
将deps-7.1-vc14-x64的压缩包内容,添加到x64下。
实际操作感觉,也无所谓工作目录那么严谨也一样可以编译php扩展。但是严谨的工作目录是个好习惯。 -
复制源码
将源码包解压到x64中,形成php714-src的目录。
最终形成了我的工作环境目录:
D:
| -- work
| -- php_sdk_tool // 解压php-sdk-binary-tools-20110915
| -- extdev // 运行phpsdk_buildtree.bat extdev之后得到
| -- vc14 // 自建
| -- x64 // 自建
| -- deps // 解压deps-7.1-vc14-x64
| -- php714-src // 解压php714的源码,编译需要的configure.js等都在这里,这个是执行编译命令的目录
| -- ext // php标准扩展目录
| -- myext // 执行php ext_skel_win32.php --extname=myext之后php创建,自开发扩展源码就在这里,.32配置文件在这里
| -- x64 // 64位编译结果输出
| -- Release // 编译非线程安全的输出,这里可以找到编译结果php_myext.dll,如果编译发生LKN,php7.lib复制到这里重新编译
| -- Release_TS // 编译线程安全的输出,结果dll在这里
| -- Release // 32位扩展的编译输出,应该是非线程安全,我没有测试过,逻辑推测
生成程序模板
到php714-src中,cd到ext目录,找到对应的win32的开发配置php程序,修改cygwin的bin路径。(在windows开发就是这样麻烦,linux中应该不用吧?)
cd..
cd php714-src
cd ext
vim ext_skel_win32.php
//$cygwin_path设置为你当前cygwin安装目录的bin目录。
php ext_skel_win32.php --extname=%your extension name% // eg : myext
这个操作完成后,会在ext的目录下,出现%your extension name% (myext)的文件夹。就是php工具创建的扩展空模板。修改代码,再编译,就可以完成扩展的开发。
cd %your extension name% // eg : myext
进入自己的扩展目录,其中有2个配置文件需要修改(参考php ext_skel_win32.php 执行后的说明也可以明白)。
一个是linux系统中需要的*.m4的配置,一个是windows系统的.w32文件配置。
我们这里修改.w32的文件。将一下被注释的代码复原:
ARG_ENABLE("myext", "enable myext support", "no");
编译程序配置
然后回到源码目录,执行配置程序的创建工作。
cd..
buildconf --force
configure --help
通常操作第一步后,如果成功,会提示你操作第二步。
这个时候,系统会提示有configure.js的某行代码出错,直接vim去修改这行代码,一般是末尾的注释需要修正:
ARG_ENABLE("myext", "enable myext support", "no"); */ -- 就是这个地方
然后再次执行configure --help。可以查看配置的功能清单。重点关注自己的myext是否存在,还有诸如zts功能(线程安全与否的开关)。
执行扩展编译
在cmd中继续执行命令
configure --disable-all --enable-cli --disable-zts --enable-myext=shared
// ^ 关闭其他功能 ^ 编译非线程安全
nmake
如果要编译线程安全的,则不需要--disable-zts
根据提示应该继续执行nmake。
期间可能会出现若干错误,一般都是环境配置的问题:
- 使用vs2015 x64的命令行可以减少诸如cl.exe、link.exe的问题
- 编译器报告lnk的问题,基本都是php7.lib的文件不到位的问题。可以从php的运行系统中,在php的目录dev中找到这个文件,复制到编译工作目录:php714\src\x64\release\
- 正常情况下,编译完成后,会在源码目录中出现对应的输出目录:release(对应x86的编译)和x64(对应x64的编译)。而x64又出现Release_TS和Release目录,分别对应线程安全和非线程安全。
测试使用
将编译后的输出,本次是php714\src\x64\release\中的php_myext.dll复制到php的运行环境,并配置ini。
在cmd中执行php代码,就可以查看到extension是否成功加载。如果加载有问题,会马上有警告。
- 警告模块不是扩展模块:可能编译器不正确,比如php714使用VC14,而编译扩展使用了不匹配的
- 警告不是有效的win32,则运行php的位数和扩展编译的位数不匹配,即运行php的版本和扩展编译的版本应该都是对应x86或x64
- 警告找不到模块:可能是运行的php的线程安全与编译的线程安全开关不匹配。
测试方式:
php -r "phpinfo();"
php -r "echo confirm_myext_compiled(0);"
为了方便查看,在phpinfo制作一个php文件通过http访问也可以看到扩展myext的加载。
注意事项
从baidu上其他的使用vs2015引入扩展目录创建工程,我没有操作成功。多半都是编译环境的问题,我发现百度的内容基本都是php5的,php7很少。估计php7升级到这个版本后,扩展的开发有了变化,因此我怎么也没有成功。(实际是成功编译了dll,但是php不认这个dll)。不过使用vs2015开一个工程,对于开发调试还是很有帮助的。