如何在gcc二进制文件的引导过程中设置rpath?

9

我正在尝试使用自定义前缀$PREFIX来构建gcc 4.7.2。

我已经将所有的先决条件构建并安装到我的前缀位置,然后成功地配置、构建和安装了gcc。

现在我遇到的问题是$PREFIX不在库搜索路径中,因此无法找到共享库。

$PREFIX/bin $ ./g++ ~/main.cpp 
$PREFIX/libexec/gcc/x86_64-suse-linux/4.7.2/cc1plus: \
    error while loading shared libraries: \
        libcloog-isl.so.1: \
           cannot open shared object file: No such file or directory

有用但不是理想的方法

如果我使用export LD_LIBRARY_PATH=$PREFIX/lib,那么程序可以正常运行,但我希望有一种无需设置环境变量的方法。

如果我使用patchelf来设置所有gcc二进制文件的RPATH,那么也可以正常工作;然而,这需要搜索所有Elf二进制文件并循环调用patchelf,我希望有更永久的解决方案。

我认为最理想的解决方案

因此,我希望在构建过程中通过make传递-Wl,-rpath,$PREFIX/lib

既然我知道路径不需要更改,这似乎是最健壮的解决方案,并且也可以在构建下一个gcc版本时使用。

是否可以配置构建过程来硬编码RPATH

我尝试过但不起作用的方法

在调用configure之前设置LDFLAGS_FOR_TARGET

所有这些方法都失败了:

export LDFLAGS_FOR_TARGET="-L$PREFIX/lib -R$PREFIX/lib" 
export LDFLAGS_FOR_TARGET="-L$PREFIX/lib" 
export LDFLAGS_FOR_TARGET="-L$PREFIX/lib -Wl,-rpath,$PREFIX/lib" 

在调用configure之前设置LDFLAGS:
export LDFLAGS="-L$PREFIX/lib -Wl,-rpath,$PREFIX/lib" 

无论如何,我担心这些将覆盖gcc本来会有的任何LDFLAGS,所以即使它们能够正常工作,我也不确定它们是否是一个可行的选项?

我的配置命令

为了完整起见,这是我传递给配置的命令行:

./configure \
    --prefix=$PREFIX \
    --build=x86_64-suse-linux \
    --with-pkgversion='SIG build 12/10/2012' \
    --disable-multilib \
    --enable-cloog-backend=isl \
    --with-mpc=$PREFIX \
    --with-mpfr=$PREFIX \
    --with-gmp=$PREFIX \
    --with-cloog=$PREFIX \
    --with-ppl=$PREFIX \
    --with-gxx-include-dir=$PREFIX/include/c++/4.7.2

不会是 LDFLAGS_FOR_TARGET:这可能用于 libgcc.so 和 libstdc++.so,但不适用于编译器二进制文件,因为它们是 主机 二进制文件。我认为 LDFLAGS 应该是正确的选择。 - ams
6个回答

10
我发现将gmp、mpfr、mpc、isl、cloog等源目录复制到顶层gcc源目录中(或使用相同名称的符号链接)可在任何地方使用。这实际上是首选方式。
为了使此方法起作用,您需要复制(或链接)到这些源目录名称没有版本号。
编译器不需要LD_LIBRARY_PATH(尽管使用编译器构建的应用程序需要一个LD_LIBRARY_PATH到$PREFIX/lib64或类似的路径 - 但这是不同的)
从您将保存所有源文件的源目录开始。 在这个源目录中,您有您的gcc目录,无论是通过解压tarball还是svn...我使用subversion。
此外,在此顶级目录中,您有以下源tarballs:
gmp-5.1.0.tar.bz2
mpfr-3.1.1.tar.bz2
mpc-1.0.1.tar.gz
isl-0.11.1.tar.bz2
cloog-0.18.0.tar.gz

我只是下载这些并定期更新到最新的tarballs。
脚本形式如下:
# Either:
svn checkout svn://gcc.gnu.org/svn/gcc/trunk gcc_work
# Or:
bunzip -c gcc-4.8.0.tar.bz2 | tar -xvf -
mv gcc-4.8.0 gcc_work

#  Uncompress sources..  (This will produce version numbered directories).
bunzip -c gmp-5.1.0.tar.bz2 | tar -xvf -
bunzip -c mpfr-3.1.1.tar.bz2 | tar -xvf -
gunzip -c mpc-1.0.1.tar.gz | tar -xvf -
bunzip -c isl-0.11.1.tar.bz2 | tar -xvf -
gunzip -c cloog-0.18.0.tar.gz | tar -xvf -

# Link outside source directories into the top level gcc directory.
cd gcc_work
ln -s ../gmp-5.1.0 gmp
ln -s ../mpfr-3.1.1 mpfr
ln -s ../mpc-1.0.1 mpc
ln -s ../isl-0.11.1 isl
ln -s ../cloog-0.18.0 cloog

