Ubuntu16.04下交叉编译适配openwrt(CC版本)的PHP源码(php-5.6.17)总结

文章目录

一、简介

其实我交叉编译PHP是为了交叉编译PHP的扩展库swoole,openwrt官方的软件源中没有php-mod-swoole扩展模块的ipk供我直接进行opkg install,在查找swoole官方网站后发现是支持openwrt的,然后第一步编译就出问题了,需要先运行phpize才能生成启动编译的configure脚本,尝试一番后发现这个phpize是需要交叉编译PHP,在PHP的bin目录下存在php-config以及phpize,这两个文件在交叉编译swoole时是至关重要的。于是交叉编译swoole的第一道门槛就是交叉编译PHP。

二、准备

下载PHP源码:​​http://php.net/releases/​

最好在上面我提供的网址中下载,我最开始在GitHub上下载的源码,但是解压后没有发现configure脚本文件,导致我走了很多弯路,需要先运行buildconf --force文件生成configure脚本,对于这其中的门道,一时半会也没完全搞清楚,所以为了稳妥起见,最好在我上面说的那个网址中去下载对应版本的PHP源码。

如果是GitHub下载的可能需要(不确定能否正确编译):

Ubuntu16.04下交叉编译适配openwrt(CC版本)的PHP源码(php-5.6.17)总结_openwrt交叉编译PHP


Ubuntu16.04下交叉编译适配openwrt(CC版本)的PHP源码(php-5.6.17)总结_openwrt交叉编译PHP_02


如果是使用我上面提到的网址:

Ubuntu16.04下交叉编译适配openwrt(CC版本)的PHP源码(php-5.6.17)总结_linux_03


我的openwrt开发板上适配的PHP是5.6.17,以下编译过程均为5.6.17,不再赘述。下载相应代码放到Ubuntu下解压即可发现configure文件。

三、编译及安装

1.configure脚本参数了解

解压我们下载好的PHP源码,我下载的tar.gz版本:
tar zxvf php-5.6.17.tzr.gz

解压完之后进入目录下先了解一下configure:

./configure --help

Ubuntu16.04下交叉编译适配openwrt(CC版本)的PHP源码(php-5.6.17)总结_mipsel交叉编译PHP5_04


编译之前最好了解一下configure这个shell脚本的参数含义,对于编译PHP源码以及相关的源码很有帮助,甚至也可以说是一道门槛。最好能深入了解一下,我目前也只是知其然而不知其所以然,所以走进了很多坑,当然,这些基础的东西也不是一时半会能全部掌握的,有什么问题,仔细看下我的总结,希望我趟过的坑能帮助你不要走进这些坑。使用./configure --help命令可以查看相关的参数说明,如果想要详细学习一下的话,全部翻译一下,好好了解一下,对于学习Linux下的一些好的开源项目是很有帮助的,因为很多开源项目都是使用configure脚本来编译的,我目前也没有很充足的时间去系统性的了解这些东西,对于Linux系统和其一些开源项目,我一直抱有一颗敬畏和渴求了解的心。

Ubuntu16.04下交叉编译适配openwrt(CC版本)的PHP源码(php-5.6.17)总结_xml_05


。。。

有很多参数,有时间的好好看一下。

2.configure命令及常见错误

在运行configure生成Makefile脚本之前,我们先建一个文件夹,我们会将交叉编译的PHP安装在这个文件夹下:mkdir mipselPHP5.6.17(我将它放在和源码一个位置下,这个位置和目录名自定)

Ubuntu16.04下交叉编译适配openwrt(CC版本)的PHP源码(php-5.6.17)总结_mipsel交叉编译PHP5_06

(1)常见问题1:没有找到libxml2、zlib等库

libxml库使用without参数也是无用的,这是一个必须装的库,zlib这个库不知道,我的openwrt交叉编译工具链上不缺这个库,所以我没试过。

Ubuntu16.04下交叉编译适配openwrt(CC版本)的PHP源码(php-5.6.17)总结_linux_07


这些库有的我们已经集成到交叉编译工具链了,而有的没有,但是我们的PHP源码需要依赖这些库,所以有两种方法,一是我们重新编译一下我们的openwrt,在编译以及生成交叉编译工具链时集成这些库,第二个方法就是我们利用现有的交叉编译工具链编译安装一下这些库的源码,而我们需要的库也不多,一般就是缺libxml2和zlib,像我这里仅仅只缺libxml2库,因此,重新编译openwrt就不不必要了,所以我们直接找到这个库的源码下载下来交叉编译一下就好了。这里以我缺少的libxml2库为例,zlib库的交叉编译方法相同。他们都是configure一个系列的。

首先下载libxml2源码(直接搜索libxml2源码下载就可以了):​​http://xmlsoft.org/sources/​​ 方法类似:下载-解压-创建安装位置-configure-make-make install即可。

a.解压:

Ubuntu16.04下交叉编译适配openwrt(CC版本)的PHP源码(php-5.6.17)总结_xml_08

