GNU bug report logs - #78072
Libtool incorrectly tries to use shared library when linking statically

Previous Next

Package: libtool;

Reported by: Mike Krinkin <krinkin.m.u <at> gmail.com>

Date: Sat, 26 Apr 2025 06:06:04 UTC

Severity: normal

To reply to this bug, email your comments to 78072 AT debbugs.gnu.org.

Toggle the display of automated, internal messages from the tracker.

View this report as an mbox folder, status mbox, maintainer mbox


Report forwarded to bug-libtool <at> gnu.org:
bug#78072; Package libtool. (Sat, 26 Apr 2025 06:06:04 GMT) Full text and rfc822 format available.

Acknowledgement sent to Mike Krinkin <krinkin.m.u <at> gmail.com>:
New bug report received and forwarded. Copy sent to bug-libtool <at> gnu.org. (Sat, 26 Apr 2025 06:06:04 GMT) Full text and rfc822 format available.

Message #5 received at submit <at> debbugs.gnu.org (full text, mbox):

From: Mike Krinkin <krinkin.m.u <at> gmail.com>
To: bug-libtool <at> gnu.org
Subject: Libtool incorrectly tries to use shared library when linking
 statically
Date: Fri, 25 Apr 2025 19:53:01 +0100
[Message part 1 (text/plain, inline)]
Hi There,

I hit a weird behaviour when build colm as part of building Envoy proxy.
Cutting through layers of the stack on top of the libtool things here is
what things boil down to:

1. we have a project using autogen/configure/libtool that was configured
with `--enable-static` and `--disable-shared`
2. when I run make on the project one of the linking steps failed with the
following error:

```
ld.lld: error: attempted static link of dynamic object /usr/lib/libstdc++.so
```

Looking at the debug logs for the libtool invocations here is what I see:

```
/bin/sh ../libtool
  --tag=CXX
  --mode=link
  /usr/bin/clang-18
  -Wall

-DINCLUDEDIR='"/root/.cache/bazel/_bazel_root/37e3aec351bcd85a6ea8b58e3592ef6e/sandbox/processwrapper-sandbox/3/execroot/envoy/bazel-out/k8-opt/bin/bazel/foreign_cc/colm.build_tmpdir/colm/include"'

-DLIBDIR='"/root/.cache/bazel/_bazel_root/37e3aec351bcd85a6ea8b58e3592ef6e/sandbox/processwrapper-sandbox/3/execroot/envoy/bazel-out/k8-opt/bin/bazel/foreign_cc/colm.build_tmpdir/colm/lib"'

-DABS_TOP_BUILDDIR='"/root/.cache/bazel/_bazel_root/37e3aec351bcd85a6ea8b58e3592ef6e/sandbox/processwrapper-sandbox/3/execroot/envoy/bazel-out/k8-opt/bin/bazel/foreign_cc/colm.build_tmpdir"'

-DABS_BUILDDIR='"/root/.cache/bazel/_bazel_root/37e3aec351bcd85a6ea8b58e3592ef6e/sandbox/processwrapper-sandbox/3/execroot/envoy/bazel-out/k8-opt/bin/bazel/foreign_cc/colm.build_tmpdir/src"'
  -DCONS_INIT
  -U_FORTIFY_SOURCE
  -fstack-protector
  -Wall
  -Wthread-safety
  -Wself-assign
  -Wunused-but-set-parameter
  -Wno-free-nonheap-object
  -fcolor-diagnostics
  -fno-omit-frame-pointer
  -g0
  -O2
  -D_FORTIFY_SOURCE=1
  -DNDEBUG
  -ffunction-sections
  -fdata-sections
  -stdlib=libc++
  -no-canonical-prefixes
  -Wno-builtin-macro-redefined
  -D__DATE__=redacted
  -D__TIMESTAMP__=redacted
  -D__TIME__=redacted
  -DABSL_MIN_LOG_LEVEL=4
  -fdebug-types-section
  -fPIC
  -Wno-deprecated-declarations
  -std=c++20 -fsized-deallocation
  --static
  -lstdc++
  -Wno-unused-command-line-argument
  -L.
  -Wl,--gdb-index
  -fuse-ld=/usr/bin/ld.lld
  -B/usr/bin
  -Wl,-no-as-needed
  -Wl,-z,relro,-z,now
  -lm
  -pthread
  -Wl,--gc-sections
  -l:libc++.a
  -l:libc++abi.a
  -fuse-ld=lld
  -o bootstrap0 bootstrap0-consinit.o bootstrap0-main.o libprog.a libcolm.la
```

