Subject: bug#34219: closed (bug#34219: libtool cannot statically link dependencies into shared C++ library)

From: [email-masked] (GNU bug Tracking System)
Date: Tue, 15 Apr 2025 15:28:03 +0000

Your bug report

#34219: libtool cannot statically link dependencies into shared C++ library

which was filed against the libtool package, has been closed.

The explanation is attached below, along with your original report.
If you require more details, please reply to [email-masked].

-- 
34219: https://debbugs.gnu.org/cgi/bugreport.cgi?bug=34219
GNU Bug Tracking System
Contact [email-masked] with problems

Subject: bug#34219: libtool cannot statically link dependencies into shared C++ library
From: Ileana Dumitrescu <[email-masked]>
To: [email-masked]
Cc: Ulya Trofimovich <[email-masked]>
Date: Tue, 15 Apr 2025 18:27:28 +0300
List-Id: <debbugs-submit.debbugs.gnu.org>

Thank you for your bug submission. This issue should be fixed by
utilizing a new configuration option, --enable-cxx-stdlib, so I
am closing this bug. If the bug still exists after re-configuring
your project, I will reopen.

https://git.savannah.gnu.org/cgit/libtool.git/commit/?id=9bc7536bd8755f3b63118613496a89671512f2db

-- 
Ileana Dumitrescu

GPG Public Key: FA26 CA78 4BE1 8892 7F22 B99F 6570 EA01 146F 7354

Subject: libtool cannot statically link dependencies into shared C++ library
From: Ulya Trofimovich <[email-masked]>
To: [email-masked]
Cc: Sergei Trofimovich <[email-masked]>
Date: Sun, 27 Jan 2019 13:28:37 +0000
List-Id: <debbugs-submit.debbugs.gnu.org>

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