很多PHPer都有尝试写PHP扩展的经历,但网上现有的扩展开发教程大都晦涩难懂,官方文档更是让人看的云里雾里。无形之中垒高了PHP扩展开发的门槛。"每个PHPer都应该抽空看一些PHP扩展的源码" 这话虽然很有道理,但PHP扩展的源码确实很难看懂。
最近我在修改tideways扩展的bug,这个扩展是当前最流行的PHP性能分析工具之一。我需要先读懂源码,然后定位到具体功能点,最后改Bug,整个过程下来也是焦头烂额。于是我想办法搭建了一套断点调试工具。
不夸张的说,这篇文章是最简洁明了的 PHP扩展开发与调试 类文章,看了这篇文章你会发现开发PHP扩展其实很简单。
一. 下载PHP源码
查看当前PHP版本
1
2
3
4
$ php -v
PHP 7.1.14 (cli) (built: Feb 7 2018 18:33:30) ( NTS )
Copyright (c) 1997-2018 The PHP Group
Zend Engine v3.1.0, Copyright (c) 1998-2018 Zend Technologies
下载PHP源码
1
2
3
$ git clone git@github.com:php/php-src.git
$ cd php-src
$ git checkout php-7.1.14
从github clone源码后记得切换到与本地一致的版本。或者直接从github下载zip包,比如我的版本是php-7.1.14,就需要下载 https://codeload.github.com/php/php-src/zip/php-7.1.14
二. 使用工具初始化扩展
PHP扩展的开发文档虽然写的一般,但提供的 ext_skel 工具还是非常人性话。
新建一个扩展
新建扩展前,我们需要为扩展程序找一个相对独立的目录,比如 /code/project/专门来存放扩展。其他目录也行,看心情来,别和官方扩展重复就行,比如mysql就不要使用了。我给扩展取的名字是layne。
1
2
3
$ cd php-src/ext/
$ ./ext_skel --extname=layne
$ mv layne /code/project/
看看扩展的文件结构
1
2
3
4
5
6
7
8
CREDITS
EXPERIMENTAL
config.m4
config.w32
layne.c
layne.php
php_layne.h
tests
自动生成的文件就几个,可以都浏览一遍。m4文件会影响编译,w32在Windows下才需用到,c和h文件是具体的扩展逻辑,php文件都是常见的PHP代码。
三. 配置调试环境
下载vscode,并安装
大名鼎鼎的编辑器,下载地址:https://code.visualstudio.com/
配置调试环境
首先用vscode打开 /code/project/layne(第二步中新建的扩展)。
1
2
$ mkdir .vscode
$ cd .vscode
.vscode目录一般会自动生成,这里为了方便就手动新建吧。这里面都放着.json的文件,vscode通过这些文件来保留用户当前的各种配置信息。我们需要新建 launch.json 和 tasks.json 文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
$ vi launch.json
{
// 使用 IntelliSense 了解相关属性。
// 悬停以查看现有属性的描述。
// 欲了解更多信息,请访问: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "php_ext_dbg",
"type": "cppdbg",
"request": "launch",
"program": "/usr/bin/php",
"args": ["/Users/sibenx/Projects/php-ext/php-xhprof/tests/test.php"],
"stopAtEntry": false,
"cwd": "${workspaceRoot}",
"environment": [],
"externalConsole": true,
"MIMode": "lldb",
"preLaunchTask": "php_ext_task"
}
]
}
launch.json 文件用来控制 调试 的相关参数。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
$ vi tasks.json
{
// See https://go.microsoft.com/fwlink/?LinkId=733558
// for the documentation about the tasks.json format
"version": "2.0.0",
"tasks": [
{
"label": "php_ext_task",
"type": "shell",
"command": "cd /Users/sibenx/Projects/php-ext/php-xhprof && sudo /usr/bin/phpize && ./configure --with-php-config=/usr/bin/php-config && make &&sudo make install",
"problemMatcher": [
"$gcc"
]
}
]
}
tasks.json 文件用来做调试前的各种初始化工作,比如编译扩展,将扩展拷贝到指定目录等等。
引入扩展
php并不会自动在 php.ini 文件中引入扩展,我们需要手动添加
1
2
$ vi /etc/php.ini
extension=layne.so
tasks.json 和 launch.json 文件中的php目录相关的配置改为自己的
点击vscode中的调试按钮
什么都不用做,10s左右会断下来。
四. 写在最后
很多教程在开始就写需要修改.m4文件,.c文件等,让很多有兴趣的开发者觉得扩展开发很高深很复杂。其实PHP本身就是一门比较实用的语言,从时间转换,字符串处理等功能就能看出来。官方提供的 ext_skel 工具也是依照这种传统,开箱即用不用改任何代码。最后配合vscode实现断点调试,写扩展可以变的很轻松。这篇文章还没有提到PHP扩展的具体代码,之后会结合实际的例子写几篇