2020-01-21 编译 PHP 扩展时,链接静态库

概述

PHP 的扩展库有两种编译形式。
一种是在编译 PHP 时,指定参数,将扩展静态化编译到 PHP 二进制文件中。
另外一种是在 PHP 编译完成后,利用 PEAR 机制编译扩展的动态库,供 PHP 启动时加载。
前一种当然更好,毕竟启动的时间是一次性,可以接受。
实际上很多时候,我们都是采用的后一种方式,因为比较灵活,安装以后还可以随时追加扩展库进去。

编译 PHP 动态扩展库的时候,又存在扩展库对其它库的依赖。比如常用的 zip 扩展,就依赖于 libzip 这个第三方库。
一般情况下,我们最常用的办法是用 yum 安装第三方依赖,然后再用 pecl cli,或者下载编译的方式,安装 php 扩展。
这样安装出来的扩展,十之八九都是 php ext 的动态库去调用第三方动态库。
通常情况下,倒是不会存在什么特别的问题,性能方面也几乎没有什么影响。
我个人的经验中,遇到过一次相关的事故,是某位哥们儿用 yum update -y 命令升级系统所有 package,包含 glibc-devel 这个包。
恰好呢,那段时间 glibc 因为安全问题,升级挺频繁的,并且某个常用的底层函数(我忘了具体名称,可能是 hostname 那次)没有向前兼容。
这下好了,yum 命令执行以后,好多程序相继崩溃,监控服务一直在重试这些程序,一直拉不起来。排查好久才找到问题。downgrade glibc-devel 后,险情接触。
这是我第一次遇到调用动态库的坑。

实际情况中,还有另外一种情况需要考虑,就是 deployment。
扩展库依赖第三方动态库,那么部署的时候,就要先部署第三方动态库。而所需的第三方动态库可能和现网服务器上同名第三方库版本冲突。
此时最直接的办法是换个目录安装新版本的第三方动态库。但后果可能像我之前举例中讲到的,某个程序因为第三方动态库版本之间的不兼容,莫名其妙出错,运行不起来。
之前举例的 zip 扩展就有这种情况。yum 安装的 libzip 有一些别的程序在用,但版本过低(0.10.1),不满足 php zip 扩展的编译要求(> 1.2)。
升级 libzip-devel package 吧,可能出现别的依赖程序不兼容;不升级吧,php zip 扩展又编译不了。

此时最简单的解决办法,就是在另外一台服务器上,把 php 的扩展编译好,里面做好第三方库的静态库。
部署的时候,把 php 扩展库的 .so 文件打包发布即可。只要 OS release 一致,这样直接发布 binary 就是没问题的。
即便未来这种方法不灵,也是很容易发现错误的。问题最晚在部署阶段就能被发现。

嗯,你们可能也看出来了,我是 fat-binary 策略的拥趸。

那安装 php 扩展时,怎么发布这种 fat binary 的动态库呢?下面举两个例子。

zip 扩展

mkdir -p /data/soft && cd $_  # 切换工作目录

# compile & install libzip 1.3.2
curl -Lo /data/soft/libzip-1.3.2.tar.xz https://libzip.org/download/libzip-1.3.2.tar.xz
tar -C /data/soft -Jxf /data/soft/libzip-1.3.2.tar.xz
cd /data/soft/libzip-1.3.2
./configure --prefix=/usr/local/libzip-1.3.2 --enable-static --disable-shared --with-pic
make -j$(nproc) && make install

# compile & install php zip ext
curl -Lo /data/soft/zip-1.15.5.tgz http://pecl.php.net/get/zip-1.15.5.tgz
tar -C /data/soft -zxf /data/soft/zip-1.15.5.tgz
cd /data/soft/zip-1.15.5
phpize
env CFLAGS="-I/usr/local/libzip-1.3.2/include" \
  LDFLAGS="-L/usr/local/libzip-1.3.2/lib -lzip -lbz2 -lz" \
  ./configure --with-libzip=/usr/local/libzip-1.3.2 --enable-zip
make -j$(nproc) && make install

PS:备注。

第一,使用 libzip-1.3.2 而不是最新的 libzip-1.5.2,是因为 libzip 从 1.4.0 开始使用 cmake 作为编译工具,而且限定 cmake > 3.0.2。可是 CentOS 7.6 下用 yum 也只能升级到 cmake 2.8.6。往下,libzip-1.3.2 还是用 gmake 来安装的,也够用,就它了。
第二,安装 libzip 时指定了不安装 shared lib,只安装 static lib,开启了 --with-pic 指令,针对平台做编译优化。这个版本的 libzip 安装到一个特定目录去。
第三,编译 php zip 扩展时,用 PKG_CONFIG_PATH 环境变量不好使,反复尝试,最后用 pkg-config 命令获取了查询结果,用 env 的方式把结果添加到 configure 命令中去,就行了。是临时取巧的做法。

lua 扩展

mkdir -p /data/soft && cd $_  # 切换工作目录

# compile & install liblua
curl -Lo /data/soft/lua-5.3.5.tar.gz https://www.lua.org/ftp/lua-5.3.5.tar.gz
tar -C /data/soft -zxf /data/soft/lua-5.3.5.tar.gz
cd /data/soft/lua-5.3.5
make CFLAGS=-fPIC PLAT=linux -j$(nproc)
make install INSTALL_TOP=/usr/local/lua-5.3.5

# compile & install lua ext
curl -Lo /data/soft/lua-2.0.6.tgz http://pecl.php.net/get/lua-2.0.6.tgz
tar -C /data/soft -zxf /data/soft/lua-2.0.6.tgz
cd /data/soft/lua-2.0.6
phpize
./configure --with-lua=/usr/local/lua-5.3.5
make -j$(nproc) && make install

PS:备注一下。

第一,编译 liblua 时,带上 CFLAGS=-fPIC 参数,是因为 liblua.a 需要链接到 php 扩展中去,如果不带 PIC 指令,liblua 和 lua 扩展两者编译出来的符号表会有冲突。
第二,把 liblua 安装到一个特定的目录,而不是安装到默认目录(默认目录是 /usr/local),和 yum 安装的 liblua 严格分离。
第三,编译 lua 扩展时,用 --with-lua 参数指定要链接的 liblua 位置即可。上面安装 liblua 的方法,只会安装 liblua 的静态库,所以只要指定这个 liblua 位置,链接的时候就一定会链接上这个静态库。

结果

从截屏中可以看出,两个扩展都解除了对第三方库的依赖。zip ext 不依赖 libzip 动态库,lua ext 也不依赖 liblua 了。达到了预期的目的。

安装完成后的截屏

这样发布的 php 扩展库,不用担心未来系统升级时收到影响。对于运维权限不在自己手上的情况,甚至与人共用一套系统的情况,真是必备良药。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,560评论 4 361
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,104评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,297评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,869评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,275评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,563评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,833评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,543评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,245评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,512评论 2 244
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,011评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,359评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,006评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,062评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,825评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,590评论 2 273
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,501评论 2 268

推荐阅读更多精彩内容