b.创建安装位置:

Ubuntu16.04下交叉编译适配openwrt(CC版本)的PHP源码(php-5.6.17)总结_mipsel交叉编译PHP5_09

c.configure:

error1:安装路径未使用绝对路径

Ubuntu16.04下交叉编译适配openwrt(CC版本)的PHP源码(php-5.6.17)总结_mipsel交叉编译PHP5_10


error2:没有提供host

Ubuntu16.04下交叉编译适配openwrt(CC版本)的PHP源码(php-5.6.17)总结_linux_11


error3:host名称错误

应使用mipsel-openwrt-linux(或者mipsel-openwrt-linux-uclibc)

Ubuntu16.04下交叉编译适配openwrt(CC版本)的PHP源码(php-5.6.17)总结_php_12


所以命令为:

CC=mipsel-openwrt-linux-uclibc-gcc AR=mipsel-openwrt-linux-uclibc-ar LD=mipsel-openwrt-linux-uclibc-ld RANLIB=mipsel-openwrt-linux-uclibc-ranlib STRIP=mipsel-openwrt-linux-uclibc-strip ./configure --host=mipsel-openwrt-linux-uclibc --prefix=/home/ubuntu/php-src-php-5.6.17/libxml2-2.7.1/mipsellibxml2/

d.make

常见错误:

Ubuntu16.04下交叉编译适配openwrt(CC版本)的PHP源码(php-5.6.17)总结_linux_13


在configure时我就发现它连接了Ubuntu系统下的python,但是configure并没有报错,在make时终于编译器发现问题了,这种错误解决方法有两种,一就是交叉编译一下python,然后在configure时指明python位置为我们的交叉编译的python,第二个就是利用configure带的without或者with-no参数去掉python连接,第二种情况下我们就无法使用libxml2库提供的关于python的操作了,但是由于我这里并不需要进行python相关的操作,果断取消掉连接python,否则,交叉编译python怕又是一堆的坑要填。

那么交叉编译libxml库的configure命令再次变更:
CC=mipsel-openwrt-linux-uclibc-gcc AR=mipsel-openwrt-linux-uclibc-ar LD=mipsel-openwrt-linux-uclibc-ld RANLIB=mipsel-openwrt-linux-uclibc-ranlib STRIP=mipsel-openwrt-linux-uclibc-strip ./configure --host=mipsel-openwrt-linux-uclibc --prefix=/home/ubuntu/php-src-php-5.6.17/libxml2-2.7.1/mipsellibxml2/ --without-python

去掉python连接后编译成功了:

Ubuntu16.04下交叉编译适配openwrt(CC版本)的PHP源码(php-5.6.17)总结_openwrt交叉编译PHP_14

e.make install

安装也成功了:

Ubuntu16.04下交叉编译适配openwrt(CC版本)的PHP源码(php-5.6.17)总结_xml_15


查看一下:

Ubuntu16.04下交叉编译适配openwrt(CC版本)的PHP源码(php-5.6.17)总结_openwrt交叉编译PHP_16

(2)常见问题2

–with-libxml-dir:这里不是libxml2,否则还是会提示你找不到libxml2的安装目录。

Ubuntu16.04下交叉编译适配openwrt(CC版本)的PHP源码(php-5.6.17)总结_php_17

(3)常见问题3

cannot run test program while cross compiling

Ubuntu16.04下交叉编译适配openwrt(CC版本)的PHP源码(php-5.6.17)总结_xml_18


这种问题的话是交叉编译特有的,因为我们是交叉编译环境,所以无法进行test测试,所以我们需要手动关闭configure中所有关于这部分test的内容。首先复制这句话,然后打开configure,然后找到这句话的所有位置,将对应的数据全部注释掉(就几个位置,不多):

比如,我原来是这样的:

Ubuntu16.04下交叉编译适配openwrt(CC版本)的PHP源码(php-5.6.17)总结_xml_19


注释掉后是这样的(不让它执行then后的语句,直接执行else后的语句):

Ubuntu16.04下交叉编译适配openwrt(CC版本)的PHP源码(php-5.6.17)总结_mipsel交叉编译PHP5_20


然后保存并重新执行configure。

(4)常见问题4

找不到iconv,交叉编译一下libiconv库,然后加上即可,这里不再赘述交叉编译的方法了。如果你不需要使用iconv函数也可以直接without。

Ubuntu16.04下交叉编译适配openwrt(CC版本)的PHP源码(php-5.6.17)总结_openwrt交叉编译PHP_21

(5)常见问题5

configure: error: Don’t know how to define struct flock on this system, set --enable-opcache=no

Ubuntu16.04下交叉编译适配openwrt(CC版本)的PHP源码(php-5.6.17)总结_linux_22

方法1:按照提示set --enable-opcache=no或者–disable-opcache

最终configure成功了:

Ubuntu16.04下交叉编译适配openwrt(CC版本)的PHP源码(php-5.6.17)总结_openwrt交叉编译PHP_23


