14

I'm building a program with autoconf, automake, and libtool. My work requires that I statically link (most) libraries. This hasn't been a problem in the past because I could statically link everything with -all-static. Now it's a problem because I have to use a library which is only dynamic; it was given to us by a thirdparty, and we don't have the source.

Of course, -all-static now causes the build to fail. Is it possible to tell libtool to statically link everything, except for this one library? Is it possible to have libtool do any combination of static and dynamic linking, or is it all or nothing?

So far I've tried creating a convenience library with LDFLAGS = -static, which depends on the libraries I want to statically link. But libtool doesn't concatenate the static libraries, like I would have hoped. The program depending on the convenience library still dynamically links everything.

I've also tried --disable-shared, but that didn't affect the build.


These questions are similar, but don't really answer my question:

Force linking a static library into a shared one with Libtool

Is it possible to link some — but not all — libraries statically with libtool?

(I don't want to delete shared libraries from my system, and specifing the full path for everything is hardly better than linking by hand, but maybe it's the only way.)

Community
  • 1
  • 1
tprk77
  • 1,151
  • 1
  • 9
  • 22

2 Answers2

13

You did not specify the operating system, but let us assume that it is a relatively recent Unix/Linux/OSX. If it is not, then ignore the following warning.

Before I answer, you should know that mixing static and shared code on most ELF-based systems (Unix/Linux) is problematic. One reason is because it can lead to code getting out of sync if you forget to relink an updated dependency. Another is due to the nature of static code vs. PIC. This is why libtool tries to discourage it.

That being said, in the Makefile.am (assuming your final program is foo and the shared library is):

    .
    .
    .
    foo_SOURCES = foo.c abc.c def.c hij.c
    foo_LDFLAGS = -all-static -Wl,-Bdynamic,-L/path/to,-lshared,-Bstatic
    foo_LDADD = -L../path/to -lbar -lbaz

What is important here is that libtool allows you to short-circuit the checks and GNU gcc's -static flag (which is used by libtool) by passing -Wl, arguments directly to the linker (GNU ld). To put spaces between arguments, the comma , delimiter is used.

Both -Bstatic and -Bdynamic are documented in GNU ld's info pages as well as the help screen. Again, since you did not mention the os or compiler package being used, I am assuming GNU gcc and GNU ld on Linux. You may want to verify by using ld --help to see for yourself. If, for some reason, it is not GNU ld, then you will need to find the equivalent flags to -Bstatic and -Bdynamic, substituting where appropriate.

Community
  • 1
  • 1
NickW
  • 146
  • 1
  • 5
  • 1
    This works, but at the loss of some flexibility. I don't need a dynamic build, but if I ever did I would need to edit some `Makefile.am`s, right? This also causes problems with macros like `AC_CHECK_LIB` (which just adds a `-l` to `LIBS`), but I guess that's to be expected. – tprk77 Dec 26 '12 at 14:03
  • 2
    I gave the simplest approach possible. However, for something fancy, you could pull the flags into your `configure.ac`. Once there, you could add `DYNLIBS="-Wl,-Bdynamic,-L/path/to,-lshared,-Bstatic"` with a call to `AC_SUBST([DYNLIBS])`. Then all you'd need to do is call `$(DYNLIBS)` in your `Makefile.am`. This would give you a more control, but remember that `AC_CHECK_LIBS` doesn't check for static vs. dynamic libs. Is that what you want or is there something else that would make it more flexible? – NickW Dec 27 '12 at 04:59
  • I am trying to do the opposite: link all libraries dynamically except given one (on the example of `cjpeg` target in [`Makefile.am`](https://github.com/mozilla/mozjpeg/blob/master/Makefile.am#L119)). I have changed `cjpeg_LDADD = -ljpeg` and added `cjpeg_LDFLAGS = -Wl,-Bstatic,-ljpeg,-Bdynamic` but still `libjpeg.so` is added to parameters and linked dynamically. If I say `cjpeg_LDADD = ` it complains about missing symbols. If I say `cjpeg_LDFLAGS = -Wl,-static` it fails with "attempted static link of dynamic object". The library itself is part of build process – maybe that causes the problem? – dma_k Dec 07 '16 at 11:30
  • Just discovered from [this answer](http://stackoverflow.com/a/10852489/267197) that one can achieve this via `./configure --disable-shared` (no further tricks with `Makefile.am` are necessary). Looks like this is the only workaround at the moment. – dma_k Dec 07 '16 at 15:39
0

In my case I wanted to link labA statically, but pthread dynamically. If I add libA to the Makefile.am as

my_proc_LDADD = -Wl,-Bstatic -lA -Wl,-Bdynamic

then ldd cannot link libA. libA should to specify in LDADD, but autotools does not allow it.

If I add to the Makefile.am LDADD as a comment

#my_proc_LDADD = -Wl,-Bstatic -lA -Wl,-Bdynamic

then it will also get added into the resulting Makefile as a comment So I simply uncomment this string after configure script:

./configure
sed -i -e 's/#my_proc_LDADD/my_proc_LDADD/g' ./src/Makefile
make

and as a result, statically linked libA is appended to LDADD

Maksim Kudimov
  • 178
  • 4
  • 17