3

我在编译一个使用链接时间优化的大型 C++ 项目时遇到了一些麻烦。经过一番挖掘,我设法产生了一个(几乎)最小的工作示例,它展示了同样的问题。

假设我有以下foo.cpp文件:

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

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

    return 0;
}

bar.h和bar.cpp看起来像这样:

//bar.h
#ifndef __BAR_H__
#define __BAR_H__

void bar();

#endif

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

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

代码编译如下:

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

但是尝试链接目标文件会导致未定义的引用错误:

$ 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

有人可以解释一下这里发生了什么吗?

一些注意事项:

  • 添加 -pthread 标志没有任何区别。
  • 我明确传递了选项 -Wl,-as-needed,因为在我的系统上,这不是默认设置。但是,这是其他一些 GNU/Linux 发行版中的默认行为。
  • 如果我取消注释 foo.cpp 中对 bar() 的调用,则链接成功。
  • 如果选项 -Wl,--as-needed 被删除(或 -Wl,--no-as-needed 添加),则链接成功。
  • 我正在使用 g++ 8.3.0 (Debian 8.3.0-6),但同样的问题出现在 g++ 7.4.0 (Ubuntu 7.4.0-1ubuntu1~18.04) 中。

编辑:带有lld的clang可以正常工作。

$ clang++ -fuse-ld=lld -flto -Wl,-as-needed foo.o bar.o -lpthread
$ ./a.out 
Hello world
4

0 回答 0