整理下大概知识点:
- C的编译、链接、安装过程
- autoconf基本语法
- config.m4中的PHP_XX系列宏(在aclocal.m4中)
具体例子:
以使用taglib(https://github.com/taglib/taglib)编写一个操作mp3的id3标签的PHP扩展为例,按照默认编译安装taglib,头文件在/usr/local/include/taglib/tag_c.h,共享库文件在/usr/local/lib/libtag_c.so
我用到了taglib这个库的c语言版,安装后taglib-config –libs命令得到的是它的c++版的库,所以要在config.m4里自己写。
config.m4的关键代码:
PHP_ARG_WITH(taglib, for taglib support, [ --with-taglib Include taglib support]) if test "$PHP_TAGLIB" != "no"; then SEARCH_PATH="/usr/local /usr" SEARCH_FOR="/include/taglib/tag_c.h" if test -r $PHP_TAGLIB/$SEARCH_FOR; then # path given as parameter TAGLIB_DIR=$PHP_TAGLIB else # search default path list AC_MSG_CHECKING([for taglib files in default path]) for i in $SEARCH_PATH ; do if test -r $i/$SEARCH_FOR; then TAGLIB_DIR=$i AC_MSG_RESULT(found in $i) fi done fi if test -z "$TAGLIB_DIR"; then AC_MSG_RESULT([not found]) AC_MSG_ERROR([Please reinstall the taglib distribution]) fi PHP_ADD_INCLUDE($TAGLIB_DIR/include) dnl #库文件 libtag_c.so LIBNAME=tag_c dnl #库函数 LIBSYMBOL=taglib_file_tag dnl 第三个参数要设置成EXTRA_LDFLAGS时,链接的时候才会加上 -ltag_c 参数...这个PHP_ADD_LIBRARY_WITH_PATH的原型还没看明白... dnl 貌似还有好几种解决方案,PHP_EVAL_LIBLINE? PHP_ADD_LIBRARY_WITH_PATH($LIBNAME, $TAGLIB_DIR/lib, EXTRA_LDFLAGS) PHP_CHECK_LIBRARY($LIBNAME,$LIBSYMBOL, [ AC_DEFINE(HAVE_TAGLIB,1,[ ]) ],[ AC_MSG_ERROR() ],[ -L$TAGLIB_DIR/lib -lm ]) PHP_NEW_EXTENSION(php_taglib, php_taglib.c, $ext_shared) PHP_SUBST(TAGLIB_SHARED_LIBADD) fi
接下来是
configure [--with-taglib[=/path]] make make install
顺利的话可以到php.ini里面加载扩展。
期间可能会出现tag_c.h文件找不到的问题,注意下头文件的路径是由 config.m4 文件里的 PHP_ADD_INCLUDE($TAGLIB_DIR/include) 加上 扩展源码里 #include “taglib/tag_c.h” 组成的。
然后,即使扩展编译安装成功,php_info()里看到加载成功,但是cli执行php 扩展测试代码的时候出现 symbol lookup error的话,应该是扩展链接的时候没有找到libtag_c.so, 注意下PHP_ADD_LIBRARY_WITH_PATH() 的第三个参数即可。