# Get out of the gcc working directory and create a build directory.  I call mine obj_work.
# I configure the gcc binary and other outputs to be bin_work in the top level directory.  Your choice.  But I have this:
# home/ed/projects
# home/ed/projects/gcc_work
# home/ed/projects/obj_work
# home/ed/projects/bin_work
# home/ed/projects/gmp-5.1.0
# home/ed/projects/mpfr-3.1.1
# home/ed/projects/mpc-1.0.1
# home/ed/projects/isl-0.11.1
# home/ed/projects/cloog-0.18.0

mkdir obj_work
cd obj_work
../gcc_work/configure --prefix=../bin_work <other options>

# Your <other options> shouldn't need to involve anything about gmp, mpfr, mpc, isl, cloog.
# The gcc build system will find the directories you linked,
# then configure and compile the needed libraries with the necessary flags and such.
# Good luck.

你能更具体一些吗?最好提供几行脚本,说明在哪里运行。谢谢! - Jens
@Jens 我添加了一个脚本来执行我所做的操作。有时候我会直接复制依赖目录,而不是使用软链接。 - emsr
非常感谢。我不得不使用gmake all-binutils install-binutils all-gcc install-gcc,因为gmake all install会在某个地方失败,因为它无法确定一些后缀。在我的情况下,我没有编译本地编译器,而是使用了--target=powerpc-wrs-vxworks交叉编译器。 - Jens

5

在安装 gmp、isl 和 cloog 后,我一直在 FreeBSD 上使用 gcc-4.8.0 中的 configure 选项:

LD_LIBRARY_PATH=/path/to/isl/lib ./configure (lots of other options) \
  --with-stage1-ldflags="-rpath /path/to/isl/lib -rpath /path/to/cloog/lib -rpath /path/to/gmp/lib"

生成的gcc二进制文件不需要任何LD_LIBRARY_PATH。对于configure来说,需要LD_LIBRARY_PATH是因为它会编译一个测试程序来检查ISL版本,如果找不到ISL共享库,测试程序将失败。

我在Linux(Ubuntu)上尝试过,但在配置期间失败了,因为-rpath参数被传递给了gcc而不是ld。我可以通过使用以下命令修复:

--with-stage1-ldflags="-Wl,-rpath,/path/to/isl/lib,-rpath,/path/to/cloog/lib,-rpath,/path/to/gmp/lib"

相反。


谢谢!这看起来是我需要的东西。我不知道--with-stage1-ldflags选项;我会在我的平台上尝试并回报! - Steve Lorimer
GCC的所有配置选项都在http://gcc.gnu.org/install/configure.html上有文档记录。 - Jens

2

仅使用configure --with-stage1-ldflags="-Wl,-rpath,/path/to/lib"不足以让我成功构建gcc 4.9.2,在第二阶段引导失败。可行的方法是直接通过以下方式将标志传递给make:

make BOOT_LDFLAGS="-Wl,-rpath,/path/to/lib"

我从https://gcc.gnu.org/ml/gcc/2008-09/msg00214.html获取了这个信息。

0

我要提出一个建议,我相信它可以解决你的问题,尽管它肯定不能回答你的问题。让我们看看我会得到多少个踩。

编写一个通用的包装脚本来设置LD_LIBRARY_PATH,然后运行可执行文件很容易;请参见https://dev59.com/4mw05IYBdhLWcg3wrDlR#7101577

这个想法是将像--prefix=$PREFIX/install这样的东西传递给configure,构建一个看起来像这样的安装树:

$PREFIX/
    install/
        lib/
            libcloogXX.so
            libgmpYY.so
            ...
        bin/
            gcc
            emacs
            ...
    bin/
        .wrapper
        gcc -> .wrapper
        emacs -> .wrapper

.wrapper 是一个简单的 shell 脚本:

#!/bin/sh

here="${0%/*}"  # or use $(dirname "$0")
base="${0##*/}" # or use $(basename "$0")

libdir="$here"/../install/lib
if [ "$LD_LIBRARY_PATH"x = x ] ; then
    LD_LIBRARY_PATH="$libdir"
else
    LD_LIBRARY_PATH="$libdir":"$LD_LIBRARY_PATH"
fi
export LD_LIBRARY_PATH
exec "$here"/../install/bin/"$base" "$@"

这将正确转发所有参数,处理参数或目录名称中的空格等。实际上,它与您想要设置的 rpath 无差别。

此外,您不仅可以在 gcc 中使用此方法,还可以在整个 my-personal-$PREFIX 树中使用。在我想要最新的 GNU 工具套件但又没有(或不想承认有)root权限的环境中,我经常这样做。


0
尝试将您的$PREFIX添加到/etc/ld.so.conf中,然后运行ldconfig:
# echo $PREFIX >> /etc/ld.so.conf
# ldconfig

这将重新创建运行时链接器使用的缓存,并且它将选择您的库。

警告:此操作将导致所有应用程序使用位于$PREFIX中而不是默认位置的新编译库。


0

尽管仍然涉及设置环境变量,但我的做法是定义LD_RUN_PATH,以设置rpath。这样,系统的其余部分可以继续使用系统提供的库,而不是使用您的gcc构建生成的库。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接