PHP Linking to a shared library in an extension

故事扮演 提交于 2020-01-04 03:19:48

问题


I'm working on a native PHP extension which includes symbols from a shared library, but I can't get the config.m4 file to generate a build procedure that includes the necessary linker options to correctly link to the share library. This is what I have in my config.m4 file so far:

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

The libotherlibrary library is in a standard system location. When I phpize with this configuration and then execute the generated configure script with the --enable-myextension argument it successfully generates a Makefile etc. and I can see it doing the test for otherlib_some_function from libotherlibrary which passes. But calling ldd on my resulting myextension.so gives just:

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)

so no mention of libotherlibrary. And the libtool and cc commands which are executed by the Makefile don't include the -lotherlibrary option. And then when I try and execute a PHP script which uses my extension I get:

php: symbol lookup error: /path/to/modules/myext.so: undefined symbol: otherlib_some_function

In place of PHP_EVAL_INCLINE and PHP_EVAL_LIBLINE I've also tried the PHP_ADD_LIBRARY macro:

PHP_ADD_LIBRARY($LIBNAME,,OTHERLIB_SHARED_LIBADD)

(I don't understand what the third argument to this macro is for.)

I've also tried (in combination with both of the above), including the fifth argument to PHP_CHECK_LIBRARY called extra-libs passing in the value of my $LIBOTHERLIB_LIBS variable. Doing so doesn't fix anything, and there's no documentation of what this argument is supposed to do or what values it requires. So this is just a guess really.

So how can I get my extension to build with the required -lotherlibrary linker option?


回答1:


You need to use PHP_ARG_WITH instead of PHP_ARG_ENABLE + plus a few other changes. Here comes an example which is working for me. Replace libxyz by the name of your external library:

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

Check this: http://php.net/manual/de/internals2.buildsys.configunix.php




回答2:


My working version now looks like this:

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

This technique uses pkg-config to find the shared library so perhaps it may not be as portable as @hek2mgl's explicit searching.

The main addition is the use of the PHP_SUBST macro which "Adds variable with it's value into Makefile" (according to the aclocal.m4 that phpize created). It seems that the macro PHP_ADD_LIBRARY, documented as "add a library to the link line", doesn't actually add anything to your Makefile. Instead, you supply a variable name as its third argument (documented as "shared-libadd") and later call PHP_SUBST to update that variable in the Makefile.




回答3:


Forgive my ignorance, but this may be a hack-y solution as I am not too good at m4.

This is working for me as of 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

I came to this conclusion after I saw in the makefile the EXTRA_CFLAGS was being defined by default. And, the contents of EXTRA_CFLAGS was being added to the build statement of the mymod.lo.

Thus, using PHP_SUBST(EXTRA_CFLAGS) sneaks it in there. After you run ./configure go to your makefile and see for yourself!



来源:https://stackoverflow.com/questions/29609438/php-linking-to-a-shared-library-in-an-extension

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!