I'm having trouble with using a library that contains weak-symbols and the --as-needed linker flag.
Example
(This uses the Jack library)
$ cat <<EOF >myjack.c
#include <jack/weakjack.h>
#include <jack/jack.h>
int main() {
if (jack_client_opent)
jack_client_open("foobar", JackNoStartServer, 0, 0);
else return 1;
return 0;
}
EOF
$ gcc -o myjack myjack.c -Wl,--no-as-needed -ljack
$ ./myjack && echo "ok" || echo "K.O."
ok
$ ldd myjack | grep jack
libjack.so.0 => /usr/lib/x86_64-linux-gnu/libjack.so.0 (0x00007f16f615f000)
$ gcc -o myjack myjack.c -Wl,--as-needed -ljack
$ ./myjack && echo "ok" || echo "K.O."
K.O.
$ ldd myjack | grep jack
$
(The example code was edited to not segfault any more, as the segfault is not my actually problem)
The problem
It seems that the problem is:
Jack declares all symbols as weak (if I include
<jack/weakjack.h>). this is fine with me; I do want my symbols to stay weak. esp. my program is weakly linking against jack on OSX (-weak_framework Jackmp), which requires to include<jack/weakjack.h>When linking with
--as-needed, the linker excludes any library, that does not reference at least one non-weak symbol. from the manpage:
--as-needed causes a DT_NEEDED tag to only be emitted for a library that at that point in the link satisfies a non-weak undefined symbol reference from a regular object file
- some OSs (e.g. Ubuntu-16.04LTS) have
--as-neededenabled by default.
Now I think that --as-needed is a nice linker feature to get rid of many really unneeded runtime dependencies.
However, I fail to see why a weak dependency is considered as no dependency at all. For me, a weak dependency is to enable optional features. I do want these features to be enabled if possible, and the decision whether this is possible should be a runtime decision. With the current behavior, it becomes a compile-time decision. (If I wanted that, I would simply disable the relevant code via some preprocessor magic).
One solution is obviously to just add --no-as-needed to the linker flags.
I don't want this: I do want to get rid of overlinking, if my distribution (or whoever compiles my binary) thinks this is the thing to do.
So I might turn on as-needed after linking in my known-weak library:
gcc -o myjack myjack.c -Wl,--no-as-needed -ljack -Wl,--as-needed ...
but this feels wrong as well, as then all libraries after my forced-needed library are suddenly forced to --as-needed (which might not be what my distribution or whoever compiles my binary thinks that this is the thing to do). It also seems to be adding a lot of cruft to the build chain, just because some library happens to export weak symbols only. I do not want to manually track all libraries that do this.
I also could of course simply not include <jack/weakjack.h>. The reason why it is included is because the application also works on OSX, where I do want to optionally depend on the JACK framework (so I link with -weak_framework Jackmp), and keep my program runnable in th absence of that framework.
I really don't want to clutter my application code because of the subtle differences between linkers on various platforms. This is probably the main issue I'm having with all this: why should I add platform-specific code to my application to cater for different linker specifics - I'd probably be OK with adding feature-specific code, e.g. not including weakjack.h if the compiler has no equivalent for -weak_library or -weak_framework; but currently it seems that the closest I can get is something like #ifdef __APPLE__ which makes me shudder in this context).
So I'd really love some option to force libraries that only have weak symbols to be dylinked nevertheless.
Is there such a thing?