我在编译一个使用链接时间优化的大型 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