简言之,BPC 可以将 PHP 代码最终转译成 C 语言,然后编译成动态链接库或者可执行程序,实现 PHP Native AOT!
0. 前置说明
本文所述的所有操作都是在 Ubuntu 18.04 amd64 上完成的,但这并不是说 BPC 只能在 Ubuntu 18.04 上运行.
BPC 编译器自身已验证过可以在 Ubuntu 18.04 / 20. 04 / 22.04 上运行,编译结果还可以在 Debian 12 上运行, 参看 wordpress 的例子.
1. 快速体验二进制版的 webman
[ol]
下载编译好的二进制文件 start
加上可执行权限 chmod +x start
运行 mkdir /tmp/x && mv start /tmp/x && cd /tmp/x && ./start start
另外打开一个终端
~$ tree /tmp/x/
/tmp/x/
├── runtime
│ ├── logs
│ │ └── workerman.log
│ ├── views
│ └── webman.pid
└── start
3 directories, 3 files
访问以下 url 查看效果
[/ol]
2. 亲自动手编译 webman
[ol]
参看文档下载安装 BPC
~$ bpc
bpc/6.4.0
Usage: bpc [options] [-- script args]
see bpc -h for help with command line options
下载安装 phptobpc 来解决 BPC 不支持的语法特性
phptobpc 就是个 phar 文件,下载回来后加上可执行权限,放到 ~/bin/ 或者 /usr/local/bin/ 目录下即可.
由于是 phar 文件,当然需要 php 解释器,sudo apt install php-cli 即可.
~$ phptobpc
Usage: php phptobpc.php file.php
参照以下 git repo README.md 开头的 BPC Notes 编译安装 webman 依赖
[ol]
[/ol]
结果如下:
~$ cd /usr/local/lib/
/usr/local/lib$ ls *psr*
libpsr-container_u-4.4a.a libpsr-log_u-4.4a.a psr-container.heap psr-log.heap
libpsr-container_u-4.4a.so libpsr-log_u-4.4a.so psr-container.sch psr-log.sch
/usr/local/lib$ ls *fastroute*
fastroute.heap fastroute.sch libfastroute_u-4.4a.a libfastroute_u-4.4a.so
/usr/local/lib$ ls *monolog*
libmonolog_u-4.4a.a libmonolog_u-4.4a.so monolog.heap monolog.sch
/usr/local/lib$ ls *workerman*
libworkerman_u-4.4a.a libworkerman_u-4.4a.so workerman.heap workerman.sch
/usr/local/lib$ ls *webman*
libwebman_u-4.4a.a libwebman_u-4.4a.so webman.heap webman.sch
编译运行 webman
~$ git clone [email protected]:heguangyu5/bpc-webman.git
~$ cd bpc-webman/
~/bpc-webman$ make
...
output prologue
generate main.c
generate build.ninja
run ninja
[34/34] link ../start (statically linked)
mv start ../
make[1]: Leaving directory '~/bpc-webman/build'
~/bpc-webman$ ./start start
Workerman[./start] start in DEBUG mode
--------------------------------------------- WORKERMAN ----------------------------------------------
Workerman version:4.1.10 PHP version:7.2.19-bpc Event-Loop:\Workerman\Events\Event
---------------------------------------------- WORKERS -----------------------------------------------
proto user worker listen processes status
tcp hgy webman http://0.0.0.0:8787 16 [OK]
------------------------------------------------------------------------------------------------------
Press Ctrl+C to stop. Start success.
[/ol]
4. 关于 webman 代码调整的说明
webman-framework
[ol]
src/App.php 不支持依赖注入
依赖注入需要获取到 callback 或者 controller 每个 method 的参数的详细信息,BPC 目前不提供这些信息,所以依赖注入部分的代码都给注释掉了, @see src/App.php#L322
src/Context.php 简化实现
BPC 尚未实现SplObjectStorage, 所以临时使用一个array替代了原来的代码
src/support/App.php Worker::$eventLoopClass 固定为 \Workerman\Events\Event, 不可配置
src/App.php::getController() 要求目录及文件名全部小写.
编译成二进制后,目录和文件的概念都没有了,所以也就不能 scanDir 了,根据 url 找到 controller 的逻辑必须固定下来,不能 scanDir+strtolower 来实现.
src/Config.php src/Route.php src/support/App.php 和第 4 点一样,由于不能 scanDir,config 文件必须想个办法明确列出来.
[/ol]
webman
[ol]
[/ol]
5. 下一步: 如何编译我自己的项目?
参看 webman Makefile 里的编译命令:
bpc -v \
--static \
-c bpc.conf \
-u psr-log \
-u psr-container \
-u fastroute \
-u monolog \
-u workerman \
-u webman \
-d display_errors=on \
--input-file src.list
将你项目的外部依赖像 psr-log/container, fastroute, monolog 等一样,编译成 .so/.a, 然后通过参数 -u YOUR_LIB link 进来, 然后把项目自身的静态资源和 php 文件加到src.list里编译就好了.
6. 关于 BPC 不支持的语法特性和扩展怎么解决?
等待 BPC 升级新版本.
翻阅过之前帖子的网友应该知道,BPC 并不是我们公司的主营业务,它最初是为了解决云招 OurATS 招聘管理系统本地部署而生的一个 side project ,目前 OurATS 自身的需求已经完善解决,所以 BPC 目前处在稳定期,更新和维护要看 OurATS 的需求来进行,请大家期望不要太高.
确实有需求的网友可以在公司层面和我们进行深度合作,我们乐意提供相应的技术支持.
语法特性涉及到 BPC 编译器的核心部分,因此实现起来一般不会很快,所以能用 phptobpc 解决的,可以用 phptobpc 解决.
php 扩展开发较为容易,简单的几天可以开发一个,复杂的需要几周时间,比如开发 event(core) 扩展用了 3 天,开发 mysqli 扩展用了 2 周.
目前 BPC 有 3 个大的特性尚未实现,提前知悉以免白忙一场:
[ol]
trait
简单的 trait 就相当于 copy paste, monolog-2.x 里有用到几个 trait,就是通过代码替换完成编译的.
class typed properties
BPC 支持 function/method type hints,但不支持 return type (可通过 phptobpc 去掉).
Generator / Fiber
[/ol]
7. 如何保障编译后的程序运行没问题?
PHPUnit.
我们维护着一个 BPC 可编译的 phpunit 版本: bpc-phpunit.phar-4.8.36.
使用 php 运行 phpunit tests 没问题,然后再用 bpc 编译运行这些 tests 还没问题,那就是没问题.
nikic-fast-route-1.3.0 和 monolog-2.x-branch 的 phpunit tests 就是使用 bpc-phpunit.phar-4.8.36 跑过的,所以可以确保没问题.
另外,我们也有一本收费的电子书 《 PHPUnit in Action --- The Easy Way 》 介绍了云招 OurATS 10 多年来的测试心得,有需要的可以看看.
8. 关于软件授权
这里说的软件授权不是 BPC 编译器自身的 license,而是你自己项目的授权.
比如你自己的项目中可能会有如下授权检测代码:
if (/* 没有通过授权检测 */) {
die('请购买授权后再使用');
}
BPC 的解决方案是在生成的 scheme 代码中随机插入授权检测代码,数量可由一个参数控制,通过插入足够多的授权检测(比如 10 万个)来增加破解时间,简单粗暴.
请参看文档 06_Licensing
9. BPC Playground
在 https://bpc.dev 上可以在线试用 BPC 编译器, 已内置了一些示例项目代码, 欢迎大家试玩儿~