使用--no-undefined与--as-needed链接时弱符号引发的链接问题
pthread_create is missing when linking with --as-needed and --no-undefined Let’s break down the root causes of your issue and how to fix it:
Key Background
First, clarify what each linker option does in this context:
--as-needed: The linker only includes a shared library (like-lpthread) if there’s a strong, unresolved reference to symbols it provides. Weak references don’t trigger inclusion.--no-undefined: The linker rejects any shared library with unresolved symbols—this applies to both strong and weak references, even though weak symbols can technically be undefined at runtime.libstdc++_nonshared.a: This static archive contains code for C++ standard library features likestd::thread, which makes strong references topthread_create(sincestd::threadrelies on pthread for implementation on Linux).
Why the Error Happens
When using both options together:
- The linker processes your code and pulls in
thread48.ofromlibstdc++_nonshared.a(because you’re usingstd::thread). This object file has a strong reference topthread_create. - If
-lpthreadis in the wrong order (beforelibstdc++) or isn’t explicitly forced to be included,--as-neededskips-lpthread—since at the time the linker processes-lpthread, there are no unresolved strong references to its symbols yet. --no-undefinedthen throws an error becausepthread_createremains unresolved (even if your own code only has weak references to it, the strong reference fromlibstdc++is enough to trigger this).
Why Your Workarounds Work
- Removing
--as-needed: The linker includes-lpthreadunconditionally, resolvingpthread_createand satisfying--no-undefined.lddshowspthread.soas a dependency because it’s included regardless of need. - Removing
--no-undefined: The linker allows unresolved symbols (including the strongpthread_createreference fromlibstdc++), so linking succeeds.--as-neededskips-lpthread(since your code doesn’t have strong references to it), soldddoesn’t list it as a dependency. However, this is risky—your code will crash at runtime ifpthreadisn’t loaded whenstd::threadis used.
Fixes
1. Correct Library Order
Ensure -lpthread comes after libstdc++ (or any libraries that reference pthread symbols) in your link command. This way, when the linker processes -lpthread, it sees the unresolved pthread_create reference from libstdc++ and includes the library:
gcc -shared -o libfoo.so foo.o -Wl,--as-needed,--no-undefined -lstdc++ -lpthread
2. Force Inclusion of pthread
If you can’t adjust the library order, use --no-as-needed around -lpthread to override the --as-needed behavior for this library:
gcc -shared -o libfoo.so foo.o -Wl,--as-needed,--no-undefined -lstdc++ -Wl,--no-as-needed,-lpthread,--as-needed
This forces the linker to include -lpthread even if it wouldn’t otherwise be considered "needed," resolving the pthread_create symbol.
3. Verify Weak vs Strong References
Run nm -C libstdc++_nonshared.a | grep pthread_create to check if the reference from libstdc++ is strong (marked with U for undefined, no W or w). If it’s a strong reference, you must link -lpthread to satisfy --no-undefined.
内容的提问来源于stack exchange,提问作者daltairwalter

