PHP扩展开发与调试

最近在修改tideways的bug,tideways是近期最流行的PHP性能分析扩展。我开源的 xhgui-branch 主要用来展示tideways捕获到的详细数据。tideways使用c语言开发,使用到了各种PHP定义的宏,代码读起来晦涩难懂,于是我想办法搭建了一套断点调试工具。

不夸张的说,这篇文章是最简洁明了的 PHP扩展开发与调试 类文章。

Windows平台上会有细微的差异,有些步骤需要自行摸索。

一. 下载PHP源码

  1. 查看当前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
  2. 下载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的扩展开发虽然很不友好,但提供的脚手架工具还是非常人性话的。

  1. 新建一个扩展

    新建扩展前,我们需要为扩展程序找一个相对独立的目录,比如 /code/project/专门来存放扩展。其他目录也行,看心情来就好。

    1
    2
    3
    $ cd php-src/ext/
    $ ./ext_skel --extname=it2048
    $ mv it2048 /code/project/
  2. 看看代码

    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语句。所以开发PHP扩展并不难,就m4,c,h文件改来改去。

  3. 修改 config.m4 文件,设置扩展加载方式。

    1
    2
    3
    16 dnl PHP_ARG_ENABLE(foobar, whether to enable foobar support,
    17 dnl Make sure that the comment is aligned:
    18 dnl [ --enable-foobar Enable foobar support])

    取消16行和18行前面的dnl,修改后如下

    1
    2
    3
    16 PHP_ARG_ENABLE(foobar, whether to enable foobar support,
    17 dnl Make sure that the comment is aligned:
    18 [ --enable-foobar Enable foobar support])

三. 配置调试环境

  1. 下载vscode,并安装 cpptools 扩展工具

    作为程序员要是不知道vscode就真的该反思了。下载地址:https://code.visualstudio.com/

    cpptools 可在vscode中直接搜索扩展并下载安装。

  2. 配置调试环境

    首先用vscode打开 /code/project/it2048 在第二步中新建的扩展。

    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": "${workspaceFolder}",
    "environment": [],
    "externalConsole": false,
    "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 ${workspaceFolder} && /usr/bin/phpize --clean && /usr/bin/phpize && ./configure --with-php-config=/usr/bin/php-config && make && make install",
    "problemMatcher": [
    "$gcc"
    ]
    }
    ]
    }

    tasks.json 文件用来做调试前的各种初始化工作,比如编译扩展,将扩展拷贝到指定目录等等。

  3. 引入扩展

    php并不会自动在 php.ini 文件中引入扩展,我们需要手动添加

    1
    2
    $ vi /etc/php.ini
    extension=it2048.so
  4. tasks.json 和 launch.json 文件中的php目录相关的配置改为自己的

  5. 点击vscode中的调试按钮

  6. 什么都不用做,10s左右会断下来。

四. 写在最后

很多教程一来就要修改.m4文件,.c文件。会让新手觉得很高深很复杂,其实大可不必,PHP就是一门比较傻瓜的语言,舒服最重要。有问题请留言