NOTE: I split it in multiple lines to make it easier to read, originally it
was a single line.

There is a lot there, but two things that I believe are particularly
relevant are: `--static` and `-lstdc++` flags.
I believe that libtool next translated it into an actual command to link
the binary and from the logs here is what I saw:

```
/usr/bin/clang-18
  -Wall

-DINCLUDEDIR=\"/root/.cache/bazel/_bazel_root/37e3aec351bcd85a6ea8b58e3592ef6e/sandbox/processwrapper-sandbox/3/execroot/envoy/bazel-out/k8-opt/bin/bazel/foreign_cc/colm.build_tmpdir/colm/include\"

-DLIBDIR=\"/root/.cache/bazel/_bazel_root/37e3aec351bcd85a6ea8b58e3592ef6e/sandbox/processwrapper-sandbox/3/execroot/envoy/bazel-out/k8-opt/bin/bazel/foreign_cc/colm.build_tmpdir/colm/lib\"

-DABS_TOP_BUILDDIR=\"/root/.cache/bazel/_bazel_root/37e3aec351bcd85a6ea8b58e3592ef6e/sandbox/processwrapper-sandbox/3/execroot/envoy/bazel-out/k8-opt/bin/bazel/foreign_cc/colm.build_tmpdir\"

-DABS_BUILDDIR=\"/root/.cache/bazel/_bazel_root/37e3aec351bcd85a6ea8b58e3592ef6e/sandbox/processwrapper-sandbox/3/execroot/envoy/bazel-out/k8-opt/bin/bazel/foreign_cc/colm.build_tmpdir/src\"
  -DCONS_INIT
  -U_FORTIFY_SOURCE
  -fstack-protector
  -Wall
  -Wthread-safety
  -Wself-assign
  -Wunused-but-set-parameter
  -Wno-free-nonheap-object
  -fcolor-diagnostics
  -fno-omit-frame-pointer
  -g0
  -O2
  -D_FORTIFY_SOURCE=1
  -DNDEBUG
  -ffunction-sections
  -fdata-sections
  -stdlib=libc++
  -no-canonical-prefixes
  -Wno-builtin-macro-redefined
  -D__DATE__=redacted
  -D__TIMESTAMP__=redacted
  -D__TIME__=redacted
  -DABSL_MIN_LOG_LEVEL=4
  -fdebug-types-section
  -fPIC
  -Wno-deprecated-declarations
  -std=c++20
  -fsized-deallocation
  --static
  -Wno-unused-command-line-argument
  -Wl,--gdb-index
  -fuse-ld=/usr/bin/ld.lld
  -B/usr/bin
  -Wl,-no-as-needed
  -Wl,-z
  -Wl,relro
  -Wl,-z
  -Wl,now
  -Wl,--gc-sections
  -fuse-ld=lld
  -o bootstrap0 bootstrap0-consinit.o bootstrap0-main.o
 /usr/lib/libstdc++.so
  -L. libprog.a
  ./.libs/libcolm.a
  -lm
  -l:libc++.a
  -l:libc++abi.a
  -pthread
```

It's pretty close to what we asked libtool to do with a few differences: it
does not have -lstdc++ flag and instead passes /usr/lib/libstdc++.so along
with other object files as input to the linker which obviously does not
work.

My understanding is that libtool looked at -lstdc++ flag, found a
corresponding libstdc++.la file and "resolved" it into a shared library.

