libpthread in mingw does not find the libraries

2019-07-04 20:55发布

问题:

I am trying to compile the following program with mingw:

#include <pthread.h>
#include <errno.h>
#include <unistd.h>
#include <iostream>
#include <cstdio>

void *hello(void *id) {
  int nid = *static_cast<int*>(id);
  std::printf("Hello from thread %d\n", nid);
  return 0;
}

int main(int argc, char **argv) {
  pthread_t ids[2];
  int *params[2];
  for (int i = 0; i < 2; ++i) {
    params[i] = new int;
    *params[i] = i;
    pthread_create(&ids[i], 0, hello, params[i]);
  }
  for (int i = 0; i < 2; ++i)
    pthread_join(ids[i], 0);
  for (int i = 0; i < 2; ++i)
    delete params[i];
  return 0;
}

using this command:

g++ -lpthread -ohello.exe hello.cc

And I get the following message:

C:\Users\XXXXXX~1\AppData\Local\Temp\cczPlv0w.o:hello.cc:(.text+0xad): undefined 
reference to `_imp__pthread_create'
C:\Users\XXXXXX~1\AppData\Local\Temp\cczPlv0w.o:hello.cc:(.text+0xe9): undefined 
reference to `_imp__pthread_join'
collect2: ld returned 1 exit status

But with an older version of MingGW I had no problems running pthreads programs. (This is just the simple of all the programs that failed, but basically everything that uses pthreads ends up with the same error, C and C++)

回答1:

Move -lpthread to the end of that command:

g++ -ohello.exe hello.cc -lpthread

The order of the arguments is important. (Using -pthread throughout instead of -lpthread for linking is actually recommended, since it sets flags both for the preprocessor and the linker.)



回答2:

Library specifications are position dependent with gcc, it will only bring in unresolved symbols at the point where the library is listed.

Because you haven't listed your main object file at that point, the only unresolved symbol is main. You need to move the library specifications to the point where there will be unresolved symbols they can satisfy.

I've never really understood why gcc chose this path since it sometimes leads to situations where you have to list libraries more than once (such as with circular dependencies). The only reason I've ever thought of is to keep control as to what libraries are allowed to resolve specific symbols.

I've seen more "intelligent" linkers where they simply batch up all the libraries till the end then go through them over and over again until either all symbols are satisfied or there is no chance that they can be. This saves a lot of effort but you do lose that aforementioned control.