官方文档
php官方提供扩展编译成 window 的 dll 的官方文档,
1. 环境准备
Visual C++ 14.0 (Visual Studio 2015) for PHP 7.0 or PHP 7.1.
Visual C++ 15.0 (Visual Studio 2017) for PHP 7.2 or PHP 7.3.
Visual C++ 16.0 (Visual Studio 2019) for PHP 7.4.
在官方文档中说到的环境要求,Visual Studio 环境可以直接用 Visual Studio ide 进行安装,
不是指Visual C++ ,所以运行 phpsdk-vc15-x64 会出现 Could not deternine 'vc15' directory 的错误,
php 编译成 dll 的环境可以使用这个 ide 进行安装
1.1 安装 Visual Studio(IDE)
到官网下载 Visual Studio Install
1.2 添加编译环境
在 Visual Studio Professional 2017 下选择修改后,选在对应的环境安装
这样需要的环境就已经准备好了
2. 编译前准备,设置构建目录
2.1 php-sdk-binary-tools
php-sdk-binary-tools 是有官方提供的工具,1. 下载 php-sdk-binary-toolsgit clone https://github.com/Microsoft/php-sdk-binary-tools
cd php-sdk-binary-tools
下载需要编译拓展的对应php版本的源码
2. 调用启动脚本,例如我这里是 php7.2,对应 Visual Studio 2017 64 位版本,调用 phpsdk-vc15-x64.bat,运行会发现 cmd 窗口开头会变成 $ 符号。
3. 运行 phpsdk_buildtree 批处理脚本,该脚本将创建所需的目录结构:phpsdk_buildtree phpdev
会发现运行后在 php-sdk-binary-tools 中多出一个 phpdev 的目录
phpsdk_buildtree 脚本将根据当前使用的 VC ++ 版本创建路径,并切换到新创建的目录
4. 将 PHP 源代码解压缩到,其中:F:\www\php-sdk-binary-tools\phpdev\vc##\x##,在解压缩 PHP 源的同一目录中,有一个 deps 目录。vc##是您正在使用的编译器版本(eq vc15)
x##是你的构建的系统位数(x86 或 x64)
例如我这里是: F:\www\php-sdk-binary-tools\phpdev\vc15\x64\php-7.2.12-src
5. 进入解压的 php 源码目录,运行 phpsdk_deps -u 或 phpsdk_deps --update --branch master,php 会自动下载 需要的依赖包 (php7 以前需要手动下载 php-dsp 文件)(php7+本步骤可省略,5.6未测试)
3. 编译 php
3.1 构建配置的环境
上面已经将编译前的构建准备环境好了,编译前在 php-sdk-binary-tools 中调用 starter 脚本以自动设置所需构建配置的环境 phpsdk-vc15-x64.bat,
3.2 执行 buildconf
切换到 php源码根目录,然后执行 buildconf 命令。如果提示输入错误: 没有文件扩展“.js”的脚本引擎。
这里主要原因是:系统安装 IDE(Dreamwear、UltraEdit、EditPlus,我之前安装 phpstorm 修改了)后后修改了.js 文件的默认打开方式。当想直接执行 js 脚本时就会出现此错误。快捷键 win + r,然后输入 regedit, 打开注册表编辑器,定位 [HKEY_CLASSES_ROOT.js] 这一项,双击默认值将其改为 “JSFile” 即可。如图所示:
然后就可以执行成功了
3.3 编译配置
执行以下命令进行编译 php 配置:configure --disable-all --enable-cli
注意:可以自己适当调整,参数可以使用 configure --help 查看,如configure --disable-all --enable-cli --enable-debug --with-all-shared
执行成功后会提示执行 nmake
执行这一步会在 main 目录下生成 config.w32.h 文件,编译 php扩展会需要用到这个文件,所以如果是编译 php 扩展则执行下一步 nmake,如果是只是 php 编译扩展可以不执行 `nmake
3.4 执行 nmake 编译
然后执行 nmake 开始编译
等待数分钟后,在 php-src 目录应该够找到能够多了一个编译位数的目录(x32 或 x64),在目录下有 Release_TS (或者 Release_NTS 或者 Debug_TS ) 这样的目录
如果编译正常的话 这下面会有 php.exe 文件 证明编译 php 文件成功.
运行编译好的 php.exe -v 查看是否正常运行
4. 编译 php 扩展
4.1 创建 php 扩展
如果我们只是编译某些已经开放好的扩展源码,可以不用运行这一步,这里创建一个 demo 扩展进行编译。使用 git bash 进入到源码的地址\ext 目录,执行:php.exe ext_skel_win32.php --extension=my_function
注:这里为什么要使用 git bash 工具,是因为 git bash 自带模拟 linux 环境,my_function 为我这里需要创建的扩展,具体可以根据自己更改执行工具创建时不是提示'sh' is not recognized as an internal or external command,
git bash 执行结果:
可以看到在源码 ext 目录下多了一个 my_function 的目录,这个就是我们刚刚使用使用 ext_skel_win32.php 命令出创建的初始扩展代码
4.2 修改源码
1. 我们编辑 my_function 下的 my_function.c 文件。添加一个方法 my_function_test 方法,代码如下:PHP_FUNCTION(my_function_test) {
php_printf("This is my function PHP extension! \n");
}
2. 然后将 PHP_FE(my_function_test, NULL) 添加到 const zend_function_entry my_function_functions[]中,但要放在 PHP_FE_END 前:
4.3 编译扩展
切换回 window 的 cmd
1. 进入 php-sdk-binary-tools 目录使用 phpsdk-vc15-x64.bat2. 切换到 php 源码目录,运行 buildconf3. 在执行完 buildconf 后如果执行 configure 命令,会提示类似以下错误:(字符)
打开提示的文件,找到对应的行数,发现结尾多出多余的注释符号。这里可能是工具的问题,
解决方法:打开扩展源码的 config.w32,找到 // Otherwise, use ARG_ENABLE 这句注释删除,重新运行 buildconf 就可以了。(此方法不友好,不如直接按照上图删掉最后的*/,省事)注意:删除的注释是你需要编译参数的上面的注释,这里看 ARG_WITH 还是 ARG_ENABLE,只要删除对应上面的注释即可
ARG_WITH 和 ARG_ENABLE 不可同时开启
运行 configure --help 会发现多出 --enable-my_function 选项:
4. 运行 configure --disable-all --enable-cli --enable-my_function=shared 进行编译配置:
发现报错提示:F:\www\php-sdk-binary-tools\phpdev\vc15\x64\php-7.2.12-src\configure.js(5490, 2) Microsoft JScript 运行时错误: 'PHP_EXTNAME_SHARED' 未定义
解决办法:重新打开扩展的 config.w32 文件,将下图 , PHP_EXTNAME_SHARED, "/DZEND_ENABLE_STATIC_TSRMLS_CACHE=1" 删除
重新开始 buildconf-> 运行编译配置命令,可以看到编译配置成功提示 Enable extensions: 多出我们的扩展:
5. 运行 nmake 命令进行编译,等待几分钟到十几分钟后,终端如果出现类似下面编译成功自己即表示编译成功
并且在源码目录下发现多了一个 x64 的目录,如果编译的事 32 位则是 x86,里面有一个 Release_TS(release 表示非 debug,相对应为 debug,TS 为线性安全,相对应为 NTS),里面的文件就是我们所编译的出来的 php 文件,并且发现有 php_my_function.dll 文件就是我们编译出来的扩展文件。
6. 配置 php.ini 引用编译的扩展进入编译好的目录,运行 php.exe -v 测试是否编译正常
运行 php.exe --ini 命令,会发现没有配置文件,并且运行 php.exe -m 会发现没有 PHP Modules 中没有我们创建的 my_function 扩展模块
复制源码中的 php.ini-development 到编译好的目录中,修改名字为 php.ini,然后修改 php.ini 文件原来:; On windows:; extension_dir = "ext"
改为:; On windows:extension_dir = "./"
并且:
再次运行 php -m 测试
7. 测试添加一个测试文件 test.php<?phpmy_function_test ();
然后运行编译生成的php目录\php.exe test.php
到这里 window 下编译 php 和编译 php 扩展就已经成功了。