【问题标题】:Linking g++ 4.8 to libstdc++将 g++ 4.8 链接到 libstdc++
【发布时间】:2013-06-17 17:40:55
【问题描述】:

我在我的桌面上下载并构建了 gcc 4.8.1,运行 64 位 Ubuntu 12.04。我按照文档推荐的方式从源代码构建它,并使用命令

../../gcc-4.8.1/configure --prefix=$HOME --program-suffix=-4.8
make
make -k check
make install

它似乎通过了所有测试,我将所有内容都安装到我的主目录中,后缀为 -4.8,以区别于系统 gcc,即版本 4.6.3。

不幸的是,当我使用 g++-4.8 编译 c++ 程序时,它链接到系统 libc 和 libstdc++,而不是从 gcc-4.8.1 编译的较新的程序。我下载并构建了 gcc 4.8,因为我想在标准库中使用新的 C++11 功能,所以这种行为绝对不是我想要的。我该怎么做才能让 gcc-4.8 自动链接到它附带的标准库而不是系统标准库?

【问题讨论】:

  • libc 与 GCC 无关,所以没有“用 gcc-4.8.1 编译的较新的”,它应该链接到系统 libc。大概当您说它链接到系统 libstdc++ 时,您的意思是它链接正确但由于 libstdc++ 版本不正确而无法运行?
  • @JonathanWakely 是的,没错。

标签: c++ linux gcc g++ libstdc++


【解决方案1】:

当您使用自己的 gcc 链接时,您需要添加一个额外的运行时链接器搜索路径,使用 -Wl,-rpath,$(PREFIX)/lib64,以便在运行时找到与您的 gcc 对应的共享库。

我通常在与gcc-4.8g++-4.8 调用的目录中创建一个名为gccg++ 的包装器,而不是gcc-4.8g++-4.8,如Dynamic linker is unable to find GCC libraries 中所述:

#!/bin/bash
exec ${0}SUFFIX -Wl,-rpath,PREFIX/lib64 "$@"

安装时SUFFIXPREFIX 应替换为传递给configure 的内容:

cd ${PREFIX}/bin && rm -f gcc g++ c++ gfortran
sed -e 's#PREFIX#${PREFIX}#g' -e 's#SUFFIX#${SUFFIX}#g' gcc-wrapper.sh > ${PREFIX}/bin/gcc
chmod +x ${PREFIX}/bin/gcc
cd ${PREFIX}/bin && ln gcc g++ && ln gcc c++ && ln gcc gfortran

gcc-wrapper.sh 就是那个 bash sn-p)。


上述解决方案不适用于libtool 的某些版本,因为g++ -Wl,... -v 采用链接模式并因错误而失败。

更好的解决方案是使用规范文件。构建 gcc/g++ 后,调用以下命令使 gcc/g++ 将 -rpath 添加到链接器命令行(根据需要替换 ${PREFIX}/lib64):

g++ -dumpspecs | awk '/^\*link:/ { print; getline; print "-rpath=${PREFIX}/lib64", $0; next } { print }' > $(dirname $(g++ -print-libgcc-file-name))/specs

【讨论】:

【解决方案2】:

我在构建 gcc-4.8.2 时遇到了同样的问题。我在那台机器上没有 root 访问权限,因此需要安装到我的主目录。在我想出让它工作所需的魔力之前,我花了几次尝试,所以我将在这里复制它,这样其他人会更轻松。这些是我用来配置 gcc 的命令:

prefix=/user/grc/packages

export LDFLAGS=-Wl,-rpath,$prefix/lib
export LD_RUN_PATH=$prefix/lib
export LD_LIBRARY_PATH=$prefix/lib

../../src/gmp-4.3.2/configure  --prefix=$prefix
../../src/mpfr-2.4.2/configure --prefix=$prefix
../../src/mpc-0.8.1/configure  --prefix=$prefix --with-mpfr=$prefix --with-gmp=$prefix
../../src/gcc-4.8.2/configure  --prefix=$prefix --with-mpfr=$prefix --with-gmp=$prefix --with-mpc=$prefix --enable-languages=c,c++

这让我得到了一个可以工作的二进制文件,但是我用那个版本的 g++ 构建的任何程序都无法正确运行,除非我使用 -Wl,-rpath,$prefix/lib64 选项构建它。可以通过提供规范文件让 g++ 自动添加该选项。如果你运行

strace g++ 2>&1 | grep specs

您可以查看它检查哪些目录以查找规范文件。就我而言,它是 $prefix/lib/gcc/x86_64-unknown-linux-gnu/4.8.2/specs 所以我运行 g++ -dumpspecs 来创建一个新的规范文件:

cd $prefix/lib/gcc/x86_64-unknown-linux-gnu/4.8.2
$prefix/bin/g++ -dumpspecs > xx
mv xx specs

然后编辑该文件以提供 -rpath 选项。搜索这样的行:

*link_libgcc:
%D

并编辑以添加 rpath 选项:

*link_libgcc:
%D -rpath /user/grc/packages/lib/%M

%M 扩展为 ../lib 或 ../lib64,具体取决于您构建的是 32 位还是 64 位可执行文件。

请注意,当我在较旧的 gcc-4.7 版本上尝试相同的技巧时,它不起作用,因为它没有扩展 %M。对于旧版本,您可以删除 %M 并仅对 lib 或 lib64 进行硬编码,但这只有在您仅构建 32 位可执行文件(使用 lib)或仅构建 64 位可执行文件(使用 lib64)时才是可行的解决方案。

【讨论】:

  • 手动安装 gmp、mpfr 和 mpc 让您的生活变得不必要地复杂,然后必须设置 LD_LIBRARY_PATH 才能找到它们,请参阅 stackoverflow.com/a/10662297/981959
  • 感谢您提供的信息。我一定在 4.5 年前的 gcc 构建说明中错过了那个金块。很高兴知道以供将来参考。
【解决方案3】:

gcc -print-search-dirs 会告诉您编译器在哪里寻找运行时库等。您可以使用 -B<prefix> 选项覆盖它。

【讨论】:

  • GCC 将在链接时自动查找正确的库,问题是动态链接器在运行时不使用相同的路径,使用 -B 无法改变
  • @JonathanWakely - 好吧,OP 另有声明:“不幸的是,当我使用 g++-4.8 编译 c++ 程序时,它链接到系统 libc 和 libstdc++...” - 你得跟他说清楚。
  • 查看我对另一个答案的评论中的链接,这是一个常见问题解答。编译器在链接时链接到正确的库,但由用户确保在运行时再次使用相同的库。
  • @JonathanWakely - 啊。我明白你的意思了。如果没有-rpath 选项,它只会在ld.so 缓存中查找第一个libstdc++.x.so,或者LD_LIBRARY_PATH,对吗?如果我在 SO 上花费的时间过长,我往往会得到狭隘的视野。
  • 完全正确,如果该 libstdc++.so 不是二进制文件最初链接到的那个,它将无法运行
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-12-11
  • 1970-01-01
  • 2011-06-06
  • 2018-08-20
  • 2023-03-24
相关资源
最近更新 更多