上面是玩笑话,现在我也说说如何学习PHP解释器的源码。
从Branch中选择一个版本tag,和每次PHP发布出来的版本就是一致的。也许你会发现你想编译的的时候缺找不到configure文件,但是有configure.in文件。这时候需要先执行的是buildconf(如果是在Windows下面可以执行buildconf.bat,不过我从来没有尝试过在Windows下面编译PHP,所以具体的步骤我就不清楚了)。buildconf本身是个简单的shell脚本,你可以用记事本打开看看它(最终的执行文件在build目录里,这个目录里有一些与编译有关的文件)。
re2c和Bison分别是PHP用到的词法解析器和语法分析器。在genfiles这个文件中可以看到它们的调用其实是在Makefile.frag中写着,分别通过zend_language_scanner.l和zend_language_parser.y生成相应的C语言文件(这个应该很多地方都有提到过)。
到了编译环节,编译之前需要先通过configure文件生成Makefile然后执行make,所以gcc自然是必不可少的。configure文件本身也是一个shell脚本,你也可以简单阅读一下它的内容。不过既然它是由autoconf从configure.in中生成的,也许直接查看configure.in会更轻松一些。
到这里总结一下就是:抛开一些核心扩展额依赖(比如xml,ssl等),编译PHP的先决条件是机器上有Autotools的工具(automake,autoconf等),需要安装re2c和Bison,当然还有编译工具(gcc)。
也许大家都知道,使用configure生成Makefile的时候可以通过--prefix参数指定目录,同时也可以选择编译哪些核心模块。至于哪些模块会被默认集成而哪些不会,这些本身是写在每个扩展的config.m4(也有几个是被命名为config0.m4或config9.m4)文件里的的,全都通过一些--enable、--disable、--with和--without的选项来控制。
编译的也与你采用的Web服务器有关,这涉及到你需要使用哪个sapi,如果是Apache,也许需要指定--with-apxs2的参数,如果是Nginx,php-fpm在默认条件下是会被编译的,但可以指定php-fpm的执行组和用户,不过这个是可以在编译完成后在配置中修改的。
编译完成之后还有一些事情需要考虑,最基本的问题是PHP的配置文件的问题,还有一个是如果使用的是php-fpm,如何更便捷的控制它的启动、停止以及重启等。
在PHP源码根中已经准备了两份配置文件的模板:php.ini-development和php.ini-production。显然是分别用于开发环境和生产环境的,将其中一个复制到配置文件目录并重命名为php.ini即可(如果你不知道配置文件的目录在哪里,可以使用php--ini命令查看)。然后也可以根据你的需要修改它。
至于php-fpm的控制脚本,源码中本身也是有提供的,在sapi/fpm目录下。这个目录下的几个文件中有php-fpm配置文件的模板,也有稍微修改即可放到服务器/etc/init.d目录下用于控制php-fpm的start、stop、restart和reload动作的脚本,现在的版本中也提供了用于systemd的service文件。
如果PHP编译完成之后,发现还需要一些没有编译进去的核心扩展或者第三方扩展,你可以单独编译它们。
扩展编译的整个过程一共四句命令:
phpize命令是用来准备PHP扩展库的编译环境的。在执行phpize的时候,如果有多个版本的PHP,用哪个就要选哪个。这个命令和编译后的php的二进制文件在同一个目录中,也是一个shell脚本。
执行configure的时候,如果当前$PATH中找不到php-config或者有多个版本的PHP时,也需要通过--with-php-config的指令来指定php-config的目录。php-config是一个用于获取所安装的PHP配置的信息,它也一样是和php的二进制文件在同一个目录的shell脚本。
phpize和php-config的源码生成文件都是在scripts目录下。
所有工作完成之后,就可以愉快的使用你自己定制的PHP了。
305611088PHP交流群。希望PHP的交流活跃起来,质量高起来。