How to link to shared lib from shared lib with relative path? - linux

I'm working on a Firefox plugin that uses external libraries to render 3D graphics on the browser.
The problem is that I want the plugin to use external libraries packed with it without changing the LD_LIBRARY_PATH variable.
The libraries are installed in a position relative to the plugin (a shared library too), while the actual executable (i.e. the browser) can be located somewhere entirely else.
I'm testing it on Ubuntu (no problem at Windows version of the plugin)
My dependencies are OpenSceneGraph libraries and static compilation will make the plugin really big (not an option if there is another one).

Use the rpath option when linking and specify the 'special' path $ORIGIN.
Example:
-Wl,-R,'$ORIGIN/../lib'
Here's a site that elaborates on using $ORIGIN:
http://www.itee.uq.edu.au/~daniel/using_origin/

You could maybe use the -L flag during the compilation to specify the relative path where the linker can find your shared objects.
If you have already generated your lib, you can link by directly invoking the ldcommand.
Tips : You can easily check if some symbols are defined in a lib using the unix command nm. This is a useful way to check that the linking is well-done.
(If I were you, I would just change temporaly the LD_LIBRARY_PATH as you said in your post. Why don't you want to do this ?)

It's wrong to use relative rpath for security reason,
You should use libdl functions (dlopen, etc)

Related

How to static link libexpat.so.1 with GCC?

I want to build statically program with GCC/G++ without shared dependencies. but i don't know how to do that.
With below command in Netbeans IDE i can build with shared dependency, but in some OS can not find this library(i don't want to install on new system)
-Wl,--dynamic-linker=/usr/lib/libexpat.so.1
To statically link a program, you need a static library, which is a library with a filename finished in .a.
Linker, by default, if using default search paths (as you do with /usr/lib), will select the .so library version and will do a dynamic link of it, so if you want to specify that you want some static library, you'll need to specify the full path name of it, instead of using the -l option. So,
gcc -o your_program mod_a.o mod_b.o ... /usr/lib/libexpat.a
is better than
gcc -o your_program mod_a.o mod_b.o ... -lexpat
(the latter will select the file /usr/lib/libexpat.so instead, which should be a link to /usr/lib/libexpat.so.1, which is normally the soname of the library, and is also a symbolic link of /usr/lib/libexpat.so.1.xx.xx)
NOTE
In the examples, I'm trying to call the linker through the compiler, as the default c runtime and libraries are automatically selected by the compiler when calling this way. If you prefer to call directly the linker, the procedure doesn't change, but then you have to add the C runtime module and the standard c library yourself.
NOTE 2
If you want to statically link everything, then you have to use static versions of all the libraries you are going to use (they are normally installed in the same directory as the dynamic ones, so you have to specify the full pathname of all in the command line) To cope with this in a permanent development system, you can make symbolic links to them all from another path and then specify that directory as the search path for your projects that must be statically linked.
If you allways want some library to be statically linked, just erase the .so link (not the .so.X and the .so.X.YY links, they are not tried by the compiler) in /usr/lib, and the .a file will be selected by default by the compiler. Of course, if you want this made for every library, you can erase all the .so links, but you'll end with larger executables (much larger) than the original dynamically linked versions.

Changing ncurses 6 "terminfo-dirs" after compilation/installation

There is a ncurses6 originally installed in a user home dir, let's say "/home/test", so a test environment was built over this ncurses path, a lot of (in development) apps were compiled and is working now, depending only of the current HOME env variable.
But, because of a purpose beyond our control, we have to change the user home dir. And now it's anything different from "/home/test".
The external apps and ncurses tools still working, we need just point the libraries with LD_LIBRARY_PATH and use a more specific path like we used before for ncurses tools:
LD_LIBRARY_PATH=~/bin/ncurses-6.0/lib ~/bin/ncurses-6.0/bin/tic
But now, after changing the user home dir, we need to point also the terminfo database:
TERMINFO=~/bin/ncurses-6.0/share/terminfo LD_LIBRARY_PATH=~/bin/ncurses-6.0/lib ~/bin/ncurses-6.0/bin/tic
But, is there any way to make the TERMINFO database path permanent without recompiling and reinstalling the ncurses ? Is it hard code in ncurses during compilation ?
The default values are compiled-in. You can override those with environment variables (TERMINFO is standard, TERMINFO_DIRS is an extension). That's not new with ncurses6 (it predates ncurses4, twenty years ago).
The most practical "permanent" change would be to put the overrides in your shell initialization.
It's possible to modify an ELF binary (there's no checksums), but the resulting path couldn't be longer. It could be shorter, since the strings are null-terminated. Since your example adds to the path, that wouldn't work for you, anyway.

How to discover the Paths to Loading Binaries

I have a problem where I need to know the filesystem path of the current binary, as well as those of any loading (as opposed to loaded) binaries. Here is an example (for Windows): Say we have an executable A.exe, which dynamically binds to B.dll, which in turn binds to C.dll. How could code executing in C.dll get the file paths of C.dll, B.dll, and A.exe?
Oh, and I need to be able to do it on Linux, Mac, and Windows.
On Linux, the closest thing I've found is dl_iterate_phdr, but the who-loaded-who info is missing.
On Windows, The Dynamic-Link functions don't have quite the right functionality.
On Mac, all I can find is what's in dlfcn.h, which is rather pithy for this purpose.
Thanks.

Visual C++ 2008: adding static libraries as relative address?

I'm adding the gtest libraries as with an absolute link to the project, but this wouldn't work on somebody else's machine if their source is downloaded elsewhere in the system. Is there a way to link to the .libs with relative address instead of absolute address? Thanks.
Just use a relative path; they work fine for lib file paths (and lib-folder paths in the project settings).
e.g. Instead of "C:\moo\cow.lib" you might put "..\..\moo\cow.lib" (depending on where you're starting from, of course).
(Edit: Fixed a \ char that got swallowed up.)

How to get a configure script to look for a library

I'm trying to write a configure.ac file such that the resulting configure script searches for a library directory containing a given static library e.g. libsomething.a. How can I do this? At the moment I have it check just one location with:
AC_CHECK_FILE([/usr/local/lib/libsomething.a],[AC_SUBST(libsomething,"-L/usr/local/lib -lsomething")],[AC_SUBST(libcfitsio,'')])
But I want it to try and find it automatically. And if the library isn't in one of the default locations, I'd like configure to say that the library wasn't found and that a custom location can be specified with --use-something=path as is usually done. So I also need to then check if --use-something=path is provided. I'm pretty new at creating configure files, and the M4 documentation isn't very easy to follow, so would appreciate any help.
Thanks!
It's not the job of configure to search where libraries are installed. it should only make sure they are available to the linker. If the user installed them in a different location, he knows how to call ./configure CPPFLAGS=-I/the/location/include LDFLAGS=-L/the/location/lib so that the tools will find the library (this is explained in the --help output of configure and in the standard INSTALL file).
Also --with-package and --enable-package macros are not supposed to be used to specify paths, contrary to what many third-party macros will do. The GNU Coding Standards explicitly prohibit this usage:
Do not use a --with option to
specify the file name to use to find
certain files. That is outside the scope
of what --with options are for.
CPPFLAGS and LDFLAGS are already here to address the problem, so why redevelop and maintain another mechanism?
The best way to figure this out is to look at other autoconf macros that do something similar. Autoconf macros are an amalgam of Bourne shell script and M4 code, so they can literally solve any computable problem.
Here's a link to a macro I wrote for MySQL++ that does this: mysql++.m4.

Resources