What I'm baffled by in this case is why did libtool resolve it to a shared
library instead of a static one, even though it's clearly a static build?
Moreover, even if we wanted to link against the dynamic library, it should
be done via -l flag, so what libtool looks very weird - we can't just link
shared library as if it was a object file or a static library.
Am I missing something or libtool is completely off the mark here and
trying to do something weird?


Both shared and static libraries are present (and in the right directory)
and la file looks reasonable otherwise:

```
# libstdc++.la - a libtool library file
# Generated by libtool (GNU libtool 1.3134 2009-11-29) 2.2.7a
#
# Please DO NOT delete this file!
# It is necessary for linking the library.

# The name that we can dlopen(3).
dlname='libstdc++.so.6'

# Names of this library.
library_names='libstdc++.so.6.0.32 libstdc++.so.6 libstdc++.so'

# The name of the static archive.
old_library='libstdc++.a'

# Linker flags that can not go in dependency_libs.
inherited_linker_flags=''

# Libraries that this one depends upon.
dependency_libs=' -lm'

# Names of additional weak libraries provided by this library
weak_library_names=''

# Version information for libstdc++.
current=6
age=0
revision=32

# Is this an already installed library?
installed=yes

# Should we warn about portability when linking against -modules?
shouldnotlink=no

# Files to dlopen/dlpreopen
dlopen=''
dlpreopen=''

# Directory that this library needs to be installed in:
libdir='/usr/lib'
```