configure命令暂时确定为:(AR=mipsel-openwrt-linux-uclibc-ar LD=mipsel-openwrt-linux-uclibc-ld RANLIB=mipsel-openwrt-linux-uclibc-ranlib STRIP=mipsel-openwrt-linux-uclibc-strip这些其实也可以不要)

CC=mipsel-openwrt-linux-uclibc-gcc AR=mipsel-openwrt-linux-uclibc-ar LD=mipsel-openwrt-linux-uclibc-ld RANLIB=mipsel-openwrt-linux-uclibc-ranlib STRIP=mipsel-openwrt-linux-uclibc-strip ./configure --host=mipsel-openwrt-linux-uclibc --prefix=/home/ubuntu/php-src-php-5.6.17/php-5.6.17/mipselPHP5.6.17/ --with-libxml-dir=/home/ubuntu/php-src-php-5.6.17/libxml2-2.7.1/mipsellibxml2/ --without-iconv --disable-opcache

方法2:

在configure中先找到if test “$flock_type” == "unknown"这句话,然后在上面增加flock_type=linux,也就是让这个if语句不成立,这样也可以解决上面的问题,推荐这种方法,因为上面那种方法不知道会不会引起其它问题,暂时没有测试过。

Ubuntu16.04下交叉编译适配openwrt(CC版本)的PHP源码(php-5.6.17)总结_php_24


configu命令更改为:

CC=mipsel-openwrt-linux-uclibc-gcc AR=mipsel-openwrt-linux-uclibc-ar LD=mipsel-openwrt-linux-uclibc-ld RANLIB=mipsel-openwrt-linux-uclibc-ranlib STRIP=mipsel-openwrt-linux-uclibc-strip ./configure --host=mipsel-openwrt-linux-uclibc --prefix=/home/ubuntu/php-src-php-5.6.17/php-5.6.17/mipselPHP5.6.17/ --with-libxml-dir=/home/ubuntu/php-src-php-5.6.17/libxml2-2.7.1/mipsellibxml2/ --without-iconv

3.make

(1)问题1:编译卡死

这里最好使用真机或者虚拟机开启虚拟内存编译,不然很卡,甚至直接卡死,我的虚拟机只分配了1G内存,没有开启虚拟内存的时候卡死了两次,而且直接导致使用vm tools的拖放复制黏贴都出问题了。

Ubuntu16.04下交叉编译适配openwrt(CC版本)的PHP源码(php-5.6.17)总结_openwrt交叉编译PHP_25


就这个位置连续卡死两次。。。开了虚拟内存就好了,关于如何开启虚拟内存,我在另一个总结“Vm虚拟机扩展Ubuntu系统磁盘空间”中最后有一部分说明,你也可以直接加入到开机启动项中,这个我会在后面总结一下,现在发现编译大的代码时还是很耗内存的。

(2)可能错误1:

Ubuntu16.04下交叉编译适配openwrt(CC版本)的PHP源码(php-5.6.17)总结_xml_26


如果遇到上面这种错误:/home/ubuntu/php-src-php-5.6.17/php-5.6.17/ext/standard/basic_functions.c:3624: undefined reference to `zm_startup_password

我最开始以为是前面的–disable-opcache参数设置造成的,但是最终发现不是这个造成的,而是在configure时少了一些参数,这几个参数经过我反复测试发现这样之后make就会成功,否则就会报上面的错误:–enable-cli --disable-cgi --disable-fpm --disable-phpdbg --disable-all

最终确认,configure完整命令:

CC=mipsel-openwrt-linux-uclibc-gcc AR=mipsel-openwrt-linux-uclibc-ar LD=mipsel-openwrt-linux-uclibc-ld RANLIB=mipsel-openwrt-linux-uclibc-ranlib STRIP=mipsel-openwrt-linux-uclibc-strip ./configure --host=mipsel-openwrt-linux-uclibc --prefix=/home/ubuntu/php-src-php-5.6.17/php-5.6.17/mipselPHP5.6.17/ --with-libxml-dir=/home/ubuntu/php-src-php-5.6.17/libxml2-2.7.1/mipsellibxml2/ --without-iconv --enable-cli --disable-cgi --disable-fpm --disable-phpdbg --disable-all

然后重新运行configure,并且make clean && make成功了:

Ubuntu16.04下交叉编译适配openwrt(CC版本)的PHP源码(php-5.6.17)总结_xml_27

4.make install

因为我设置的安装目录位置在home下,所以不需要sudo开启root权限即可安装,如果你安装的位置特殊,有可能需要开启root权限安装。

Ubuntu16.04下交叉编译适配openwrt(CC版本)的PHP源码(php-5.6.17)总结_xml_28


查看一下:

Ubuntu16.04下交叉编译适配openwrt(CC版本)的PHP源码(php-5.6.17)总结_php_29

四、最后

交叉编译PHP算是完成了,期间遇到了很多问题,但总算都解决了。接下来就是交叉编译swoole扩展库了。