Symbols from convenience library not getting exported in executable
Asked Answered
C

2

8

I have a program, myprogram, which is linked with a static convenience library, call it libconvenience.a, which contains a function, func(). The function func() isn't called anywhere in myprogram; it needs to be able to be called from a plugin library, plugin.so.

The symbol func() is not getting exported dynamically in myprogram. If I run

nm myprogram | grep func

I get nothing. However, it isn't missing from libconvenience.a:

nm libconvenience/libconvenience.a | grep func
00000000 T func

I am using automake, but if I do the last linking step by hand on the command line instead, it doesn't work either:

gcc -Wl,--export-dynamic -o myprogram *.o libconvenience/libconvenience.a `pkg-config --libs somelibraries`

However, if I link the program like this, skipping the use of a convenience library and linking the object files that would have gone into libconvenience.a directly, func() shows up in myprogram's symbols as it should:

gcc -Wl,--export-dynamic -o myprogram *.o libconvenience/*.o `pkg-config --libs somelibraries`

If I add a dummy call to func() somewhere in myprogram, then func() also shows up in myprogram's symbols. But I thought that --export-dynamic was supposed to export all symbols regardless of whether they were used in the program or not!

I am using automake 1.11.1 and gcc 4.5.1 on Fedora 14. I am also using Libtool 2.2.10 to build plugin.so (but not the convenience library.)

I didn't forget to put -Wl,--export-dynamic in myprogram_LDFLAGS, nor did I forget to put the source that contains func() in libconvenience_a_SOURCES (some Googling suggests that these are common causes of this problem.)

Can somebody help me understand what is going on here?

Cuyp answered 14/11, 2010 at 1:58 Comment(0)
C
7

I managed to solve it. It was this note from John Calcote's excellent Autotools book that pointed me in the right direction:

Linkers add to the binary product every object file specified explicitly on the command line, but they only extract from archives those object files that are actually referenced in the code being linked.

To counteract this behavior, one can use the --whole-archive flag to libtool. However, this causes all the symbols from all the system libraries to be pulled in also, causing lots of double symbol definition errors. So --whole-archive needs to be right before libconvenience.a on the linker command line, and it needs to be followed by --no-whole-archive so that the other libraries aren't treated that way. This is a bit difficult since automake and libtool don't really guarantee keeping your flags in the same order on the command line, but this line in Makefile.am did the trick:

myprogram_LDFLAGS = -Wl,--export-dynamic \
    -Wl,--whole-archive,libconvenience/libconvenience.a,--no-whole-archive
Cuyp answered 14/11, 2010 at 10:28 Comment(1)
In bazel, this corresponds to cc_library( alwayslink=True )Kwakiutl
K
0

If you need func to be in plugin.so, you should try and locate it there if possible. Convenience libraries are meant to be just that -- a convenience to link to an executable or lib as an intermediate step.

Kassia answered 14/11, 2010 at 2:4 Comment(1)
True, but I explicitly need func not to be in the plugin, because func is part of an API that several plugins need to call. The plugins were written elsewhere and I'm trying to avoid local modifications to them.Cuyp

© 2022 - 2024 — McMap. All rights reserved.