Compile PHP extension using SWIG - php

I am trying to compile the swig interface of crfsuite as a PHP module. So far I've managed to actually compile a crfsuite.so file, load it as an extension in PHP and call methods on it. As far as I can see any method call that was wrapped by SWIG works fine out of the box. Unfortunately I seem to be missing some symbols:
❯ nm crfsuite.so | grep crfsuite
U crfsuite_attribute_set
U crfsuite_create_instance
U crfsuite_create_instance_from_file
U crfsuite_create_instance_from_memory
U crfsuite_data_append
U crfsuite_data_finish
U crfsuite_data_init
00000000000281b3 T crfsuite_dictionary_create_instance
U crfsuite_evaluation_accmulate
U crfsuite_evaluation_finalize
U crfsuite_evaluation_init
U crfsuite_evaluation_output
0000000000256460 B crfsuite_globals
U crfsuite_instance_finish
U crfsuite_instance_init_n
U crfsuite_interlocked_decrement
U crfsuite_interlocked_increment
U crfsuite_item_append_attribute
U crfsuite_item_init
U crfsuite_item_init_n
I have generated the swig wrapper like so, using the default export.i:
swig -c++ -php7 -Icrfsuite/include -o export_wrap.cpp export.i
After that I've compiled the code with the following commands:
gcc -fpic -Icrfsuite/include -Icrfsuite/lib/cqdb/include -Iliblbfgs/include \
`php-config --includes` -c crfsuite.cpp export_wrap.cpp crfsuite/lib/crf/src/*.c \
crfsuite/swig/*.cpp crfsuite/lib/cqdb/src/cqdb.c crfsuite/lib/cqdb/src/lookup3.c \
liblbfgs/lib/*.c
gcc -shared *.o -o crfsuite.so
I've played with many gcc flags such as -L/usr/local/lib, -lcrfsuite, -Wl,-undefined,dynamic_lookup but stopped as they didn't seem to affect the result.
Running a basic example errors with the following message:
/usr/bin/php: symbol lookup error: /usr/lib/php/20170718/crfsuite.so: undefined symbol: crfsuite_data_init
The example correctly calls the Trainer constructor.
This all is quite new so I am lost between the many steps. Am I missing something obvious? Why are the symbols not linked correctly? And how can it be fixed?
Update:
I've set the $LD_LIBRARY_PATH and $LD_RUN_PATH to /usr/local/lib. That is also where the compiled and installed version of the crfsuite lies as a shared object:
ll $LD_LIBRARY_PATH/libcrfsuite.so
/usr/local/lib/libcrfsuite.so -> libcrfsuite-0.12.so
I have also changed the order of .o files. Didn't change anything.

Related

SOLVED: Compiling PHP with GD : relocation R_X86_64_PC32 against symbol `WebPMemoryWrite' can not be used when making a shared object;

I'm currently installing PHP with GD library from sources on a RedHat7 server and I'm facing some issues.
I configure PHP with this command:
./configure --with-apxs2=/server/lib/httpd/bin/apxs --with-pdo-mysql --with-config-file-path=/server/php-7.3.9/conf --with-libxml-dir=/server/lib/libxml2 --with-curl=/server/lib/curl --with-gd --enable-mbstring --with-jpeg-dir=/server/lib/libjpeg --with-png-dir=/server/lib/libpng –with-webp-dir=/server/lib/webp
It works but when I'm doing the make command I have this error:
/bin/ld: /server/lib/webp/lib/libwebp.a(picture_enc.o): relocation R_X86_64_PC32 against symbol `WebPMemoryWrite' can not be used when making a shared object; recompile with -fPIC
/bin/ld: final link failed: Bad value
collect2: error: ld returned 1 exit status
make: *** [libphp7.la] Error 1
I also tried to compile and install it without webp (It's not required in the PHP documentation: php doc) but I have this error :
ext/gd/libgd/.libs/gd_webp.o: In function `gdImageCreateFromWebpCtx':
/server/php-7.3.9/ext/gd/libgd/gd_webp.c:68: undefined reference to `WebPGetInfo'
/sever/php-7.3.9/ext/gd/libgd/gd_webp.c:79: undefined reference to `WebPDecodeARGB'
ext/gd/libgd/.libs/gd_webp.o: In function `gdImageWebpCtx':
/server/php-7.3.9/ext/gd/libgd/gd_webp.c:153: undefined reference to `WebPEncodeRGBA'
collect2: error: ld returned 1 exit status
make: *** [sapi/cli/php] Error 1
So it seems to be required.
Can you please help me to solve this
Thanks
I resolved my issue by replacing my installation of webp package.
At first I used the pre-compiled linux package and replacing it by native sources and a compiling, make & make install solve the problem.
Thanks all

Adding php-curl in a Yocto build

I've been building a custom image using Yocto and wpewebkit to use within docker. I need to run a local web server with php, which I have accomplished no problem. I need to use curl within my project and I have apache2, php, modphp, and curl installed. All I need is php-curl but I cannot find how to install this. Does anyone know how or if I can do this? I've put in all my efforts on googling multiple phrases but I only find how to install php-curl using apt-get or yum, or I get links to the meta-* directories which I have access to within my build files anyways.
If it helps at all, this custom image was based on the image provided from the following project on GitHub: https://github.com/resin-io-playground/resin-wpe/tree/master/base-image . I already spoke to the developer and their knowledge of PHP is limited.
EDIT #1: Progress so far, had to update the curl.bb file to properly include libcurl-dev, and then worked with #pmod's suggestion to incorporate curl into the php build. Everything seemed to run okay until I received the following error:
| ../php-7.1.9/configure: line 386: test: please: integer expression expected
| configure: error: reinstall
| ../php-7.1.9/configure: line 275: return: please: numeric argument required
| ../php-7.1.9/configure: line 285: exit: please: numeric argument required
| NOTE: The following config.log files may provide further information.
| NOTE: /base-image/build/tmp-glibc/work/x86_64-linux/php-native/7.1.9-r0/build/config.log
| ERROR: configure failed
| WARNING: /base-image/build/tmp-glibc/work/x86_64-linux/php-native/7.1.9-r0/temp/run.do_configure.29590:1 exit 1 from 'exit 1'
| ERROR: Function failed: do_configure (log file is located at /base-image/build/tmp-glibc/work/x86_64-linux/php-native/7.1.9-r0/temp/log.do_configure.29590)
ERROR: Task (virtual:native:/base-image/build/../meta-openembedded/meta-oe/recipes-devtools/php/php_7.1.9.bb:do_configure) failed with exit code '1'
Edit #2: I've gone ahead and added everything I was missing. I'm getting the same error above, where the function do_configure during the php build is failing. I'm posting below what I ensured I have in my curl.bb file (I had to add this), what I have in my php.inc file, and the curl files located staging directory.
curl.bb:
PACKAGES =+ "lib${BPN} lib${BPN}-native lib${BPN}-dev lib${BPN}-dev-native"
FILES_lib${BPN} = "${libdir}/lib*.so.*"
FILES_lib${BPN}-dev = "${includedir} \
${libdir}/lib*.so \
${libdir}/lib*.a \
${libdir}/lib*.la \
${libdir}/pkgconfig \
${datadir}/aclocal \
${bindir}/*-config"
php.inc:
EXTRA_OECONF_append = " --with-curl=${libdir}/.."
DEPENDS_${PN} += "libcurl-dev libcurl-dev-native"
PHP Staging Directory:
/installeddeps/curl-native
/installeddeps/curl-native.b77f37db31cf2391919a12c5c9774bff
/installeddeps/curl-native.complete
/usr/share/aclocal/libcurl.m4
/usr/bin/curl-config
/usr/bin/crossscripts/curl-config
/usr/bin/curl
/usr/lib/pkgconfig/libcurl.pc
/usr/lib/libcurl.so
/usr/lib/libcurl.a
/usr/lib/libcurl.so.4.4.0
/usr/lib/libcurl.so.4
/usr/include/curl
/usr/include/curl/curl.h
/usr/include/curl/curlrules.h
/usr/include/curl/curlbuild.h
/usr/include/curl/curlver.h
/usr/include/curl/easy.h
According to php manual, PHP/cURL feature is enabled at php configuration stage with --with-curl=[dir] option.
I checked the main recipe include file php.inc and couldn't find such configuration option. So, try creating in your working layer php_%.bbappend file with (or add this directly to the bottom of php.inc to test):
EXTRA_OECONF_append_class-target = " --with-curl=${STAGING_LIBDIR}/.."
DEPENDS_append_class-target = " curl"
Note, that curl package among DEPENDS because it is needed at build stage.
I don't think you need to update curl recipe with PACKAGES and FILES, pkg_config should take care

PHP Extension for C is failing to find function in C Library

Problem
I am learning to create a php extension. I have created a php extension for a basic hello world app. But the moment I try to include functions from the C library I am trying to entend then I get the following error message:
PHP Warning: PHP Startup: Unable to load dynamic library '/usr/lib/php5/20121212/hello.so' - /usr/lib/php5/20121212/hello.so: undefined symbol: nc_open in Unknown on line 0
This nc_open() function is the key function in the libary I am trying to extend
Process
I have created by header and config files and my c extension file which contains:
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "php.h"
#include "php_hello.h"
#include <netcdf.h>
...
PHP_FUNCTION(hello_world)
{
int status;
int ncid;
status = nc_open("sample.nc", 0, &ncid);
RETURN_LONG(status);
}
I have set up a directory (on Ubuntu) and run the phpize and configure steps. I run the make command which runs with no errors.
In my php.ini file I have the hello.so extension which points to symbolic link to the file I make.
I then restart the apache server on my local machine and then run:
php -r 'echo hello_world();'
and get:
- /usr/lib/php5/20121212/hello.so: undefined symbol: nc_open in Unknown on line 0
PHP Warning: Module 'xdebug' already loaded in Unknown on line 0
PHP Fatal error: Call to undefined function hello_world() in Command line code on line 1
PHP Stack trace:
PHP 1. {main}() Command line code:0
The error only occurs when I have a function from netcdf.h
The error does not occur from just having the include statement.
What I've tried:
Firstly I tried writing a basic c program to check that it would work, I managed to succeed by compiling it with:
gcc test.c -lnetcdf -o Test
and running ./Test
I tried using the following MakeFile
LDLIBS = -lnetcdf
but was unsuccessful.
What I would like:
Preferably to know how to get this library to work in my extension but I would settle for being pointed to documents or examples to help me understand what I need to know to accomplish this.
Update
Following Elliott Frisch's comments I have tried the
Setting the PHP_RPATHS=/usr/local
Setting /etc/ld.so.conf to:
include /etc/ld.so.conf.d/*.conf
/usr/lib
Changing the MakeFile to:
LDLIBS = -lnetcdf
LDFLAGS = -static
I am making the assumption that /usr/local is the correct directory due to it containing netcdf.so
I have added the following lines to my config.m4 file according to try adding the suggested functions
PHP_ADD_INCLUDE(/usr/lib)
PHP_ADD_LIBRARY_WITH_PATH(netcdf, /usr/lib, HELLO_SHARED_LIBADD)
Unfortunately I am still getting the problem so I am trying to understand what these functions mean to make sure I using them correctly. (The library I need to connect to is /usr/lib/libnetcdf.a and need to include netcdf.h from that file.)
You'll need to use PHP_ADD_LIBRARY_WITH_PATH & PHP_ADD_INCLUDE macros in config.m4 to handle linking. Autoconf's macros are also helpful for find & verifying existing libraries.
The best examples can be found in the ext directory of PHP's source code. Like ext/zlib
PHP_ADD_LIBPATH($ZLIB_DIR/$PHP_LIBDIR, ZLIB_SHARED_LIBADD)
PHP_ZLIB_DIR=$ZLIB_DIR
PHP_ADD_LIBRARY(z,, ZLIB_SHARED_LIBADD)
PHP_ADD_INCLUDE($ZLIB_INCDIR)
And more detailed examples in ext/oracle (from apple's open source labs)
PHP_ADD_LIBRARY(clntsh, 1, ORACLE_SHARED_LIBADD)
PHP_ADD_LIBPATH($ORACLE_DIR/lib, ORACLE_SHARED_LIBADD)
The issue was with an incorrectly configured config.m4 file.
I added the following that I modified from examples I found to get it to work:
if test "$PHP_HELLO" != "no"; then
SEARCH_PATH="/usr/local /usr" # you might want to change this
SEARCH_FOR="/include/netcdf.h" # you most likely want to change this
if test -r $PHP_HELLO/$SEARCH_FOR; then # path given as parameter
HELLO_INC_DIR=$PHP_HELLO/include
else # search default path list
AC_MSG_CHECKING([for netcdf.h in default path])
for i in $SEARCH_PATH ; do
if test -r $i/$SEARCH_FOR; then
HELLO_INC_DIR=$i/include
AC_MSG_RESULT(found in $i)
fi
done
fi
if test -z "$HELLO_INC_DIR"; then
AC_MSG_RESULT([not found])
fi
SEARCH_PATH="/usr/local /usr" # you might want to change this
SEARCH_FOR="/lib/libnetcdf.a" # you most likely want to change this
if test -r $PHP_HELLO/$SEARCH_FOR; then # path given as parameter
HELLO_LIB_DIR=$PHP_HELLO/lib
else # search default path list
AC_MSG_CHECKING([for libnetcdf in default path])
for i in $SEARCH_PATH ; do
if test -r $i/$SEARCH_FOR; then
HELLO_LIB_DIR=$i/lib
AC_MSG_RESULT(found in $i)
fi
done
fi
if test -z "$HELLO_LIB_DIR"; then
AC_MSG_RESULT([not found])
AC_MSG_ERROR([Please check the netCDF distribution])
fi
# --with-netcdf -> add include path
PHP_ADD_INCLUDE($HELLO_INC_DIR)
# --with-netcdf -> check for lib and symbol presence
LIBNAME=netcdf # you may want to change this
dnl O_LDFLAGS=$LDFLAGS
dnl LDFLAGS="$LDFLAGS -L$NETCDF_LIB_DIR -l$LIBNAME"
PHP_ADD_LIBRARY($LIBNAME)
LIBSYMBOL=nc_inq_libvers # you most likely want to change this
PHP_CHECK_LIBRARY($LIBNAME,$LIBSYMBOL,
[
PHP_ADD_LIBRARY($LIBNAME)
AC_DEFINE(HAVE_HELLO,1,[Build netCDF extension])
],[
AC_MSG_ERROR([wrong netCDF library version or lib not found])
])
PHP_SUBST(HELLO_SHARED_LIBADD)
HELLO_SHARED_LIBADD=-l$LIBNAME

PHP cross compilation failure

I try to cross compile PHP 5.3.25 for arm-merlin on x86_64 linux.
My configure command looks like the following:
export CC=/opt/mobilygen/tools/arm-merlin-linux-uclibc/i686-linux/bin/arm-merlin-linux-uclibc-gcc
./configure --prefix=/opt/php --host=arm-merlin-linux-uclibc --target=arm-merlin-linux-uclibc --build=x86_64-linux --without-iconv --without-pear --disable-ipv6 --without-openssl --without-sqlite --without-sqlite3 --disable-pdo --without-pdo-sqlite --with-libxml-dir=/opt/libxml2/ --includedir=/opt/mobilygen/tools/arm-merlin-linux-uclibc-SDK7r4552/i686-linux/arm-merlin-linux-uclibc/usr/include
The linker fails with:
ext/standard/php_crypt_r.o: In function `_crypt_extended_init_r':
/projects/php/php-5.3.25/ext/standard/php_crypt_r.c:101: undefined reference to `membar_producer'
/projects/php/php-5.3.25/ext/standard/php_crypt_r.c:102: undefined reference to `atomic_add_int'
collect2: ld returned 1 exit status
make: *** [sapi/cgi/php-cgi] Error 1
It seems that the SDK doesn't provide the correct sys/atomic.h library.
Is there a workaround for this? It would be also ok if the MD5 functionality is stripped.

swig fails for creating php libnetcdf extension

I need to interface libnetcdf with PHP. (the php-netcdf on google code is broken)
Here's netcdf.i :
%module netcdf
%{
/* Includes the header in the wrapper code */
#include "netcdf.h"
%}
/* Parse the header file to generate wrappers */
%include "netcdf.h"
I did :
gcc `php-config --includes` -fpic -c netcdf_wrap.c
gcc -shared netcdf_wrap.o -o netcdf.so
but when loading the extension in php, I get :
Unable to load dynamic library netcdf.so:
undefined symbol: ncerr in Unknown on line 0
It's the first time I try something like that. Am I missing something ?
ADDED -lnetcdf flag.
now, I got : undefined symbol: zend_error_noreturn. fixed replacing zend_error_noreturn by zend_error in netcdf_wrap.c
Your immediate problem is caused by not linking against libnetcdf. You need the -l flag for gcc to do so:
gcc -shared netcdf_wrap.o -o netcdf.so -lnetcdf
☝
php-netcdf at Google Code isn't broken, it's just unfinished and not maintained any more. However, one of the contributors, Santi Oliveras, seems to have managed to use it. Try to contact him, maybe he has some new code or something. Or feel free to take the project over.
P.S. I'm the author.

Categories