Windows 下最详细的源码编译 PHP 以及 PHP 扩展

概述

我平常开发php扩展是在linux系统上,而扩展都是采用编译安装方式添加扩展,
但是由于开发php-opencv扩展的的时候有扩展的使用者问我能不能提供window的扩展dll引用文件。
所以最近在考虑支持window平台,总结一下window下开发php扩展和编译成dll的经验,

官方文档

其实php官方是有提供扩展编译成window的dll的官方文档
当时没细看官方文档,自己白捣鼓了几天。

1.环境准备

这里要细说一下环境,在官方文档中说到的环境要求,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下选择修改后,选在对应的环境安装
1.png
这样需要的环境就已经准备好了

2.编译前准备,设置构建目录

2.1 php-sdk-binary-tools

php-sdk-binary-tools是有官方提供的工具,
1.下载php-sdk-binary-tools

git clone https://github.com/Microsoft/php-sdk-binary-tools
cd php-sdk-binary-tools

2.调用启动脚本,例如我这里是php7.2,对应Visual Studio 2017 64位版本,调用phpsdk-vc15-x64.bat,
运行会发现cmd窗口开头会变成$符号。
2.png

3.运行phpsdk_buildtree批处理脚本,该脚本将创建所需的目录结构:

phpsdk_buildtree phpdev

3.png
会发现运行后在php-sdk-binary-tools中多出一个phpdev的目录
4.png

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.png

5.进入解压的php源码目录,运行phpsdk_deps -uphpsdk_deps --update --branch master,php会自动下载 需要的依赖包(php7以前需要手动下载php-dsp文件)

6.png
7.png

3.编译php

3.1 构建配置的环境

上面已经将编译前的构建准备环境好了,编译前在php-sdk-binary-tools中调用starter脚本以自动设置所需构建配置的环境phpsdk-vc15-x64.bat

3.2 执行buildconf

切换到php源码根目录,然后执行buildconf命令。
如果提示输入错误: 没有文件扩展“.js”的脚本引擎。
8.png

这里主要原因是:系统安装IDE(Dreamwear、UltraEdit、EditPlus,我之前安装phpstorm修改了)后后修改了.js文件的默认打开方式。
当想直接执行js脚本时就会出现此错误。
快捷键win + r,然后输入regedit,打开注册表编辑器,定位[HKEY_CLASSES_ROOT.js]这一项,双击默认值将其改为“JSFile”即可。如图所示:
9.png
10.png
11.png

然后就可以执行成功了

12.png

3.3 编译配置

执行以下命令进行编译php配置:

configure --disable-all  --enable-cli

注意:可以自己适当调整,参数可以使用configure --help查看,如

configure --disable-all  --enable-cli --enable-debug --with-all-shared

执行成功后会提示执行nmake
13.png

执行这一步会在main目录下生成config.w32.h文件,编译php扩展会需要用到这个文件,
所以如果是编译php扩展则执行下一步nmake,如果是只是php编译扩展可以不执行`nmake

3.4 执行nmake编译

然后执行nmake 开始编译

等待数分钟后,在php-src 目录应该够找到能够多了一个编译位数的目录(x32或x64),在目录下有 Release_TS (或者 Release_NTS 或者 Debug_TS ) 这样的目录

14.png

如果编译正常的话 这下面会有 php.exe 文件 证明编译php文件成功.

运行编译好的 php.exe -v查看是否正常运行
15.png

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,
16.png

git bash执行结果:
17.png

可以看到在源码ext目录下多了一个my_function的目录,这个就是我们刚刚使用使用ext_skel_win32.php命令出创建的初始扩展代码

18.png

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前:
22.png

4.3 编译扩展

切换回window的cmd

1.进入php-sdk-binary-tools目录使用phpsdk-vc15-x64.bat
2.切换到php源码目录,运行buildconf
3.在执行完buildconf后如果执行configure命令,会提示类似以下错误:

19.png

打开提示的文件,找到对应的行数,发现结尾多出多余的注释符号。这里可能是工具的问题,
20.png

解决方法:打开扩展源码的config.w32,找到// Otherwise, use ARG_ENABLE这句注释删除,重新运行buildconf就可以了。
注意:

  • 删除的注释是你需要编译参数的上面的注释,这里看ARG_WITH还是ARG_ENABLE,只要删除对应上面的注释即可
  • ARG_WITHARG_ENABLE不可同时开启

21.png

运行configure --help会发现多出--enable-my_function选项:

23.png

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"删除
24.png

重新开始buildconf->运行编译配置命令,可以看到编译配置成功提示Enable extensions:多出我们的扩展:
25.png

5.运行nmake命令进行编译,等待几分钟到十几分钟后,终端如果出现类似下面编译成功自己即表示编译成功
26.png

并且在源码目录下发现多了一个x64的目录,如果编译的事32位则是x86
里面有一个Release_TS(release表示非debug,相对应为debug,TS为线性安全,相对应为NTS),
里面的文件就是我们所编译的出来的php文件,并且发现有php_my_function.dll文件就是我们编译出来的扩展文件。
27.png

6.配置php.ini引用编译的扩展
进入编译好的目录,运行php.exe -v测试是否编译正常
28.png
运行php.exe --ini命令,会发现没有配置文件,并且运行php.exe -m会发现没有PHP Modules中没有我们创建的my_function扩展模块
29.png

复制源码中的php.ini-development到编译好的目录中,修改名字为php.ini,然后修改php.ini文件
原来:

; On windows:
; extension_dir = "ext"

改为:

; On windows:
extension_dir = "./"

并且:
30.png
再次运行php -m测试
31.png

7.测试
添加一个测试文件test.php

<?php

my_function_test();

然后运行编译生成的php目录\php.exe test.php
32.png

到这里window下编译php和编译php扩展就已经成功了。

迭代

  • 2018年11月17日 15:45 初稿
  • 2018年11月20日 22:26 添加最后编译php步骤
  • 2019年01月13日 14:30 编译后配置和测试

参考

本作品采用《CC 协议》,转载必须注明作者和本文链接
本帖由系统于 4年前 自动加精
《L03 构架 API 服务器》
你将学到如 RESTFul 设计风格、PostMan 的使用、OAuth 流程,JWT 概念及使用 和 API 开发相关的进阶知识。
《G01 Go 实战入门》
从零开始带你一步步开发一个 Go 博客项目,让你在最短的时间内学会使用 Go 进行编码。项目结构很大程度上参考了 Laravel。
讨论数量: 6

TS为线性安全

TS = Thread Safe = 线程安全

另外,Visual Studio 就是 Visual Studio,猜测你说的 Visual Studio C++ 应该是老版本的 Visual C++

再其次,建议安装 Community 版本,免费。

5年前 评论

@Wi1dcard 谢谢指正,环境名称是Visual C++,我把它和ide的名称搞混淆了。

5年前 评论

蛮复杂的,另外Linux下的php-opencv扩展有地址吗

5年前 评论

file
这有遇到过得吗?求指教 visual studio 2019 / 2017都试过了

4年前 评论
to-xmc (作者) 4年前

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!