GNU bug report logs - #34219
libtool cannot statically link dependencies into shared C++ library

Previous Next

Package: libtool;

Reported by: Ulya Trofimovich <skvadrik <at> gmail.com>

Date: Sun, 27 Jan 2019 13:30:02 UTC

Severity: normal

Done: Ileana Dumitrescu <ileanadumitrescu95 <at> gmail.com>

Bug is archived. No further changes may be made.

Full log


View this message in rfc822 format

From: Ulya Trofimovich <skvadrik <at> gmail.com>
To: 34219 <at> debbugs.gnu.org
Cc: Sergei Trofimovich <slyfox <at> gentoo.org>
Subject: bug#34219: libtool cannot statically link dependencies into shared C++ library
Date: Sun, 27 Jan 2019 13:28:37 +0000
Hello!


I'm trying to build a portable DLL for windows with libtool. To do that,
I need to eliminate dynamic dependencies on libstdc++ and libgcc. With
GCC it is normally done by passing -static-libstdc++ -statlic-libgcc to
the linker.

I would want these commands to result in a shared library that has no
dynamic dependencies on libstdc++ and libgcc:

$ libtool --tag=CXX --mode=compile g++ -c foo.cc
$ libtool --tag=CXX --mode=link g++ \
    -static-libstdc++ -static-libgcc \
    -o libfoo.la foo.lo -rpath /usr/lib

First problem is that libtool doesn't recognize these options, and as a
result it does not pass them to linker. This can be worked around by
wrapping them in -Wc,-static-libstdc++ -Wc,-static-libgcc.

Second problem is that libtool adds hard-coded link option -nostdlib and
some predefined startup object files. Because of that, -static-libstdc++
-statlic-libgcc have no effect and the resulting shared library still
has dynamic dependencies on libstdc++ and libgcc.

Let me show what I mean on a simple example (I will build native
library, not DLL, because it's simpler and shows the same problem).
Let's say, source code of our library is in a file foo.cc:

$ cat foo.cc
#include <iostream>
void foo(void)
{
    std::cout << "foo" << std::endl;
}

Without libtool, I can build shared library like this:

$ g++ -shared -fPIC foo.cc -o libfoo.so
$ objdump -x libfoo.so | grep NEEDED
  NEEDED               libstdc++.so.6
  NEEDED               libm.so.6
  NEEDED               libgcc_s.so.1
  NEEDED               libc.so.6

Note the dependency on libstdc++. I can get rid of it like this:

$ g++ -shared -fPIC foo.cc -o libfoo.so -static-libstdc++ -static-libgcc
$ objdump -x libfoo.so | grep NEEDED
  NEEDED               libm.so.6
  NEEDED               libc.so.6
  NEEDED               ld-linux-x86-64.so.2

With libtool, however, I'm stuck:

$ libtool --tag=CXX --mode=compile g++ -c foo.cc
libtool: compile:  g++ -c foo.cc  -fPIC -DPIC -o .libs/foo.o
libtool: compile:  g++ -c foo.cc -o foo.o >/dev/null 2>&1

$ libtool --tag=CXX --mode=link g++ \
    -Wc,-static-libstdc++ -Wc,-static-libgcc \
    -o libfoo.la foo.lo -rpath /usr/lib
libtool: link: rm -fr  .libs/libfoo.a .libs/libfoo.la .libs/libfoo.lai
.libs/libfoo.so .libs/libfoo.so.0 .libs/libfoo.so.0.0.0
libtool: link: x86_64-pc-linux-gnu-g++  -fPIC -DPIC -shared -nostdlib
/usr/lib/gcc/x86_64-pc-linux-gnu/8.2.0/../../../../lib64/crti.o
/usr/lib/gcc/x86_64-pc-linux-gnu/8.2.0/crtbeginS.o  .libs/foo.o
-L/usr/lib/gcc/x86_64-pc-linux-gnu/8.2.0
-L/usr/lib/gcc/x86_64-pc-linux-gnu/8.2.0/../../../../lib64
-L/lib/../lib64 -L/usr/lib/../lib64
-L/usr/lib/gcc/x86_64-pc-linux-gnu/8.2.0/../../../../x86_64-pc-linux-gnu/lib
-L/usr/lib/gcc/x86_64-pc-linux-gnu/8.2.0/../../.. -lstdc++ -lm -lc
-lgcc_s /usr/lib/gcc/x86_64-pc-linux-gnu/8.2.0/crtendS.o
/usr/lib/gcc/x86_64-pc-linux-gnu/8.2.0/../../../../lib64/crtn.o
-static-libstdc++ -static-libgcc   -Wl,-soname -Wl,libfoo.so.0 -o
.libs/libfoo.so.0.0.0
libtool: link: (cd ".libs" && rm -f "libfoo.so.0" && ln -s
"libfoo.so.0.0.0" "libfoo.so.0")
libtool: link: (cd ".libs" && rm -f "libfoo.so" && ln -s
"libfoo.so.0.0.0" "libfoo.so")
libtool: link: x86_64-pc-linux-gnu-ar cru .libs/libfoo.a  foo.o
libtool: link: x86_64-pc-linux-gnu-ranlib .libs/libfoo.a
libtool: link: ( cd ".libs" && rm -f "libfoo.la" && ln -s "../libfoo.la"
"libfoo.la" )

$ objdump -x .libs/libfoo.so | grep NEEDED
  NEEDED               libstdc++.so.6
  NEEDED               libm.so.6
  NEEDED               libc.so.6
  NEEDED               libgcc_s.so.1

Even though options -static-libstdc++ -static-libgcc are passed to the
linker, hard-coded -nostdlib
/usr/lib/gcc/x86_64-pc-linux-gnu/8.2.0/../../../../lib64/crti.o
/usr/lib/gcc/x86_64-pc-linux-gnu/8.2.0/crtbeginS.o pulls in dynamic
dependencies.

As a temporary workaround, I'm using slibtool:

    https://github.com/midipix-project/slibtool

But I think this use case is very common and needs to be fixed in
libtool as well.

When using libtool with autotools (my original setting), I would want to
just pass these flags to configure:

    ./configure LDFLAGS="-static-libstdc++ -static-libgcc"

Currently I also have to override libtool program in make:

    make LIBTOOL=slibtool


-- 
Ulya




This bug report was last modified 36 days ago.

Previous Next


GNU bug tracking system
Copyright (C) 1999 Darren O. Benham, 1997,2003 nCipher Corporation Ltd, 1994-97 Ian Jackson.