If I just deleate the .la file all together, it skips the libtool siliness
and things just work (that's how we are working around the issue now).

Thank you.
[Message part 2 (text/html, inline)]

Information forwarded to bug-libtool <at> gnu.org:
bug#78072; Package libtool. (Mon, 28 Apr 2025 15:43:02 GMT) Full text and rfc822 format available.

Message #8 received at 78072 <at> debbugs.gnu.org (full text, mbox):

From: Ileana Dumitrescu <ileanadumitrescu95 <at> gmail.com>
To: Mike Krinkin <krinkin.m.u <at> gmail.com>, 78072 <at> debbugs.gnu.org
Subject: Re: bug#78072: Libtool incorrectly tries to use shared library when
 linking statically
Date: Mon, 28 Apr 2025 18:41:57 +0300
[Message part 1 (text/plain, inline)]
On 25/04/2025 21:53, Mike Krinkin wrote:
> Hi There,

Hi Mike,

Thank you for your bug report!

> I hit a weird behaviour when build colm as part of building Envoy proxy. 
> Cutting through layers of the stack on top of the libtool things here is 
> what things boil down to:
> 
> 1. we have a project using autogen/configure/libtool that was configured 
> with `--enable-static` and `--disable-shared`
> 2. when I run make on the project one of the linking steps failed with 
> the following error:
> 
> ```
> ld.lld: error: attempted static link of dynamic object /usr/lib/libstdc++.so
> ```
>
> There is a lot there, but two things that I believe are particularly 
> relevant are: `--static` and `-lstdc++` flags.
> I believe that libtool next translated it into an actual command to link 
> the binary and from the logs here is what I saw:
>
> It's pretty close to what we asked libtool to do with a few differences: 
> it does not have -lstdc++ flag and instead passes /usr/lib/libstdc++.so 
> along with other object files as input to the linker which obviously 
> does not work.
> 
> My understanding is that libtool looked at -lstdc++ flag, found a 
> corresponding libstdc++.la file and "resolved" it into a shared library.
> 
> What I'm baffled by in this case is why did libtool resolve it to a 
> shared library instead of a static one, even though it's clearly a 
> static build?
> Moreover, even if we wanted to link against the dynamic library, it 
> should be done via -l flag, so what libtool looks very weird - we can't 
> just link shared library as if it was a object file or a static library.
> Am I missing something or libtool is completely off the mark here and 
> trying to do something weird?

This issue is similar in some ways to a couple of bugs that have been
reported recently [1] [2]. Since you are using clang, '-static-libstc++'
is not available, so I think you would need to utilize other libtool
flags, either '-static-libtool-libs' or '-all-static'. Here [3] is the
section of the manual that explains them, and it would likely require
editing your Makefile.am to pass them to libtool.

If updating your project configuration fixes this, I will close the bug.
Otherwise I will start reviewing the code for a way to fix this
behaviour.

[1] https://savannah.gnu.org/support/?111184
[2] https://savannah.gnu.org/support/?111202
[3] https://www.gnu.org/software/libtool/manual/html_node/Link-mode.html

-- 
Ileana Dumitrescu

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

[OpenPGP_0x6570EA01146F7354.asc (application/pgp-keys, attachment)]
[OpenPGP_signature.asc (application/pgp-signature, attachment)]

Information forwarded to bug-libtool <at> gnu.org:
bug#78072; Package libtool. (Mon, 28 Apr 2025 15:49:06 GMT) Full text and rfc822 format available.

Message #11 received at 78072 <at> debbugs.gnu.org (full text, mbox):

From: Mike Krinkin <krinkin.m.u <at> gmail.com>
To: Ileana Dumitrescu <ileanadumitrescu95 <at> gmail.com>
Cc: 78072 <at> debbugs.gnu.org
Subject: Re: bug#78072: Libtool incorrectly tries to use shared library when
 linking statically
Date: Mon, 28 Apr 2025 16:47:24 +0100
[Message part 1 (text/plain, inline)]
Hi Ileana,

thank you for the response. I will try to test it out to confirm if your
suggestions will fix the issue, it would take some time though.

The problem in our case though is that colm for us is a dependency - it's
not a project we own.
So while I can apply changes you suggested to test if they work, that's not
a solution we will be able to settle on.

Is there any reason why --static flag that was provided to libtool is not
enough indication to libtool to pick a static library over a shared one
when both are available?
If that behavior could be addressed somehow, IMO, it would be the best.
Otherwise, I think, it would be just much easier for us to drop the la
config alltogether rather than apply patches to a dependency.

On Mon, 28 Apr 2025 at 16:42, Ileana Dumitrescu <
ileanadumitrescu95 <at> gmail.com> wrote:

> On 25/04/2025 21:53, Mike Krinkin wrote:
> > Hi There,
>
> Hi Mike,
>
> Thank you for your bug report!
>
> > I hit a weird behaviour when build colm as part of building Envoy proxy.
> > Cutting through layers of the stack on top of the libtool things here is
> > what things boil down to:
> >
> > 1. we have a project using autogen/configure/libtool that was configured
> > with `--enable-static` and `--disable-shared`
> > 2. when I run make on the project one of the linking steps failed with
> > the following error:
> >
> > ```
> > ld.lld: error: attempted static link of dynamic object
> /usr/lib/libstdc++.so
> > ```
> >
> > There is a lot there, but two things that I believe are particularly
> > relevant are: `--static` and `-lstdc++` flags.
> > I believe that libtool next translated it into an actual command to link
> > the binary and from the logs here is what I saw:
> >
> > It's pretty close to what we asked libtool to do with a few differences:
> > it does not have -lstdc++ flag and instead passes /usr/lib/libstdc++.so
> > along with other object files as input to the linker which obviously
> > does not work.
> >
> > My understanding is that libtool looked at -lstdc++ flag, found a
> > corresponding libstdc++.la file and "resolved" it into a shared library.
> >
> > What I'm baffled by in this case is why did libtool resolve it to a
> > shared library instead of a static one, even though it's clearly a
> > static build?
> > Moreover, even if we wanted to link against the dynamic library, it
> > should be done via -l flag, so what libtool looks very weird - we can't
> > just link shared library as if it was a object file or a static library.
> > Am I missing something or libtool is completely off the mark here and
> > trying to do something weird?
>
> This issue is similar in some ways to a couple of bugs that have been
> reported recently [1] [2]. Since you are using clang, '-static-libstc++'
> is not available, so I think you would need to utilize other libtool
> flags, either '-static-libtool-libs' or '-all-static'. Here [3] is the
> section of the manual that explains them, and it would likely require
> editing your Makefile.am to pass them to libtool.
>
> If updating your project configuration fixes this, I will close the bug.
> Otherwise I will start reviewing the code for a way to fix this
> behaviour.
>
> [1] https://savannah.gnu.org/support/?111184
> [2] https://savannah.gnu.org/support/?111202
> [3] https://www.gnu.org/software/libtool/manual/html_node/Link-mode.html
>
> --
> Ileana Dumitrescu
>
> GPG Public Key: FA26 CA78 4BE1 8892 7F22 B99F 6570 EA01 146F 7354
>
>
[Message part 2 (text/html, inline)]

Information forwarded to bug-libtool <at> gnu.org:
bug#78072; Package libtool. (Tue, 29 Apr 2025 14:00:12 GMT) Full text and rfc822 format available.

Message #14 received at 78072 <at> debbugs.gnu.org (full text, mbox):

From: Ileana Dumitrescu <ileanadumitrescu95 <at> gmail.com>
To: 78072 <at> debbugs.gnu.org
Cc: Mike Krinkin <krinkin.m.u <at> gmail.com>
Subject: Re: bug#78072: Libtool incorrectly tries to use shared library when
 linking statically
Date: Tue, 29 Apr 2025 16:58:52 +0300
[Message part 1 (text/plain, inline)]
On 28/04/2025 18:47, Mike Krinkin wrote:
> Hi Ileana,
> 
> thank you for the response. I will try to test it out to confirm if your 
> suggestions will fix the issue, it would take some time though.
> 
> The problem in our case though is that colm for us is a dependency - 
> it's not a project we own.
> So while I can apply changes you suggested to test if they work, that's 
> not a solution we will be able to settle on.
> 
> Is there any reason why --static flag that was provided to libtool is 
> not enough indication to libtool to pick a static library over a shared 
> one when both are available?

I thought it should be enough indication, but after looking through
ltmain.in, the --static flag does not seem to be used for configuring
other variables that libtool needs, like prefer_static_libs:

	# Get the name of the library we link against.
	linklib=
	if test -n "$old_library" &&
	   { test yes = "$prefer_static_libs" ||
	     test built,no = "$prefer_static_libs,$installed"; }; then
	  linklib=$old_library
	else
	  for l in $old_library $library_names; do
	    linklib=$l
	  done
	fi

I have not been able to reproduce this issue easily, so I am not sure if
the following patch will work:

diff --git a/build-aux/ltmain.in b/build-aux/ltmain.in
index aaf48f14..11cf1c44 100644
--- a/build-aux/ltmain.in
+++ b/build-aux/ltmain.in
@@ -4848,7 +4848,7 @@ func_mode_link ()
 	build_old_libs=no
 	break
 	;;
-      -all-static | -static | -static-libtool-libs)
+      -all-static | -static | -static-libtool-libs | --static | -Bstatic)
 	case $arg in
 	-all-static)
 	  if test yes = "$build_libtool_libs" && test -z "$link_static_flag"; 
then
@@ -4865,7 +4865,7 @@ func_mode_link ()
 	  fi
 	  prefer_static_libs=built
 	  ;;
-	-static-libtool-libs)
+	-static-libtool-libs | --static | -Bstatic)
 	  if test -z "$pic_flag" && test -n "$link_static_flag"; then
 	    dlopen_self=$dlopen_self_static
 	  fi

If prefer_static_libs is already set to yes in your build, the above
patch should have no effect.

-- 
Ileana Dumitrescu

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

[OpenPGP_0x6570EA01146F7354.asc (application/pgp-keys, attachment)]
[OpenPGP_signature.asc (application/pgp-signature, attachment)]

This bug report was last modified 4 days ago.

Previous Next


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