Search code examples
linuxlinkersymbolsweak

When linking with --no-undefined and --as-needed, how should weak symbols be handled


When I link a shared library with --as-needed and --no-undefined, I see an error that indicates pthread_create is missing and is referenced by libstdc++_nonshared.a. If I remove --as-needed, the library links and ldd indicates that pthread.so is a dependency. If I instead remove --no-undefined, the library links and ldd indicates that pthread.so is not a dependency. Either way, if I do nm -d | grep pthread, I see a weak symbol reference to pthread_create. When I search for help on weak symbols, most documents say that the weak symbol references will not prevent a library from linking, but it seems like the weak symbols are blocking the link. How is this supposed to work?

The link error I see with both --as-needed and --no-undefined is: /opt/rh/devtoolset-8/root/usr/lib/gcc/x86_64-redhat-linux/8/libstdc++_nonshared.a(thread48.o): In function std::thread::_M_start_thread(std::unique_ptr<std::thread::_State, std::default_delete<std::thread::_State> >, void (*)())': (.text._ZNSt6thread15_M_start_threadESt10unique_ptrINS_6_StateESt14default_deleteIS1_EEPFvvE+0x11): undefined reference to pthread_create' /opt/rh/devtoolset-8/root/usr/lib/gcc/x86_64-redhat-linux/8/libstdc++_nonshared.a(thread48.o): In function std::thread::_M_start_thread(std::shared_ptr<std::thread::_Impl_base>, void (*)())': (.text._ZNSt6thread15_M_start_threadESt10shared_ptrINS_10_Impl_baseEEPFvvE+0x60): undefined reference to pthread_create


Solution

  • I made a smaller test. A single object file with a single doNothing() function and used the same link line without the pthread library and without the --as-needed. This still failed which made it more visible that one of the other shared libraries that I was linking might be causing the problem. I tried removing shared libraries from the link line until the link was successful and then I tried fixing the other shared library and then the linking was successful.

    Overall, the behavior I found was that --as-needed is checking very specifically about whether the shared library being linked has any strong references to a library while --no-undefined is checking the shared library being linked and all of the dependencies of the library being linked. The weak symbol reference in the library that was being linked was not causing the link to fail.