greengeek wrote:I feel I'm not explaining this too well.
Well, I think I know what you are saying, although using the term "static programs" is confusing, since (as amigo has already pointed-out), it makes one think of statically-linked programs, which create no such problems with searching for libraries, since the necessary code is already in the executable binary. But you seem to be looking for something else.
I think you are actually referring to programs that use shared objects (e.g., shared libraries) and have one or more of their own libraries segregated from the general collections of libraries used by other programs. Right?
greengeek wrote:Those libs are expected to be in, say, usr/lib. However, some other static program may already be using usr/lib as storage for its own libs, and those libs may share the same name as the libs for the new program.
So if I understand you correctly, you are talking about a situation where a program uses a library that has the same name as a library that already exists in the /usr/lib/ directory, but is totally different.
If that is the case, then, yes, there are ways of handling that situation.
The ideal, of course, would be for the developer of the library to come up with a new name. But in a world with thousands of people developing libraries, such name conflicts are inevitable, and convincing one developer that her library should be the one that is renamed, and not the other, may not be easy.
So you get to work around the conflict.
As you have already guessed, you will create a new directory in which to put the library. Let's call it "/usr/local/lib/example_app/". And let's call the library "libexample.so.0", and the program "example_app".
So, in this example, you would have an existing library at /usr/lib/libexample.so.0 and a different library for use by example_app at /usr/local/lib/example_app/libexample.so.0 .
There are various methods that can be used to tell the loader to look in the latter directory at run time.
1. RUNPATH
If you have the source code, you can set the RUNPATH attribute at build time. This attribute is used to define a library search path and lives in the executable file, where the loader will find it at run time. Here is a simple example (which is all one long line):
Code: Select all
gcc -o example_app example_app.c -L/usr/local/lib/example_app -lexample -Wl,-rpath=/usr/local/lib/example_app,--enable-new-dtags
Unfortunately, although this is perhaps the best way to do what you want, this probably won't work for you in Puppy because many (perhaps all?) Puppies set the LD_LIBRARY_PATH environmental variable, which overrides RUNPATH. (I do not know why Puppy does this. The usual way to define the general library search path is to use the /etc/ld.so.conf file and ldconfig. LD_LIBRARY_PATH is usually just used temporarily for stuff like testing new libraries and debugging.)
2. RPATH
This is an older method of defining a library search path in the executable, using the RPATH attribute. This method is deprecated, since it cannot be overridden by LD_LIBRARY_PATH, which caused many headaches in the past because sometimes it is useful to be able to override the path. So it was replaced by RUNPATH, which is overridable. (Actually, the
-rpath combined with the
--enable-new-dtags options sets
both RUNPATH and RPATH, but if RUNPATH is set, modern loaders ignores RPATH.)
RPATH is set similarly to the way RUNPATH was set, but without the
--enable-new-dtags option:
Code: Select all
gcc -o example_app example_app.c -L/usr/local/lib/example_app -lexample -Wl,-rpath=/usr/local/lib/example_app
The above code is simplified to illustrate the options that need to be passed to the linker. But in the real world you are unlikely to be calling gcc directly to build a source package. You will probably need to either pass them to a configuration script, or set them manually in a Makefile (for instance, using LDFLAGS). Of course, the exact details of doing so will depend on the source package.
Because it is deprecated, I would not recommend that anyone use this method on a large-scale basis, but to solve an occasional problem like your library name conflict on Puppy, it could be useful.
By the way, the following command will show you if RPATH or RUNPATH are set in a program:
Code: Select all
readelf --dynamic example_app | grep -E "RPATH|RUNPATH"
3. LD_LIBRARY_PATH
This might be what you need if you have only the executable binary, not the source code, and therefore cannot set the RUNPATH or RPATH variables at build time.
As previously mentioned, LD_LIBRARY_PATH is usually just used temporarily for stuff like testing new libraries and debugging, but if the RUNPATH and RPATH methods are not available to you, this could do the job. For example, on the command line:
Code: Select all
LD_LIBRARY_PATH=/usr/local/lib/example_app:$LD_LIBRARY_PATH example_app
or in a wrapper script:
Code: Select all
#!/bin/bash
export LD_LIBRARY_PATH=/usr/local/lib/example_app:$LD_LIBRARY_PATH
exec example_app
Note that the the new LD_LIBRARY_PATH also includes the old LD_LIBRARY_PATH, but the new directory is first in the path so that it is searched first. Of course, if all the needed libraries are in the new directory, or in /lib/ or /usr/lib/, or in /etc/ld.so.cache, you don't need the old value of LD_LIBRARY_PATH, and can simply use "LD_LIBRARY_PATH=/usr/local/lib/example_app".
Note also that the above examples cause LD_LIBRARY_PATH to be set to its new value only for running example_app. You would not want to set it permanently for a couple of reasons: first, because doing so would cause the loader to search the new directory first for libraries when running
any program, which would be inefficient, and second, because the other library with the same name at /usr/lib/libexample would never be found when it was needed, since the one in the new directory would always be found first.
Be aware that this method will not work with programs that have their set-uid or set-gid permission bits set (unless, respectively, the user ID matches the file's owner or the user is a member of the file's group). (Allowing users to cause their own libraries to be loaded in such programs would, obviously, be a very large security hole.)
4. LD_PRELOAD
If you are just dealing with one or a few libraries, you could use this method to list those specific libraries so that the loader will load them first. It works similarly to LD_LIBRARY_PATH except that you list the absolute name of each library, not just the directory. (Normally this is used for stuff like testing a new library.)
For example, on the command line:
Code: Select all
LD_PRELOAD=/usr/local/lib/example_app/libexample.so.0 example_app
or in a wrapper script:
Code: Select all
#!/bin/bash
export LD_PRELOAD=/usr/local/lib/example_app/libexample.so.0
exec example_app
As was the case with LD_LIBRARY_PATH, this LD_PRELOAD method won't work with programs that have their set-uid or set-gid permission bits set (unless, respectively, the user ID matches the file's owner or the user is a member of the file's group).
Further reading - - -
I've tried to give a brief overview of some of your options, but I've probably not explained it well enough to make it really clear. Here are a few suggestions that may help to clear things up:
Program Library HOWTO Shared Libraries by David A. Wheeler
ld.so( 8 ) - Linux manual page
RPATH, RUNPATH, and dynamic linking by W. Trevor King