【问题标题】:Error building gcc 4.8.3 from source: libstdc++.so.6: version `CXXABI_1.3.8' not found (required by /usr/lib/x86_64-linux-gnu/libicuuc.so.55)从源构建 gcc 4.8.3 时出错:libstdc++.so.6:找不到版本“CXXABI_1.3.8”(/usr/lib/x86_64-linux-gnu/libicuuc.so.55 需要)
【发布时间】:2023-03-28 20:41:01
【问题描述】:

我正在使用 gcc (Ubuntu 5.2.1-22ubuntu2) 5.2.1 20151010 进行编译,但我也尝试了 gcc 4.1.2,但我得到了同样的错误。

gcc 5.2.1

字符串 /usr/lib/x86_64-linux-gnu/libstdc++.so.6|grep CXXABI 给出

CXXABI_1.3
CXXABI_1.3.1
CXXABI_1.3.2 
CXXABI_1.3.3
CXXABI_1.3.4
CXXABI_1.3.5
CXXABI_1.3.6
CXXABI_1.3.7
CXXABI_1.3.8
CXXABI_1.3.9
CXXABI_TM_1
CXXABI_FLOAT128

对于正在编译的编译器 gcc 4.8.3

strings gcc-build/build/x86_64-linux-gnu/libstdc++-v3/src/.libs/libstdc++.so.6|grep CXXABI

CXXABI_1.3
CXXABI_1.3.1 
CXXABI_1.3.2 
CXXABI_1.3.3
CXXABI_1.3.4
CXXABI_1.3.5
CXXABI_1.3.6
CXXABI_1.3.7
CXXABI_TM_1
CXXABI_1.3
CXXABI_1.3.2
CXXABI_1.3.6
CXXABI_1.3.1
CXXABI_1.3.5
CXXABI_1.3.4
CXXABI_TM_1
CXXABI_1.3.7
CXXABI_1.3.3

即没有 1.3.8

在运行 configure 和 make 之前我也尝试过:

export LIBRARY_PATH=/usr/lib/x86_64-linux-gnu/:$LIBRARY_PATH
export LD_LIBRARY_PATH=/usr/lib/x86_64-linux-gnu/:$LD_LIBRARY_PATH
../gcc-4.8.3/configure --build=x86_64-linux-gnu
make 

错误信息:

msgfmt -o fr.mo ../../../../gcc-4.8.3/libstdc++-v3/po/fr.po
msgfmt: gcc-build/build/x86_64-linux-gnu/libstdc++-v3/src/.libs/libstdc++.so.6: version `CXXABI_1.3.8' not found (required by /usr/lib/x86_64-linux-gnu/libicuuc.so.55)
msgfmt: Makefile:460: recipe for target 'de.mo' failed

当使用 gcc 4.1.2 编译时,我得到同样的错误:

msgfmt -o fr.mo ../../../../libstdc++-v3/po/fr.po
gcc-build/gcc-4.8.3/build/x86_64-linux-gnu/libstdc++-v3/src/.libs/libstdc++.so.6: version `CXXABI_1.3.8' not found (required by /usr/lib/x86_64-linux-gnu/libicuuc.so.55)
Makefile:460: recipe for target 'de.mo' failed

使用 gcc 4.1.2 编译时,我在配置和制作之前做了以下操作

#where libraries i have compiled with gcc 4.1.2 are located i.e 
export LD_LIBRARY_PATH=/opt/devtools/gcc-4.1.2/lib
#where libstdc++.so.6 is
export LIBRARY_PATH=/opt/gcc-4.1.2/lib64

strings /opt/gcc-4.1.2/lib64/libstdc++.so.6|grep CXXABI
CXXABI_1.3
CXXABI_1.3.1
CXXABI_1.3.1
CXXABI_1.3

这让我想知道 CXXABI_1.3.8 是从哪里来的。我还在更改编译器之间做了一个“make distclean”

【问题讨论】:

  • 所以你有一个库或一些类似的库,它需要比你所链接的编译器支持的更新版本的 C++ 库。用旧的编译器重新编译整个项目,应该可以解决它。
  • 您正在使用的某些头文件(或目标文件)将需要更新的 C++ 库。我不确定您需要什么进一步的信息来解决这个问题,但基本上,您必须修复您的构建环境,以便它具有相关的 C++ 库...您可以使用不同的编译器重建 /usr/lib/x86_64-linux-gnu/libicuuc.so.55 ,也许?
  • 请注意,特定编译器版本附带的 C++ 库将支持特定 C++ ABI 版本,因此混合使用编译器会产生此类错误。
  • 非常感谢您的帮助。用 gcc 4.1.2 构建 libicuuc.so.55 然后构建 gcc 解决了我的问题

标签: c++ linux ubuntu gcc


【解决方案1】:

在构建 GCC 4.8.5 时,我偶然发现了使用较新的编译器组合的相同问题,即使用 gcc (Ubuntu 5.4.0-6ubuntu1~16.04.4) 5.4.0 20160609。到目前为止,解决方案显然完成了工作,并对问题给出了有价值的一般解释。我在下面提供了更多详细信息和替代解决方案。

有问题的错误消息来自 msgfmt 程序 - gettext 的一部分,一个国际化和本地化系统:

$ which msgfmt
/usr/bin/msgfmt
$ dpkg -S /usr/bin/msgfmt
gettext: /usr/bin/msgfmt

msgfmt 被 GCC 构建系统调用以编译当前正在构建的 C++ 标准库 (libstdc++) 发出的消息。 msgfmt 是一个动态链接的可执行文件,与 libicuuc.so.55 链接(以及其他) - 一个基于 Unicode 的跨平台全球化库:

$ ldd /usr/bin/msgfmt
    libicuuc.so.55 => /usr/lib/x86_64-linux-gnu/libicuuc.so.55 (0x00007ff133f47000)

(为清楚起见未显示其他依赖项)

icuuc 库本身就是一个动态链接的共享对象,它依赖于 stdc++ 库:

$ ldd /usr/lib/x86_64-linux-gnu/libicuuc.so.55
    libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007ff688a16000)

(为清楚起见未显示其他依赖项)

上面的清单是使用我的交互式 shell 环境生成的,它将对 libstdc++.so.6 的依赖解析为位于 /usr/lib/x86_64-linux-gnu 的 C++ 库的系统范围版本。但是,GCC 构建环境显然解决了对当前构建过程早期阶段生成的 C++ 库的这种依赖关系,即位于 $TOP_BUILD_DIR/x86_64-linux-gnu/libstdc++-v3/src/.libs 的库 - 回想一下最初发布的错误消息:

msgfmt: gcc-build/build/x86_64-linux-gnu/libstdc++-v3/src/.libs/libstdc++.so.6: version `CXXABI_1.3.8' not found (required by /usr/lib/x86_64-linux-gnu/libicuuc.so.55)

