Re: Forcing static link of libstdc++

From:

Ralf Wildenhues

Subject:

Re: Forcing static link of libstdc++

Date:

Tue, 26 Sep 2006 09:17:29 +0200

User-agent:

Mutt/1.5.13 (2006-09-08)

Hello Mike, Bob,
* Bob Proulx wrote on Tue, Sep 26, 2006 at 04:41:19AM CEST:
>
> Unless the shared library is using rpath. In which case it will use
> the compiled in path first and only if that fails will it fall back to
> using LD_LIBRARY_PATH and if that fails fall back to using whatever is
> configured for the system in /etc/ld.so.conf.
I feel obliged to point out that the order of priority here is system
dependent. On most GNU/Linux distributions, it works as you say; on
Gentoo, LD_LIBRARY_PATH overrides the hardcoded path (because they patch
their ld to set both DT_RPATH and DT_RUNPATH); FWIW, on other systems
it may depend on linker flags (HP-UX/PA, for example), the rpath always
wins (e.g., IRIX) or never wins (e.g., NetBSD).
> (I do not like rpath because it freezes the configuration into an
> inflexible state.)
But also it allows programs to work without having the user to set an
ever-longer LD_LIBRARY_PATH. It's a two-edged sword.
> Mike Melanson wrote:
> > This is a proprietary plugin that another program is expected to
> > load and call. Is there some sort of wrapper trick for that, or is
> > that up to the communication between the app and the plugin?
>
> Everything depends upon how the application is loading the shared
> library. If it done by the linker then ld.so will load it and
> LD_LIBRARY_PATH should work to find it. If the application is
> dynamically loading a specific file from the filesystem then you are
> stuck with whatever the application allows you to adjust.
Yes.
Linking libstdc++ statically into your plugin won't do what you like,
if the libstdc++ used by other parts of the program you run is not
binary compatible. It simply won't work, and I think
http://www.trilithium.com/johan/2005/06/static-libstdc/ summarizes
that nicely.
You may also want to note that linking libstdc++ statically into a
plugin won't necessarily do what you want, i.e., use its symbols
rather than the ones from a system's libstdc++ that has been loaded
earlier because the program (or some library it depends upon) uses
that. The reverse may also happen (some plugin dlopened later may
just happen to use some symbols of your copy rather than the installed
libstdc++ ones'). This is how ELF linking works.
Do you use something like symbolic linkage for symbols inside your
module (to prevent the first problem), and hide all the libstdc++
symbols that end up in your module (to prevent the second problem)?
Below's a small recipe to show the first of the two issues.
If you're seeing weird bugs, or browsers that use your plugin see them
with other bugs, you may want to read this again. Note I am not
suggesting that you go this route (not at all), because closing the
potential incompatibility between your plugin and the libstdc++ symbols
it uses, just opens up the potential incompatibility between the
libstdc++ symbols you use, and the ones the rest of the program uses.
I would think building two different plugins, one for version 5 and one
for version 6 is a safer bet. And of course, allowing users and
distributions to build from source is a much safer bet.
Cheers,
Ralf
cat >a.c <<EOF
double sin(double x)
{
return 0.0;
}
EOF
cat >b.c <<EOF
extern double sin(double);
double b() { return sin(1.0);}
EOF
cat >m.c <<EOF
#include <stdlib.h>
#include <stdio.h>
#include <dlfcn.h>
#include <math.h>
int main(int argc, char **argv)
{
void *handle;
double (*ptr_b)(void);
char *error;
handle = dlopen ("libb.so", RTLD_LAZY);
if (!handle) {
fprintf (stderr, "%s\n", dlerror());
exit(1);
}
dlerror(); /* Clear any existing error */
*(void **) (&ptr_b) = dlsym(handle, "b");
if ((error = dlerror()) != NULL) {
fprintf (stderr, "%s\n", error);
exit(1);
}
printf ("%f\n", (*ptr_b)());
printf ("%f\n", sin(1.0));
dlclose(handle);
return 0;
}
EOF
gcc -fPIC -c a.c
ar cru liba.a a.o
gcc -fPIC -c b.c
gcc -shared -o libb.so b.o liba.a
gcc -c m.c
gcc -o m m.o -ldl -lm
LD_LIBRARY_PATH=. ./m
# then try adding -Wl,-Bsymbolic to the link creating libb.so