Bug #1055
closedstatic build produces dynamic executable
0%
Description
When configured for a static build (configure --disable-shared --enable-static), a dynamic executable is produced without error or warning. This is with current stable-1.4 branch on Fedora 23 x86_64.
$ git describe --all --long
heads/stable-1.4-0-g09c9a6e8d4ec
$ ./bootstrap && ./configure --disable-shared --enable-static
[ ... complete output attached ... ]
$ make
[ ... ]
$ file converter/babeltrace
converter/babeltrace: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 2.6.32, BuildID[sha1]=af3ef2edcc6d6475a1eacab62c1f7d1622a2133d, not stripped
$ rm converter/babeltrace && make V=1
/bin/sh ../libtool --tag=CC --mode=link gcc -pthread -I/usr/include/glib-2.0 -I/usr/lib64/glib-2.0/include -Wall -Wformat -I../include -g -O2 -pthread -I/usr/include/uuid -Wl,--no-as-needed -o babeltrace babeltrace.o ../lib/libbabeltrace.la ../formats/ctf/libbabeltrace-ctf.la ../compat/libcompat.la ../formats/ctf-text/libbabeltrace-ctf-text.la ../formats/ctf-metadata/libbabeltrace-ctf-metadata.la ../formats/bt-dummy/libbabeltrace-dummy.la ../formats/lttng-live/libbabeltrace-lttng-live.la ../lib/libdebug-info.la -ldw -lelf -lpopt -luuid -Wl,--export-dynamic -lgmodule-2.0 -pthread -lglib-2.0
libtool: link: gcc -pthread -I/usr/include/glib-2.0 -I/usr/lib64/glib-2.0/include -Wall -Wformat -I../include -g -O2 -pthread -I/usr/include/uuid -Wl,--no-as-needed -o babeltrace babeltrace.o -Wl,--export-dynamic -pthread ../lib/.libs/libbabeltrace.a ../formats/ctf/.libs/libbabeltrace-ctf.a ../compat/.libs/libcompat.a ../formats/ctf-text/.libs/libbabeltrace-ctf-text.a /home/nathanl/src/babeltrace/formats/ctf/.libs/libbabeltrace-ctf.a ../formats/ctf-metadata/.libs/libbabeltrace-ctf-metadata.a ../formats/bt-dummy/.libs/libbabeltrace-dummy.a ../formats/lttng-live/.libs/libbabeltrace-lttng-live.a ../lib/.libs/libdebug-info.a /home/nathanl/src/babeltrace/lib/.libs/libbabeltrace.a -ldw -lelf -lpopt -luuid -lgmodule-2.0 -lglib-2.0 -pthread
I think the LTTng CI is seeing this too; see for example:
Files
Updated by Nathan Lynch over 8 years ago
After looking into this a bit I think there are two parts to this issue:
1.) Using inappropriate link flags (-Wl,--export-dynamic) prevents static link from being attempted.
2.) Once (1) is fixed, GLib APIs are used from constructor code which can run before GLib itself is initialized, causing program abort.
(1) arises from running pkg-config against "gmodule" instead of just "glib". Babeltrace doesn't use any GModule facilities, so it shouldn't need --export-dynamic to work correctly. See:
https://developer.gnome.org/glib/stable/glib-compiling.html
Fixing (1) allows static linking of the babeltrace executable to succeed. Note that configuring with --enable-static isn't enough; one must also add CFLAGS=-static LDFLAGS=--static to the configure line.
Running the binary results in many GLib assertion failures and eventual abort, due to GLib API calls in constructor functions before GLib's initialization has run (I verified this in GDB):
(process:17328): GLib-CRITICAL **: g_hash_table_lookup: assertion 'hash_table != NULL' failed (process:17328): GLib-CRITICAL **: g_hash_table_insert_internal: assertion 'hash_table != NULL' failed GLib:ERROR:gquark.c:60:g_quark_init: assertion failed: (quark_seq_id == 0) Aborted (core dumped)
I'm not sure how to address the runtime issue with constructors at this time.
Updated by Nathan Lynch over 8 years ago
I opened this issue with an incorrect expectation on my part: that "configure --disable-shared --enable-static" is the convention for telling Autotools to build a statically linked executable. This is not so. These options only tell libtool what kinds of libraries (PIC/shared and non-PIC/static) to produce during the build, and the executable is linked according to the options available, with a preference for the shared libraries.
So there are three kinds of babeltrace executable that can be produced:
1. Fully dynamic: runtime dependencies on internal libraries (libbabeltrace.so.1, libbabeltrace-ctf.so.1, and so on) as well as runtime dependencies on external libraries (libpopt, libuuid, et al). This is the default when configured with --enable-shared and make is invoked without the user setting LDFLAGS.
2. Partially dynamic: internal libraries built-in but runtime dependencies on external libraries. (make LDFLAGS=-static)
3. Static: all dependencies built-in, no runtime dependencies. (make LDFLAGS=-all-static)
Configuring with --disable-shared --enable-static just causes the default to be case #2 since internal shared libraries are not available.
However, this produces an executable without all the plugins included:
$ ./converter/babeltrace --list Formats available: text, ctf.
This is because the lttng-live, ctf-metadata, and dummy format libraries are dead code in the linker's view (and --no-as-needed does not change this when these are being linked statically). --whole-archive might work around it but it doesn't seem easy to use from Automake/libtool in my experimentation.
In conclusion, there is still an issue here, but it is a different one from the original report, and fully static linking is a whole other mess :) Let me know if I should open new issues so it's less confusing.
Updated by Jérémie Galarneau over 8 years ago
Thanks for doing the digging! I don't think a new bug report is necessary.
Updated by Jérémie Galarneau about 8 years ago
- Status changed from New to Feedback
Hi Nathan,
Would you mind trying with the latest master?
Thanks,
Jérémie
Updated by Nathan Lynch about 8 years ago
Case #2 from my previous comment (Partially dynamic: internal libraries built-in but runtime dependencies on external libraries. (make LDFLAGS=-static)) now works correctly, thanks.
Updated by Jonathan Rajotte Julien almost 5 years ago
- Status changed from Feedback to Invalid
State of babeltrace moved a lot since.
Closing this ticket as invalid. Reopen it if it stills apply to Babeltrace 2.