PHP 链接到扩展中的共享库
PHP Linking to a shared library in an extension
我正在开发包含来自共享库的符号的本机 PHP 扩展,但我无法获取 config.m4
文件来生成包含必要 linker 选项正确 link 到共享库。到目前为止,这是我 config.m4
文件中的内容:
PHP_ARG_ENABLE(myextension, whether to enable MyExtension support, [ --enable-myextension Enable MyExtension support])
if test "$PHP_MYEXTENSION" = "yes"; then
LIBNAME=otherlibrary
LIBSYMBOL=otherlib_some_function
LIBOTHERLIB_LIBS=`pkg-config --libs otherlibrary`
LIBOTHERLIB_INC=`pkg-config --cflags otherlibrary`
PHP_CHECK_LIBRARY($LIBNAME,$LIBSYMBOL,
[
PHP_EVAL_INCLINE($LIBOTHERLIB_INC)
PHP_EVAL_LIBLINE($LIBOTHERLIB_LIBS)
AC_DEFINE(HAVE_MYEXTENSION, 1, [Whether you have MyExtension])
],[
AC_MSG_ERROR([wrong lib$LIBNAME version or library not found])
])
PHP_NEW_EXTENSION(myextension, myextension.c, $ext_shared)
fi
libotherlibrary
库位于标准系统位置。当我使用此配置 phpize
然后使用 --enable-myextension
参数执行生成的 configure
脚本时,它成功生成了 Makefile
等,我可以看到它正在为 otherlib_some_function
从 libotherlibrary
过去了。但是在我的结果 myextension.so 上调用 ldd
只给出:
linux-vdso.so.1 (0x00007ffd11fce000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f741e653000)
/lib64/ld-linux-x86-64.so.2 (0x00007f741ec26000)
所以没有提到 libotherlibrary
。由Makefile
执行的libtool
和cc
命令不包括-lotherlibrary
选项。然后当我尝试执行使用我的扩展名的 PHP 脚本时,我得到:
php: symbol lookup error: /path/to/modules/myext.so: undefined symbol: otherlib_some_function
代替 PHP_EVAL_INCLINE
和 PHP_EVAL_LIBLINE
我还尝试了 PHP_ADD_LIBRARY
宏:
PHP_ADD_LIBRARY($LIBNAME,,OTHERLIB_SHARED_LIBADD)
(我不明白这个宏的第三个参数是干什么用的。)
我也尝试过(与上述两者结合),包括 PHP_CHECK_LIBRARY
的第五个参数 extra-libs
传入我的 $LIBOTHERLIB_LIBS
变量的值。这样做并不能解决任何问题,也没有关于该参数应该做什么或它需要什么值的文档。所以这真的只是一个猜测。
那么我怎样才能使用所需的 -lotherlibrary
linker 选项构建我的扩展?
您需要使用 PHP_ARG_WITH
而不是 PHP_ARG_ENABLE
+ 加上一些其他更改。这是一个对我有用的例子。将 libxyz
替换为您的外部库的名称:
config.m4
dnl If your extension references something external, use with:
PHP_ARG_WITH(libxyz, for libxyz support,
Make sure that the comment is aligned:
[ --with-libxyz Include libxyz support])
dnl Otherwise use enable:
dnl PHP_ARG_ENABLE(libxyz, whether to enable libxyz support,
dnl Make sure that the comment is aligned:
dnl [ --enable-libxyz Enable libxyz support])
if test "$PHP_LIBXYZ" != "no"; then
dnl Write more examples of tests here...
dnl # --with-libxyz -> check with-path
SEARCH_PATH="/usr/local /usr"
SEARCH_FOR="/include/libxyz.h"
if test -r $PHP_LIBXYZ/$SEARCH_FOR; then # path given as parameter
LIBXYZ_DIR=$PHP_LIBXYZ
else # search default path list
AC_MSG_CHECKING([for libxyz files in default path])
for i in $SEARCH_PATH ; do
if test -r $i/$SEARCH_FOR; then
LIBXYZ_DIR=$i
AC_MSG_RESULT(found in $i)
fi
done
fi
dnl
if test -z "$LIBXYZ_DIR"; then
AC_MSG_RESULT([not found])
AC_MSG_ERROR([Please reinstall the libxyz distribution])
fi
dnl # --with-libxyz -> add include path
PHP_ADD_INCLUDE($LIBXYZ_DIR/include)
dnl # --with-libxyz -> check for lib and symbol presence
LIBNAME=libxyz
LIBSYMBOL=libxyz_lib_version
PHP_CHECK_LIBRARY($LIBNAME,$LIBSYMBOL,
[
PHP_ADD_LIBRARY_WITH_PATH($LIBNAME, $LIBXYZ_DIR/lib, LIBXYZ_SHARED_LIBADD)
AC_DEFINE(HAVE_LIBXYZLIB,1,[ ])
],[
AC_MSG_ERROR([wrong libxyz lib version or lib not found])
],[
-L$LIBXYZ_DIR/lib -lm
])
PHP_SUBST(LIBXYZ_SHARED_LIBADD)
PHP_NEW_EXTENSION(libxyz, libxyz.c, $ext_shared)
fi
检查这个:http://php.net/manual/de/internals2.buildsys.configunix.php
我的工作版本现在是这样的:
PHP_ARG_ENABLE(myextension, whether to enable MyExtension support, [ --enable-myextension Enable MyExtension support])
if test "$PHP_MYEXTENSION" = "yes"; then
LIBNAME=otherlibrary
LIBSYMBOL=otherlib_some_function
LIBOTHERLIB_LIBS=`pkg-config --libs otherlibrary`
LIBOTHERLIB_INC=`pkg-config --cflags otherlibrary`
PHP_CHECK_LIBRARY($LIBNAME,$LIBSYMBOL,
[
PHP_ADD_LIBRARY($LIBNAME,1,OTHERLIBRARY_SHARED_LIBADD)
PHP_SUBST(OTHERLIBRARY_SHARED_LIBADD)
AC_DEFINE(HAVE_MYEXTENSION, 1, [Whether you have MyExtension])
],[
AC_MSG_ERROR([wrong lib$LIBNAME version or library not found])
])
PHP_NEW_EXTENSION(myextension, myextension.c, $ext_shared)
fi
此技术使用 pkg-config
来查找共享库,因此它可能不像 @hek2mgl 的显式搜索那样可移植。
主要的添加是 "Adds variable with it's value into Makefile" 的 PHP_SUBST
宏的使用(根据 phpize
创建的 aclocal.m4
)。似乎宏 PHP_ADD_LIBRARY
,记录为 "add a library to the link line",实际上并没有向您的 Makefile
添加任何内容。相反,您提供一个变量名称作为其第三个参数(记录为 "shared-libadd"),然后调用 PHP_SUBST
以更新 Makefile
.
中的该变量
原谅我的无知,但是这个可能是一个 hack-y 解决方案,因为我不太擅长 m4。
从 php-7.0
这对我有用
if test "$PHP_MYMOD" != "no";
then
LIBNAME=my_dank_lib
LIBSYMBOL=my_dank_lib_function_name
PHP_CHECK_LIBRARY($LIBNAME,$LIBSYMBOL,
[
PHP_ADD_LIBRARY($LIBNAME, 1, EXTRA_CFLAGS)
PHP_SUBST(EXTRA_CFLAGS)
AC_DEFINE([MYMOD],1 ,[whether to enable mymod support])
AC_HEADER_STDC
],[
AC_MSG_ERROR([Uh oh, library $LIBNAME was not found with the function $LIBSYMBOL in it.])
])
PHP_NEW_EXTENSION(mymod,
mymod.c,
$ext_shared,, -DZEND_ENABLE_STATIC_TSRMLS_CACHE=1)
fi
我在 makefile 中看到默认定义了 EXTRA_CFLAGS
后得出了这个结论。并且,EXTRA_CFLAGS
的内容被添加到 mymod.lo
.
的构建语句中
因此,使用 PHP_SUBST(EXTRA_CFLAGS)
将其偷偷放入其中。在您 运行 ./configure
转到您的 makefile 并亲自查看之后!
我正在开发包含来自共享库的符号的本机 PHP 扩展,但我无法获取 config.m4
文件来生成包含必要 linker 选项正确 link 到共享库。到目前为止,这是我 config.m4
文件中的内容:
PHP_ARG_ENABLE(myextension, whether to enable MyExtension support, [ --enable-myextension Enable MyExtension support])
if test "$PHP_MYEXTENSION" = "yes"; then
LIBNAME=otherlibrary
LIBSYMBOL=otherlib_some_function
LIBOTHERLIB_LIBS=`pkg-config --libs otherlibrary`
LIBOTHERLIB_INC=`pkg-config --cflags otherlibrary`
PHP_CHECK_LIBRARY($LIBNAME,$LIBSYMBOL,
[
PHP_EVAL_INCLINE($LIBOTHERLIB_INC)
PHP_EVAL_LIBLINE($LIBOTHERLIB_LIBS)
AC_DEFINE(HAVE_MYEXTENSION, 1, [Whether you have MyExtension])
],[
AC_MSG_ERROR([wrong lib$LIBNAME version or library not found])
])
PHP_NEW_EXTENSION(myextension, myextension.c, $ext_shared)
fi
libotherlibrary
库位于标准系统位置。当我使用此配置 phpize
然后使用 --enable-myextension
参数执行生成的 configure
脚本时,它成功生成了 Makefile
等,我可以看到它正在为 otherlib_some_function
从 libotherlibrary
过去了。但是在我的结果 myextension.so 上调用 ldd
只给出:
linux-vdso.so.1 (0x00007ffd11fce000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f741e653000)
/lib64/ld-linux-x86-64.so.2 (0x00007f741ec26000)
所以没有提到 libotherlibrary
。由Makefile
执行的libtool
和cc
命令不包括-lotherlibrary
选项。然后当我尝试执行使用我的扩展名的 PHP 脚本时,我得到:
php: symbol lookup error: /path/to/modules/myext.so: undefined symbol: otherlib_some_function
代替 PHP_EVAL_INCLINE
和 PHP_EVAL_LIBLINE
我还尝试了 PHP_ADD_LIBRARY
宏:
PHP_ADD_LIBRARY($LIBNAME,,OTHERLIB_SHARED_LIBADD)
(我不明白这个宏的第三个参数是干什么用的。)
我也尝试过(与上述两者结合),包括 PHP_CHECK_LIBRARY
的第五个参数 extra-libs
传入我的 $LIBOTHERLIB_LIBS
变量的值。这样做并不能解决任何问题,也没有关于该参数应该做什么或它需要什么值的文档。所以这真的只是一个猜测。
那么我怎样才能使用所需的 -lotherlibrary
linker 选项构建我的扩展?
您需要使用 PHP_ARG_WITH
而不是 PHP_ARG_ENABLE
+ 加上一些其他更改。这是一个对我有用的例子。将 libxyz
替换为您的外部库的名称:
config.m4
dnl If your extension references something external, use with:
PHP_ARG_WITH(libxyz, for libxyz support,
Make sure that the comment is aligned:
[ --with-libxyz Include libxyz support])
dnl Otherwise use enable:
dnl PHP_ARG_ENABLE(libxyz, whether to enable libxyz support,
dnl Make sure that the comment is aligned:
dnl [ --enable-libxyz Enable libxyz support])
if test "$PHP_LIBXYZ" != "no"; then
dnl Write more examples of tests here...
dnl # --with-libxyz -> check with-path
SEARCH_PATH="/usr/local /usr"
SEARCH_FOR="/include/libxyz.h"
if test -r $PHP_LIBXYZ/$SEARCH_FOR; then # path given as parameter
LIBXYZ_DIR=$PHP_LIBXYZ
else # search default path list
AC_MSG_CHECKING([for libxyz files in default path])
for i in $SEARCH_PATH ; do
if test -r $i/$SEARCH_FOR; then
LIBXYZ_DIR=$i
AC_MSG_RESULT(found in $i)
fi
done
fi
dnl
if test -z "$LIBXYZ_DIR"; then
AC_MSG_RESULT([not found])
AC_MSG_ERROR([Please reinstall the libxyz distribution])
fi
dnl # --with-libxyz -> add include path
PHP_ADD_INCLUDE($LIBXYZ_DIR/include)
dnl # --with-libxyz -> check for lib and symbol presence
LIBNAME=libxyz
LIBSYMBOL=libxyz_lib_version
PHP_CHECK_LIBRARY($LIBNAME,$LIBSYMBOL,
[
PHP_ADD_LIBRARY_WITH_PATH($LIBNAME, $LIBXYZ_DIR/lib, LIBXYZ_SHARED_LIBADD)
AC_DEFINE(HAVE_LIBXYZLIB,1,[ ])
],[
AC_MSG_ERROR([wrong libxyz lib version or lib not found])
],[
-L$LIBXYZ_DIR/lib -lm
])
PHP_SUBST(LIBXYZ_SHARED_LIBADD)
PHP_NEW_EXTENSION(libxyz, libxyz.c, $ext_shared)
fi
检查这个:http://php.net/manual/de/internals2.buildsys.configunix.php
我的工作版本现在是这样的:
PHP_ARG_ENABLE(myextension, whether to enable MyExtension support, [ --enable-myextension Enable MyExtension support])
if test "$PHP_MYEXTENSION" = "yes"; then
LIBNAME=otherlibrary
LIBSYMBOL=otherlib_some_function
LIBOTHERLIB_LIBS=`pkg-config --libs otherlibrary`
LIBOTHERLIB_INC=`pkg-config --cflags otherlibrary`
PHP_CHECK_LIBRARY($LIBNAME,$LIBSYMBOL,
[
PHP_ADD_LIBRARY($LIBNAME,1,OTHERLIBRARY_SHARED_LIBADD)
PHP_SUBST(OTHERLIBRARY_SHARED_LIBADD)
AC_DEFINE(HAVE_MYEXTENSION, 1, [Whether you have MyExtension])
],[
AC_MSG_ERROR([wrong lib$LIBNAME version or library not found])
])
PHP_NEW_EXTENSION(myextension, myextension.c, $ext_shared)
fi
此技术使用 pkg-config
来查找共享库,因此它可能不像 @hek2mgl 的显式搜索那样可移植。
主要的添加是 "Adds variable with it's value into Makefile" 的 PHP_SUBST
宏的使用(根据 phpize
创建的 aclocal.m4
)。似乎宏 PHP_ADD_LIBRARY
,记录为 "add a library to the link line",实际上并没有向您的 Makefile
添加任何内容。相反,您提供一个变量名称作为其第三个参数(记录为 "shared-libadd"),然后调用 PHP_SUBST
以更新 Makefile
.
原谅我的无知,但是这个可能是一个 hack-y 解决方案,因为我不太擅长 m4。
从 php-7.0
这对我有用if test "$PHP_MYMOD" != "no";
then
LIBNAME=my_dank_lib
LIBSYMBOL=my_dank_lib_function_name
PHP_CHECK_LIBRARY($LIBNAME,$LIBSYMBOL,
[
PHP_ADD_LIBRARY($LIBNAME, 1, EXTRA_CFLAGS)
PHP_SUBST(EXTRA_CFLAGS)
AC_DEFINE([MYMOD],1 ,[whether to enable mymod support])
AC_HEADER_STDC
],[
AC_MSG_ERROR([Uh oh, library $LIBNAME was not found with the function $LIBSYMBOL in it.])
])
PHP_NEW_EXTENSION(mymod,
mymod.c,
$ext_shared,, -DZEND_ENABLE_STATIC_TSRMLS_CACHE=1)
fi
我在 makefile 中看到默认定义了 EXTRA_CFLAGS
后得出了这个结论。并且,EXTRA_CFLAGS
的内容被添加到 mymod.lo
.
因此,使用 PHP_SUBST(EXTRA_CFLAGS)
将其偷偷放入其中。在您 运行 ./configure
转到您的 makefile 并亲自查看之后!