Undefined reference to ‘pthread_create’ — linker command option order (libraries before/after object files?) [duplicate]

List libraries after the object files

When linking only object files and libraries, list the libraries after the object files:

gcc -o Server1.exe -Wall -Wunused -ansi -pedantic -ggdb  Server1.o Util.o -lpthread -lm

When the linking command includes source files, list the source files and object files (if any) before the libaries. The -l options come at the end of the command line, therefore. Relevant -L options specifying where a library is found should come before the -l option specifying the library.

The subsidiary question is:

Why does it work?

When the C compiler invokes the linker, it tells the linker to pull in some system object files with names like crt0.o, and tells it to look for a symbol main (or possibly _main(), depending on local naming conventions). It also supplies the object files and libraries in the order you specified on the command line. When it comes across an object file, the linker notes the definitions it provides, and the unsatisfied references it makes. When it comes across a library, it scans the library to see whether it can satisfy any unsatisfied references. If the library can supply any as yet unsatisfied references, then it includes (the relevant parts of) the library ‘in the executable’. For a shared library, the linker ensures that the library will be loaded at runtime. For a static library, the linker includes the object files from the library that satisfy at least one reference, rescanning until there are no further references that can be satisfied. If the library satisfies no references, it is ignored. When the process is complete, if any references are still unsatisfied, you get the error messages.

So, in your scenario, you had -lpthread before either Server1.o or Util.o. Since -lpthread does not provide a main function and that was the only relevant unsatisfied symbol, it was ignored. The mathematics library, -lm may also have been ignored, or it may be an empty stub to keep code devised for other systems where the mathematics library is separate from the main C library. Then the linker read your object files, and found the reference to pthread_create(). When it scanned the C library -lc (libc.so) afterwards, it found symbols to satisfy everything except pthread_create.

When the libraries are listed after the object files, then the linker knew it needed pthread_create when it scanned -lpthread and ensured that the shared library would be loaded at runtime.

GNU ld and the --as-needed option

The discussion above is essentially platform-neutral. If you follow the ‘libraries after object files’ rule, your linker line has the maximum chance of working correctly on all platforms.

If you are on a system using the GNU binutils package, and the GNU ld command in particular, you may find different behaviour.

The manual from Sourceware (which is where you are redirected if you try http://www.gnu.org/software/binutils/manuals) includes the information:

--as-needed
--no-as-needed
This option affects ELF DT_NEEDED tags for dynamic libraries mentioned on the command line after the --as-needed option. Normally the linker will add a DT_NEEDED tag for each dynamic library mentioned on the command line, regardless of whether the library is actually needed or not. --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 or, if the library is not found in the DT_NEEDED lists of other libraries, a non-weak undefined symbol reference from another dynamic library. Object files or libraries appearing on the command line after the library in question do not affect whether the library is seen as needed. This is similar to the rules for extraction of object files from archives. --no-as-needed restores the default behaviour.

It appears that different versions of different systems use different values for the as-needed option. While the --no-as-needed behaviour is convenient in that it lets you order libraries and object files in more or less any order on your command line, it also means that all the libraries listed on the command line are loaded at run time, even if there are no symbols actually used from the library (thus --no-as-needed is equivalent to a hypothetical --whether-needed-or-not flag). Using the --as-needed option is the classic and portable behaviour.

Rumour has it that some Linux distributions changed the default behaviour on their systems from --no-as-needed to --as-needed sometime in the last 5 years or so (the first half of the second decade of the third millennium, for sake of argument). You can find evidence in support of this rumour in a number of questions on SO.

Leave a Comment