将 Clang 与内置的 libstdc++ 一起使用会产生未定义的符号 _ZSt15__once_callable
Using Clang with built libstdc++ produces undefined symbol _ZSt15__once_callable
我构建了 libstdc++,还没有修改:
cd gccsrcdir/libstdc++-v3/build
../configure --prefix=$PWD/../install
make && make install
我正在使用 Ubuntu 21.10 并设置了以下环境变量:
export LIBRARY_PATH=gccsrcdir/libstdc++-v3/install/lib
export LD_LIBRARY_PATH=gccsrcdir/libstdc++-v3/install/lib
export CPLUS_INCLUDE_PATH=gccsrcdir/libstdc++-v3/install/include/c++/13.0.0
然后当我使用系统的GCC时,我没有遇到任何问题。当我使用系统的 Clang 时,它会产生符号查找错误 - 即使没有参数:
clang++
clang++: symbol lookup error: /lib/x86_64-linux-gnu/libicuuc.so.67: undefined symbol: _ZSt15__once_callable, version GLIBCXX_3.4.11
其实我只需要更新LD_LIBRARY_PATH
就可以到达这里。我做错了什么?
符号 -- std::__once_callable
在您的系统 libstdc++.so.6
中定义(它在我的构建中有版本 GLIBCXX_3.4.11
,means 它是在 GCC-4.4 中添加的.0).
您的 libstdc++.so.6
构建也应该 定义此符号,但由于某些原因没有。 是 一个问题——任何使用此符号的二进制文件在使用 libstdc++.so.6
的构建时都会在 运行 时失败(这是因为你指出LD_LIBRARY_PATH
到它)。
注意:在您的情况下,clang++
二进制文件未能 运行 -- 您添加到其中的任何标志(例如 -femulated-tls
)都是 irrelevant——它们只会影响如果clang++
本身没有失败就会生成的二进制文件。
我只是重复了你的 configure && make
步骤,而这样构建的库 也 没有定义这个符号。
然后我重复了 configure && make
,但是从 top-level GCC 目录开始,libstdc++.so.6
以这种方式构建 定义了符号。
结论:libstdc++
在“正常”GCC 构建期间配置不同。
定义来自 mutex.o
,它是从 ./libstdc++-v3/src/c++11/mutex.cc
构建的,并且有这段代码:
#ifdef _GLIBCXX_HAS_GTHREADS
namespace std _GLIBCXX_VISIBILITY(default)
{
_GLIBCXX_BEGIN_NAMESPACE_VERSION
#ifdef _GLIBCXX_HAVE_TLS
__thread void* __once_callable;
__thread void (*__once_call)();
...
因此,当直接在 libstdc++-v3
中执行 configure && make
时,听起来好像没有定义 _GLIBCXX_HAS_GTHREADS
或 _GLIBCXX_HAVE_TLS
。
进一步挖掘,我看到 libstdc++-v3
通过尝试编译 #include "gthr.h"
来确定 _GLIBCXX_HAS_GTHREADS
,并且该文件在 libgcc/gthr.h
中可用,但是 不是 在“标准”安装的 GCC 中。
../libstdc++-v3/configure && grep _GLIBCXX_HAS_GTHREADS config.h
/* #undef _GLIBCXX_HAS_GTHREADS */
TL;DR:正确配置 libstdc++.so
很复杂,构建 complete GCC 会更好。
完成构建后,您将有一个正确配置的 libstdc++-v3
目录,并且可以在该目录中重建:
grep _GLIBCXX_HAS_GTHREADS ./x86_64-pc-linux-gnu/libstdc++-v3/config.h
#define _GLIBCXX_HAS_GTHREADS 1
我构建了 libstdc++,还没有修改:
cd gccsrcdir/libstdc++-v3/build
../configure --prefix=$PWD/../install
make && make install
我正在使用 Ubuntu 21.10 并设置了以下环境变量:
export LIBRARY_PATH=gccsrcdir/libstdc++-v3/install/lib
export LD_LIBRARY_PATH=gccsrcdir/libstdc++-v3/install/lib
export CPLUS_INCLUDE_PATH=gccsrcdir/libstdc++-v3/install/include/c++/13.0.0
然后当我使用系统的GCC时,我没有遇到任何问题。当我使用系统的 Clang 时,它会产生符号查找错误 - 即使没有参数:
clang++
clang++: symbol lookup error: /lib/x86_64-linux-gnu/libicuuc.so.67: undefined symbol: _ZSt15__once_callable, version GLIBCXX_3.4.11
其实我只需要更新LD_LIBRARY_PATH
就可以到达这里。我做错了什么?
符号 -- std::__once_callable
在您的系统 libstdc++.so.6
中定义(它在我的构建中有版本 GLIBCXX_3.4.11
,means 它是在 GCC-4.4 中添加的.0).
您的 libstdc++.so.6
构建也应该 定义此符号,但由于某些原因没有。 是 一个问题——任何使用此符号的二进制文件在使用 libstdc++.so.6
的构建时都会在 运行 时失败(这是因为你指出LD_LIBRARY_PATH
到它)。
注意:在您的情况下,clang++
二进制文件未能 运行 -- 您添加到其中的任何标志(例如 -femulated-tls
)都是 irrelevant——它们只会影响如果clang++
本身没有失败就会生成的二进制文件。
我只是重复了你的 configure && make
步骤,而这样构建的库 也 没有定义这个符号。
然后我重复了 configure && make
,但是从 top-level GCC 目录开始,libstdc++.so.6
以这种方式构建 定义了符号。
结论:libstdc++
在“正常”GCC 构建期间配置不同。
定义来自 mutex.o
,它是从 ./libstdc++-v3/src/c++11/mutex.cc
构建的,并且有这段代码:
#ifdef _GLIBCXX_HAS_GTHREADS
namespace std _GLIBCXX_VISIBILITY(default)
{
_GLIBCXX_BEGIN_NAMESPACE_VERSION
#ifdef _GLIBCXX_HAVE_TLS
__thread void* __once_callable;
__thread void (*__once_call)();
...
因此,当直接在 libstdc++-v3
中执行 configure && make
时,听起来好像没有定义 _GLIBCXX_HAS_GTHREADS
或 _GLIBCXX_HAVE_TLS
。
进一步挖掘,我看到 libstdc++-v3
通过尝试编译 #include "gthr.h"
来确定 _GLIBCXX_HAS_GTHREADS
,并且该文件在 libgcc/gthr.h
中可用,但是 不是 在“标准”安装的 GCC 中。
../libstdc++-v3/configure && grep _GLIBCXX_HAS_GTHREADS config.h
/* #undef _GLIBCXX_HAS_GTHREADS */
TL;DR:正确配置 libstdc++.so
很复杂,构建 complete GCC 会更好。
完成构建后,您将有一个正确配置的 libstdc++-v3
目录,并且可以在该目录中重建:
grep _GLIBCXX_HAS_GTHREADS ./x86_64-pc-linux-gnu/libstdc++-v3/config.h
#define _GLIBCXX_HAS_GTHREADS 1