Why does my static build require shared libraries?
Every so often I get these warnings from my linker... (at the moment it is happening with openssh-5.2p1)
The warnings look similar to:
"Using 'function' in statically linked applications requires at runtime the shared libraries from the glibc version used for..."
When I google, I only see fixes, not reasons.
Thanks,
Chenz
It doesn't require shared libs per se, it just warns you that some things might not work properly if you link statically to glibc.
Some of those things are the nsswitch, see e.g. /etc/nsswitch.conf .On a system different ways of looking up users/groups/hostnames and other things can be configured and altered via plugins - e.g. samba comes with a module for managing users configured on a windows domain/active directory transparently.
Your app will not honor /etc/nsswitch.conf customization if you link statically to glibc, functions such as gethostbyname,getpwuid and others will just use the default ways of looking up things.
Same goes for e.g. other libraries your app might use that for whatever reason dlopen()s itself to hook into glibc or similar.
See also
Statically linking considered harmful
Related
I have a project, where I want to link one of system libraries statically. The project uses GNU build system.
In configure.ac I have:
AC_CHECK_LIB(foobar, foobar_init)
On development machine this library is installed in /usr/lib/x86_64-linux-gnu. It is detected, but it is linked dynamically, which causes issues, as it is not present on some machines. Linking it statically (-Wl,-Bstatic etc.) works fine, but I don't know how to set this up in autotools. I tried forcing this into Makefile.am link flags for the project, but it still gives a preference to dynamic library.
I also tried using --enable-static with ./configure, but it seems to have no effect on system libraries.
If you want to link the whole program statically, then you should pass the --disable-shared option to configure. You might or might not need also to pass --enable-static, depending on the default value for that option (which you can influence via your configure.ac file). You really should consider doing this.
You should also consider making this the installer's problem, not the build system's. Let it be the installer's responsibility to ensure that all the shared libraries needed by the program are provided by the systems where it is installed. This is very common; in fact, it is one of the inspirations for package-management systems such as yum / dnf and apt, and their underlying packaging formats.
If you insist on linking only one library statically, while linking everything else dynamically, then you'll need to jump through a few more hoops. The objective will be to emit link options that cause just that library to be linked statically, without changing other libraries' linking. With the GNU toolchain, and supposing that the program is otherwise being linked dynamically, that would be this combination of options:
-Wl,-Bstatic -lfoobar -Wl,-Bdynamic
Now consider the documentation of the AC_CHECK_LIB() macro:
Macro: AC_CHECK_LIB (library, function, [action-if-found],
[action-if-not-found], [other-libraries])
[...] action-if-found is a list of shell commands to run if the link with the library succeeds; action-if-not-found is a list of shell
commands to run if the link fails. If action-if-found is not
specified, the default action prepends -llibrary to LIBS and defines
'HAVE_LIBlibrary' (in all capitals). [...]
Note in particular the default behavior in the event that the optional arguments are not provided (your present case) -- that's not quite what you want, at least not by itself. I suggest providing at least an alternative behavior for action-if-found case, and you could consider also making configure fail in the action-if-not-found case. The latter is left as an exercise; implementing just the former might look like this:
AC_CHECK_LIB([foobar], [foobar_init], [
LIBS="-Wl,-Bstatic -lfoobar -Wl,-Bdynamic $LIBS"
AC_DEFINE([HAVE_LIBFOOBAR], [1], [Define to 1 if you have libfoobar.])
])
You should also pay attention to the order of your AC_CHECK_LIB() invocations. As its docs go on to say:
This macro is intended to support building LIBS in a right-to-left
(least-dependent to most-dependent) fashion such that library
dependencies are satisfied as a natural side effect of consecutive
tests. Linkers are sensitive to library ordering so the order in which
LIBS is generated is important to reliable detection of libraries.
If you find that you still aren't getting what you want, then have a look at the link commands that make actually executes. You need to understand what's wrong about them before you can determine how to fix the problem.
With all that said, I observe that the above treatment is basically a hack, and it makes your build system much less resilient. It introduces dependencies on GNU toolchain options (which some other toolchains may nevertheless accept), and it assumes dynamic linking is being performed overall. It may be possible to resolve those issues with additional Autoconf code, but I urge you to instead go with one of the first two alternatives I described.
I've been writing a Python extension use the Python/C API to read data out of a .ROOT file and store it in a list of custom objects. The extension itself works just fine, however when I tried to use it on a different machine I ran into some problems.
The code depends upon several libraries written for the ROOT data manipulation program. The compiler is linking these libraries dynamically, which means I cannot use my extension on a machine that does not have ROOT installed.
Is there a set of flags that I can add to my compilation commands to make these libraries statically linked? Obviously this would make the file size much larger but that isn't much of an issue providing that the code runs at the same speed.
I did think about collating all of the ROOT libraries that I need into an 'archive' file. I'm not too familiar with this so I don't know if that's a good idea or not.
Any advice would be great, I've never really dealt with the static/dynamic library issue before.
Thanks, Sean.
Question:
Why were static libraries /usr/lib/*.a dropped from Solaris 10?
So it is NOT possible to generate statically-linked object?
Dynamically-linked compilation, is the only option?
You can still create your own *.a libraries and link to them, but the system libraries will always be dynamically linked.
See: this post from blogs.oracle.com
If you pass the right flags to the linker, then you can create a static library or application. However, why would you want to? Static libraries are a pain to provide fixes for.
It's a wise decision. The static linking idea does not really work well. Thats why LSB (Linux Standard Base) Project also forbids static linking. Compatibility moved away from system calls to a higher level in the last two decades.
Can't say I've ever gone looking for them, but did you check the "additional options" (or whatever they call it) CD/DVD? I remember it had other random "missing" things...
I am working on a project which is built using autoconf, automake and libtool. The project is distributed in both binary and source form.
On Linux, by default the build script links to all libraries dynamically. This makes sense since Linux users can rely on their distribution’s package manager to handle dependencies.
On Windows, by default the build script links to all libraries statically using libtool’s -all-static option. This makes sense since none of the dependencies are provided with Windows, and it’s helpful to be able to distribute a single binary containing all dependencies rather than mucking about distributing tons of DLLs.
On OSX, some of the dependencies are provided by the OS, and some are not. Therefore it would be helpful to link to the OS-provided libraries dynamically and to the other libraries statically. Unfortunately libtool’s all-or-nothing -all-static option is not helpful here.
Is there a good way to get libtool to link to some libraries statically, but not all?
Note: I realise I could carefully compile the dependencies so that only static builds are available. However, I’d rather the build system for my project were robust in the common case of static and dynamic builds of dependencies being available.
Note: Of course, I am not concerned with really low level dependencies like the C/C++ runtime libraries, which are always linked dynamically on all three of the above platforms.
After some research I have answered my own question.
If you have static and dynamic builds of a library installed, and you link to that library using the -l parameter, libtool links by preference to the dynamic build. It links to a static build if there is no dynamic build available, or if you pass the -static or -all-static options.
libtool can be forced to link to the static library by giving the full path to that library in place of the -l option.
I have a gcc-compiled application linked against dynamic libraries. Is there a way to impose the order in which libraries are loaded? (In my case one library constructor uses resources set up by other library constructor).
Thanks.
gcc isn't in-charge of loading the libraries, either ld.so does it automatically when your program loads, or you do it manually as #jldupont suggests.
And ld.so might deliberately randomise the order to prevent return-to-stdlib attacks.
So either:
Load the libraries yourself.
Or remove the dependencies between the library load scripts.
Make the libraries contain the dependencies themselves (might work, might not)
That is when you get to the point of linking each shared library, make sure it includes -l<dependentlib> in the link command. You can test this by creating a trival program that links only with that shared library - if it builds and runs, then the library contains all necessary dependent libs. This might help if ld.so loads the libraries in dependency order - which I think it has to do.
You can use dlopen and load the libraries yourself: this way, you can have a finer grain control over the loading/unloading process. See here.
Of course, this isn't a "gcc" based solution and it requires reworking your application... Maybe you could explain the "problem" you are facing in a bit more details?
You can disregard my solution if it doesn't fit your needs. Cheers!