3

I'm having some troubles compiling a large C++ project that uses link time optimization. After some digging I managed to produce an (almost) minimal working example that exhibits the same issue.

Say that I have the following foo.cpp file:

//foo.cpp
#include <iostream>
#include "bar.h"

int main()
{
    std::cout << "Hello world" << std::endl;
    //bar(); //Everything works if this is uncommented

    return 0;
}

Where bar.h and bar.cpp look like this:

//bar.h
#ifndef __BAR_H__
#define __BAR_H__

void bar();

#endif

and

//bar.cpp
#include "bar.h"
#include <thread>

void bar()
{
    std::thread t([] {});
    t.join();
}

The code is compiled like this:

$ g++ -std=c++11 -O3 -flto -c foo.cpp
$ g++ -std=c++11 -O3 -flto -c bar.cpp

But trying to link the object files results in a undefined reference error:

$ g++ -flto -Wl,-as-needed foo.o bar.o -lpthread
/usr/bin/ld: /usr/lib/gcc/x86_64-linux-gnu/8/libstdc++.so: undefined reference to `pthread_create'
collect2: error: ld returned 1 exit status

Can somebody please explain what is going on here?

Some notes:

  • Adding the -pthread flag makes no difference.
  • I'm explicitly passing the option -Wl,-as-needed as, on my system, this is not the default. However, this is the default behavior in some other GNU/Linux distributions.
  • Linking succeeds if I uncomment the call to bar() in foo.cpp.
  • Linking succeeds if the option -Wl,--as-needed is removed (or -Wl,--no-as-needed is added).
  • I'm using g++ 8.3.0 (Debian 8.3.0-6) but the same problem appears in g++ 7.4.0 (Ubuntu 7.4.0-1ubuntu1~18.04).

Edit: clang with lld works fine.

$ clang++ -fuse-ld=lld -flto -Wl,-as-needed foo.o bar.o -lpthread
$ ./a.out 
Hello world
Steven
  • 209
  • 2
  • 10
  • Seems like a linker bug to me, maybe file a bug report – M.M May 30 '19 at 03:12
  • Linking with -pthread does not make any difference. Also compiling with -pthread does not make any difference, regardless on whether -pthread is used for linking or not. – Steven Jun 03 '19 at 14:29
  • 2
    If the gold linker is installed, try linking with `-fuse-ld=gold`. But as M.M said, this looks like a linker bug. It's probably worth reporting. I use the latest version of binutils (2.32) and I can reproduce the issue. – Nikos C. Jun 03 '19 at 14:35
  • @NikosC. Everything works with gold. Thank you for confirming the issue. I'll look into filing a bug report. – Steven Jun 03 '19 at 15:30
  • 1
    The issue seems to be fixed in binutils 2.32.51.20190707-1 in Debian testing. – Steven Aug 01 '19 at 22:59
  • @Steven, thank you for this question, all my questions were marked as a duplicate (which they werent) and now after another 3h I finally found this, you are my hero ^^ – Coronon Oct 24 '20 at 15:54

0 Answers0