How to load my own libxxx.so in php extension source code? - php-extension

I was given a libxxx.so file which i can't view it's source code and i can compile my c file with the next command:
gcc -ldl libxxx.so my.c -a a.out
a.out worked well in command line. But after i wrapped it into a PHP extension, PHP showed a message like this:
PHP Warning: PHP Startup: Unable to load dynamic library '/usr/lib64/php/modules/myextension.so' - /usr/lib64/php/modules/myextension.so: undefined symbol: xxxfunction in Unknown on line 0
xxxfunction is a function exported by libxxx.so.
I'm new to C and I think the problem is the way of compiling my PHP extension, i searched google but didn't find the answer.
I'm wondering whether there is an option like -ldl in gcc so i can specify that i'm going to use the libxxx.so in my PHP extention.
I compiled my extension by next steps:
cd myextension/
phpize
./configure
make
make install
I have moved libxxx.so file to /usr/local/lib.
My /etc/ld.so.conf:
include ld.so.conf.d/*.conf
/usr/local/lib
I have runed lddconfig.

You need to tell the build system to link against the shared library at compile time. This allows the dependency to be stored in the compiled PHP extension, where it will be loaded at first use.
To do this, you need to modify the config.m4 to add a library. You can do this via the PHP_ADD_LIBRARY macro. This macro adds a library to the link line and has the form PHP_ADD_LIBRARY($name,$append,$var). The first parameter is the name of the library; this is the name of the *.so file without the lib prefix (e.g. xxx). The second parameter determines (I presume) whether the line is appended or overwritten; this should usually be set to 1. The final parameter is the variable name into which the line is stored. This variable must be substituted into the output file via PHP_SUBST.
You should place your PHP_ADD_LIBRARY line somewhere before the PHP_NEW_EXTENSION macro in the config.m4 file. In addition, it's a good idea to wrap the PHP_ADD_LIBRARY in a PHP_CHECK_LIBRARY call. This ensures the library can be found by the build system before adding it. See my example below.
Here is another SO question that is similar to yours. It has some working examples you can follow. Additionally, I'll include a quick example here:
PHP_CHECK_LIBRARY(xxx,xxxfunction,[
PHP_ADD_LIBRARY(xxx,1,XXX_SHARED_LIBADD)
],[
AC_MSG_ERROR([Please install libxxx on the system])
],
[])
PHP_SUBST([XXX_SHARED_LIBADD])
Note: The second parameter to PHP_CHECK_LIBRARY is a function for which the build system will check if it finds the given library.

Related

Generate list files with CMake

I hope this is a simple question and I'm just missing something fundamental.
I'm trying to emulate a binary build manager for an embedded Cortex-M0 target using a CMake project. I'm having some trouble figuring out how to generate list files for each dependency of my executable target.
The current build system, when building a file called main.c passes -Wa,-alh=.\CortexM0\ARM_GCC_493\Debug/main.lst as an argument to gcc. I can't figure out how to get CMake to use the current filename without the extension to save the file.
I've looked at the get_filename_component command, but it appears only to get the filename of the output:
add_executable(TestExe main.c)
get_filename_component(curr_name TestExe NAME_WM)
message(${curr_name})
As expected, this prints TestExe instead of the hoped for main
Is there a simple variable I'm overlooking that I could put in my toolchain file's CMAKE_C_FLAGS like -Wa,-alh=${CURR_SOURCE}.lst? Or some other method that I'm not seeing?
System info:
Windows 10
Msys shell
CMake 3.7.2
arm-none-eabi-gcc v4.9.3
You can use Expansion Rules and extend CMAKE_C_COMPILE_OBJECT:
set(CMAKE_C_COMPILE_OBJECT "${CMAKE_C_COMPILE_OBJECT} -Wa,-alh=<OBJECT>.lst")
But there is unfortunately
no Expansion Rule that does give the current source file without path and extension
so you will get in the above example main.c.o.lst as an output name
Footnote: In CMake generated makefile projects, if you just need the assembly file can just do make main.s or for the pre-processed file make main.i.

What is the use of -Wl,-rpath in while making the executable from the library

We know that the command for making the executable is :
gcc -L/home/username/foo -Wall -o test main.c -lfoo
But if run ./test ,it will give error :
/test
./test: error while loading shared libraries: libfoo.so: cannot open shared object file: No such file or directory
There are 2 solutionss for it:
1)
LD_LIBRARY_PATH=/home/username/foo
2)
gcc -L/home/username/foo -Wl,-rpath=/home/username/foo -Wall -o test main.c -lfoo
my question is why do need to provide the library path to the loader??While making the execuatble I have explicilty mentioned the path such that the linker could create the excutable and I beleive there must be a refernce of the location of the library embedded in th execuatble
This a conceptual doubt i have ,plz clear it out.Thank you
It's just a choice that the linker designers made -- but a good one.
The reason it is good is that it lets you build a library, link against it, and then install the executable and library without requiring a re-link.
The cost is that you have to use LD_LIBRARY_PATH or the like to run the executable in the build tree; but normally this is no problem, as you can add the needed setting to make check or what have you.
If the default were flipped, then you would have to either relink at install time (which is a bit unfriendly since it is reasonably common to make install as root); or provide a flag to turn off the behavior at build time (but then you're back to the above...).
-Wl,rptath: Its actually build the executable feeding the information that where the loader will check for the library for loading.
Lets me give an example with 2 cases:
1)
If I transfer the library and executable to another machine and place them in 2 different location then I need to mention the path where the library is located by setting LD_LIBRARY_PATH.Then the loader will understand where to look for the loader while executing.
2)If i make the make the executable with -Wl,rpath= then I need to place the execuatble in the same path in another machine as the value of -Wl,rpath=.
So in simple terms we can say that we have the independency of placing the library with LD_LIBRARY_PATH

Problems compiling with libraries

I am trying to compile some C++ code which uses the CGAL library on OS X Lion. I downloaded and installed on some directory the CGAL library. Then, when I try to compile the code, using "make";
triangulation.h:18:64: error: CGAL/Exact_predicates_inexact_constructions_kernel.h: No such file or directory
which means it does not find the CGAL lib. I look at the Makefile, and I see that it compiles using the flag
-lCGAL
Wondering how to solve this, I guess I could pass the information about the placement of my compiled library to this variable, but I do not how. I tried with export and so on but it does not recognize it, any hints?
The error message doesn't mean the library isn't found; it means a header file isn't found. The -lCGAL switch does indeed refer to the library. You're going to need a -IXXXXX switch added on to CFLAGS, where XXXXX is the path to the directory containing the CGAL directory which in turn contains Exact_predicates_inexact_constructions_kernel.h .

How to specify non-default shared-library path in GCC Linux? Getting "error while loading shared libraries" when running

There is a laptop on which I have no root privilege.
onto the machine I have a library installed using configure --prefix=$HOME/.usr .
after that, I got these files in ~/.usr/lib :
libXX.so.16.0.0
libXX.so.16
libXX.so
libXX.la
libXX.a
when I compile a program that invokes one of function provided by the library with this command :
gcc XXX.c -o xxx.out -L$HOME/.usr/lib -lXX
xxx.out was generated without warning, but when I run it error like this was thrown:
./xxx.out: error while loading shared libraries: libXX.so.16: cannot open shared object file: No such file or directory , though libXX.so.16 resides there.
my clue-less assumption is that ~/.usr/lib wasn't searched when xxx.out is invoked.
but what can I do to specify path of .so , in order that xxx.out can look there for .so file?
An addition is when I feed -static to gcc, another error happens like this:
undefined reference to `function_proviced_by_the_very_librar'
It seems .so does not matter even though -L and -l are given to gcc.
what should I do to build a usable exe with that library?
For other people who has the same question as I did
I found a useful article at tldp about this.
It introduces static/shared/dynamic loaded library, as well as some example code to use them.
There are two ways to achieve that:
Use -rpath linker option:
gcc XXX.c -o xxx.out -L$HOME/.usr/lib -lXX -Wl,-rpath=/home/user/.usr/lib
Use LD_LIBRARY_PATH environment variable - put this line in your ~/.bashrc file:
export LD_LIBRARY_PATH=/home/user/.usr/lib
This will work even for a pre-generated binaries, so you can for example download some packages from the debian.org, unpack the binaries and shared libraries into your home directory, and launch them without recompiling.
For a quick test, you can also do (in bash at least):
LD_LIBRARY_PATH=/home/user/.usr/lib ./xxx.out
which has the advantage of not changing your library path for everything else.
Should it be LIBRARY_PATH instead of LD_LIBRARY_PATH.
gcc checks for LIBRARY_PATH which can be seen with -v option

linker woes - undefined reference

I'm having a problem with my compiler telling me there is an 'undefined reference to' a function I want to use in a library. Let me share some info on the problem:
I'm cross compiling with gcc for C.
I am calling a library function which is accessed through an included header which includes another header, which contains the prototype.
I have included the headers directory using -I and i'm sure it's being found.
I'm first creating the .o files then linking them in a separate command.
So my thought is it might be the order in which I include the library files, but i'm not sure what is the correct way to order them. I tried with including the headers folder both before and after the .o file.
Some suggests would be great, and maybe and explanation of how the linker does its thing.
Thanks!
Response to answers
there is no .a library file, just .h and .c in the library, so -l isn't appropriate
my understanding of a library file is that it is just a collection of header and source files, but maybe it's a collection of .o files created from the source?!
there is no library object file being created, maybe there should be?? Yes seems I don't understand the difference between includes and libraries...i'll work on that :-)
Thanks for all the responses! I learned a lot about libraries. I'd like to put all the responses as the accepted answer :-)
Headers provide function declarations and function definitions. To allow the linker find the function's implementation (and get rid of the undefined reference) you need to ask the compiler driver (gcc) to link the specific library where the function resides using the -l flag. For instance, -lm will link the math library. A function's manual page typically specifies what library, if any, must be specified to find the function.
If the linker can't find a specified library you can add a library search path using the -L switch (for example, -L/usr/local/lib). You can also permanently affect the library path through the LIBRARY_PATH environment variable.
Here are some additional details to help you debug your problem. By convention the names of library files are prefixed with lib and (in their static form) have a .a extension. Thus, the statically linked version of the system's default math library (the one you link with -lm) typically resides in /usr/lib/libm.a. To see what symbols a given library defines you can run nm --defined-only on the library file. On my system, running the command on libm.a gives me output like the following.
e_atan2.o:
00000000 T atan2
e_asinf.o:
00000000 T asinf
e_asin.o:
00000000 T asin
To see the library path that your compiler uses and which libraries it loads by default you can invoke gcc with the -v option. Again on my system this gives the following output.
GNU assembler version 2.15 [FreeBSD] 2004-05-23 (i386-obrien-freebsd)
using BFD version 2.15 [FreeBSD] 2004-05-23
/usr/bin/ld -V -dynamic-linker /libexec/ld-elf.so.1 /usr/lib/crt1.o
/usr/lib/crti.o /usr/lib/crtbegin.o -L/usr/lib /var/tmp//ccIxJczl.o -lgcc -lc
-lgcc /usr/lib/crtend.o /usr/lib/crtn.o
It sounds like you are not compiling the .c file in the library to produce a .o file. The linker would look for the prototype's implementation in the .o file produced by compiling the library
Does your build process compile the library .c file?
Why do you call it a "library" if it's actually just source code?
I fear you mixed the library and header concepts.
Let's say you have a library libmylib.a that contains the function myfunc() and a corresponding header mylib.h that defines its prototype. In your source file myapp.c you include the header, either directly or including another header that includes it. For example:
/* myapp.h
** Here I will include and define my stuff
*/
...
#include "mylib.h"
...
your source file looks like:
/* myapp.c
** Here is my real code
*/
...
#include "myapp.h"
...
/* Here I can use the function */
myfunc(3,"XYZ");
Now you can compile it to obtain myapp.o:
gcc -c -I../mylib/includes myapp.c
Note that the -I just tells gcc where the headers files are, they have nothing to do with the library itself!
Now you can link your application with the real library:
gcc -o myapp -L../mylib/libs myapp.o -lmylib
Note that the -L switch tells gcc where the library is, and the -l tells it to link your code to the library.
If you don't do this last step, you may encounter the problem you described.
There might be other more complex cases but from your question, I hope this would be enough to solve your problem.
Post your makefile, and the library function you are trying to call. Even simple gcc makefiles usually have a line like this:
LIBFLAGS =-lc -lpthread -lrt -lstdc++ -lShared -L../shared
In this case, it means link the standard C library, among others
I guess you have to add the path where the linker can find the libraray. In gcc/ld you can do this with -L and libraray with -l.
-Ldir, --library-path=dir
Search directory dir before standard
search directories (this option must
precede the -l option that searches
that directory).
-larch, --library=archive
Include the archive file arch in the
list of files to link.
Response to answers - there is no .a library file, just .h and .c in the library, so -l isn't approriate
Then you may have to create the libraray first?
gcc -c mylib.c -o mylib.o
ar rcs libmylib.a mylib.o
I have encountered this problem when building a program with a new version of gcc. The problem was fixed by calling gcc with the -std=gnu89 option. Apparently this was due to inline function declarations. I have found this solution at https://gcc.gnu.org/gcc-5/porting_to.html

Resources