自定义 gcc 安装的LIBRARY_PATH优先级



有没有办法让编译器更喜欢LIBRARY_PATH库中的库而不是系统路径。我特别喜欢叮当。在写这个问题时,我部分解决了 GCC 的问题,但也不是很清楚。

背景

LIBRARY_PATH是一个方便的环境变量,允许透明地链接非标准目录中的库,例如用户安装,以及在我的情况下提供不同版本库的环境模块。 这个想法是做一个module load libfoo/version,编译器将透明地使用正确的libfoo.so

对于共享库,还需要为ld.so设置LD_LIBRARY_PATH以找到合适的库。如果在LD_LIBRARY_PATH/usr/lib中有多个libfoo.sold.so指定在默认路径之前搜索LD_LIBRARY_PATH

问题

当库定义soname时,我遇到了问题 - 在/usr/libLIBRARY_PATH中,两个libfoo.so版本(分别是指向libfoo.so.1libfoo.so.2的符号链接)不同。然后ld将链接到/usr/lib中的sonameLD_LIBRARY_PATH无法再优先考虑预期的库。

我第一次遇到这个 boost ,但这里有一个小例子:

echo "void foo() {}" > foo.c
# create an old libfoo version in /usr/lib
sudo gcc foo.c -fpic -shared -o /usr/lib/libfoo.so.1 -Wl,-soname,libfoo.so.1
sudo ln -s libfoo.so.1 /usr/lib/libfoo.so
# create the new libfoo that we want to transparently override
mkdir -p /tmp/XXX/lib
gcc foo.c -fpic -shared -o /tmp/XXX/lib/libfoo.so.2 -Wl,-soname,libfoo.so.2
ln -s libfoo.so.2 /tmp/XXX/lib/libfoo.so
export LIBRARY_PATH=/tmp/XXX/lib
export LD_LIBRARY_PATH=/tmp/XXX/lib
echo "void foo(); int main() { foo(); }" > main.c
gcc main.c -lfoo
ldd a.out| grep foo
# under some conditions this shows libfoo.so.1 instead of .2
libfoo.so.1 => /usr/lib/libfoo.so.1

海湾合作委员会

我最初在自定义安装GCC时遇到了此问题,而GCC正在按系统安装的预期工作。gcc --print-search-dirs揭示了一个模式:

/tmp/XXX/lib/x86_64-pc-linux-gnu/7.2.0/
/tmp/XXX/lib/x86_64-linux-gnu/
/tmp/XXX/lib/../lib64/
/opt/gcc/7.2.0/lib/gcc/x86_64-pc-linux-gnu/7.2.0/
/opt/gcc/7.2.0/lib/gcc/x86_64-pc-linux-gnu/7.2.0/../../../../x86_64-pc-linux-gnu/lib/x86_64-pc-linux-gnu/7.2.0/
/opt/gcc/7.2.0/lib/gcc/x86_64-pc-linux-gnu/7.2.0/../../../../x86_64-pc-linux-gnu/lib/x86_64-linux-gnu/
/opt/gcc/7.2.0/lib/gcc/x86_64-pc-linux-gnu/7.2.0/../../../../x86_64-pc-linux-gnu/lib/../lib64/
/opt/gcc/7.2.0/lib/gcc/x86_64-pc-linux-gnu/7.2.0/../../../x86_64-pc-linux-gnu/7.2.0/
/opt/gcc/7.2.0/lib/gcc/x86_64-pc-linux-gnu/7.2.0/../../../x86_64-linux-gnu/
/opt/gcc/7.2.0/lib/gcc/x86_64-pc-linux-gnu/7.2.0/../../../../lib64/
/lib/x86_64-pc-linux-gnu/7.2.0/
/lib/x86_64-linux-gnu/
/lib/../lib64/
/usr/lib/x86_64-pc-linux-gnu/7.2.0/
/usr/lib/x86_64-linux-gnu/
/usr/lib/../lib64/
/tmp/XXX/lib/
/opt/gcc/7.2.0/lib/gcc/x86_64-pc-linux-gnu/7.2.0/../../../../x86_64-pc-linux-gnu/lib/
/opt/gcc/7.2.0/lib/gcc/x86_64-pc-linux-gnu/7.2.0/../../../
/lib/
/usr/lib/

除了正常的搜索优先级(LIBRARY_PATH在系统路径之前)之外,GCC 还会优先考虑一些"前缀",包括../lib64。这可以通过创建另一个符号链接来解决:

ln -s lib /tmp/XXX/lib64

我认为这与configure期间的--libdir参数有关,我省略了该参数,并且在系统安装中/usr/lib,但即使我指定--libdir=$PREFIX/lib --libexecdir=$PREFIX/lib,它也更喜欢../lib64

如何在运行时编译或控制gcc,使其至少使用../lib而不是后缀../lib64

叮当更是不配合。它不包括--print-search-dirs输出中的LIBRARY_PATH,甚至不包括-L/tmp/XXX/lib它调用ld是否可以在/usr/lib中找到libfoo.so

如何让 Clang 透明地确定我的库路径的优先级?

笔记

  • 示例来自 Archlinux,但我也在 Ubuntu 16.04 下进行了测试,它的行为类似。
  • GCC 的相关问题:为什么 g++ 看起来像 LIBRARY_PATH/../lib64 这在哪里记录?和 g++ 搜索/lib/../lib/,然后是/lib/。
  • -L覆盖搜索顺序是有效的,但不是透明的。
  • gcc --print-search-dirs列出的目录多于gcc -v。后者过滤掉非退出路径。

我发现了GCC的自定义安装不同的原因。Debian 发行版修补了 GCC makefiles,这就是它获得正确优先级LIBRARY_PATH的方式。在构建 GCC 之前,找到gcc/config/i386/t-linux64,将所有MULTILIB_OSDIRNAMES更改为以下行:

MULTILIB_OSDIRNAMES = m64=../lib$(call if_multiarch,:x86_64-linux-gnu)
MULTILIB_OSDIRNAMES+= m32=../lib32$(call if_multiarch,:i386-linux-gnu)
MULTILIB_OSDIRNAMES+= mx32=../libx32$(call if_multiarch,:x86_64-linux-gnux32)

同时将--libexecdir=/your/custom/path/lib --libdir=/your/custom/path/lib添加到configure

最新更新