我得到了一个相当相似的输出:

msgfmt: /opt/build/gcc/gcc-4.8.4/x86_64-unknown-linux-gnu/libstdc++-v3/src/.libs/libstdc++.so.6: version `CXXABI_1.3.8' not found (required by /usr/lib/x86_64-linux-gnu/libicuuc.so.55)

现在,回答原始问题,字符串“CXXABI_1.3.8”来自libicuuc.so.55 库,这要求它所依赖的libstdc++.so.6 库提供特定的ABI 版本:

$ strings /usr/lib/x86_64-linux-gnu/libicuuc.so.55 | grep CXXABI
CXXABI_1.3.8
CXXABI_1.3

总而言之,GCC 构建系统创建了一个循环依赖,它将系统范围的二进制文件与本地库混合在一起:

libstdc++ (currenlty built) > msgfmt > libicuuc.so.55 > libstdc++.so.6

通过将libstdc++.so.6 解析为它自己的库结构而不是系统范围的版本。

Mats Petersson 提出的解决方案,包括重建libicuuc.so.55 库,使其依赖于旧版本的libstdc++.so.6,它(希望)与 GCC 构建系统兼容,当然是有效的。但是,这对我来说似乎有点不自然,因为它需要处理系统范围的二进制文件的依赖关系,这不受任何非 root 用户的控制。

我的替代解决方案涉及构建 gettext 包的自定义版本,这样msgfmt 二进制文件是自包含的,其依赖项不会干扰 GCC 构建系统。可以通过在/opt中安装gettext的自定义版本并使用环境模块调整相关路径来实现。

【讨论】:

  • 如何通过调整 env.模块?
  • @camilo 我说的是environment modules,它可以帮助您动态修改您的环境。我建议创建一个模块文件来调整 env($PATH、$LD_LIBRARY_PATH 和 $MANPATH)以自定义安装 gettext,然后将该模块插入用于构建 GCC 的 shell 中。时机成熟时,构建系统将调用您的自定义版本 msgfmt,这是您有意编译的,例如作为静态二进制文件,从而解决了 libstdc++ ABI 不兼容的问题。
【解决方案2】:

当我尝试在带有 GCC 5.4.0 的 Ubuntu 16.04.3 LTS 上从源代码构建 GCC 4.8.5 时遇到了同样的问题。

作为一种解决方法,我只是在 makefile 中为 msgfmt 命令删除了 LD_LIBRARY_PATH。准确地说,我给出了我为成功构建而执行的确切命令:

1 - 提取来源

tar zxfv gcc-4.8.5.tar.gz 
cd gcc-4.8.5

2 - 修改 msgfmt 的调用(添加 LD_LIBRARY_PATH= )并确保它正确

vi ./libstdc++-v3/po/Makefile.in
vi ./libstdc++-v3/po/Makefile.am
grep "MSGFMT =" ./libstdc++-v3/po/Makefile.in ./libstdc++-v3/po/Makefile.am
./libstdc++-v3/po/Makefile.in:MSGFMT = LD_LIBRARY_PATH= msgfmt
./libstdc++-v3/po/Makefile.am:MSGFMT = LD_LIBRARY_PATH= msgfmt

3 - 配置(我将 multilib 限制为仅 64 位,因为我没有在我的 64 位主机上安装 libc6-dev-i386 并且不想只为此构建执行此操作),构建并安装

./configure --prefix=$HOME/gcc-4.8.5 --with-multilib-list=m64
make
make install

【讨论】:

  • 这一定是正确答案
【解决方案3】:

因此,当使用较新编译器构建的库与较旧版本的 C++ 库链接时,或者有时当使用较新的头文件编译某些内容然后链接到较旧的 C++ 库时,就会出现此问题。

如果安装在“新系统”上的共享库比构建代码的共享库旧,那么在将二进制文件从一个系统移动到另一个系统时也可能会遇到类似的问题。

通常有三种可行的解决方案: 1. 使用较旧的编译器重新编译有问题的库。 2. 安装新版本的 C++ 库。 3. 从源代码重建 C++ 库(使用足够新的编译器)。

【讨论】:

    【解决方案4】:

    只需将系统安装目录中的libstdc++.so复制到你的gcc源相应目录,记得正确重命名。

    注意:编译过程中可能需要多次复制,gcc 会多次替换该库。

    【讨论】:

      猜你喜欢
      • 2017-12-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-07-23
      • 2022-10-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多