C++ 所以从相对于加载可执行文件的目录加载

C++ 所以从相对于加载可执行文件的目录加载,c++,linux,shared-libraries,C++,Linux,Shared Libraries,由于与惯性有关的各种原因,我们没有makeinstall目标 < >我们将我们的大型C++代码库直接构建成一个类似于FHS的树;p> output/ bin/ lib/ etc/ ... 我们最近将一些第三方库转换为动态链接,因此我们将许多.so库推送到lib/ 现在,我们习惯于只从bin/启动可执行文件,但这不再有效,因为加载程序不搜索lib/目录 LD_LIBRARY_PATH可以解决这个问题,但我们不希望在每次可执行调用之前都提供它,我们也不希望将它固定在shell环境中

由于与惯性有关的各种原因,我们没有
makeinstall
目标

< >我们将我们的大型C++代码库直接构建成一个类似于FHS的树;p>
output/
  bin/
  lib/
  etc/
  ...
我们最近将一些第三方库转换为动态链接,因此我们将许多
.so
库推送到
lib/

现在,我们习惯于只从
bin/
启动可执行文件,但这不再有效,因为加载程序不搜索
lib/
目录

LD_LIBRARY_PATH
可以解决这个问题,但我们不希望在每次可执行调用之前都提供它,我们也不希望将它固定在shell环境中,因为我们通常在同一shell中的多个不同构建树之间切换

我们已经考虑在生成的ELF中添加一个
rpath
条目,但是相对路径通常是根据
$PWD
而不是可执行文件的dirname来解析的

是否有方法推动加载程序在
dirname(argv[0])/../lib
中查找.so libs


基本上,我知道有很多方法可以改变我们的习惯来实现这一点(也许应该),但我们不希望在这一点上,所以我们可以强制Linux so加载程序做我们想要的吗?谢谢

是的,可以使用
rpath
${ORIGIN}
宏,该宏在运行时由
ld.so
识别

man ld.so

ld.so understands certain strings in an rpath specification 
(DT_RPATH or DT_RUNPATH); those strings are substituted as follows

$ORIGIN (or equivalently ${ORIGIN})
    This expands to the directory containing the application executable.

更多变量可用。您不需要强制加载程序执行任何操作。它具有适合您的功能。:)

很好,谢谢!我认为即使没有
rpath
,也没有办法实现这一点。Windows有一个清单文件的概念,您可以将其放在可执行文件旁边,以控制类似的内容。如果
ld有类似的带外机制,那就太酷了,所以
。最流行的解决方案是提供包装器外壳脚本来设置环境并调用二进制文件。很多大型项目都是这样做的
IntelliJ IDEA
Android Studio
是两个著名的例子。很有意义,谢谢。我们希望不必再教育那些在肌肉记忆中拥有所有可执行名称的开发人员。无论如何,回答得很好,谢谢!在这种情况下,我会将
bin/app
移动到
bin/app.bin
并将包装器脚本放入
bin/app
。没有人会看到区别。Firefox和Thunderbird使用了这种方法。不要忘记传递所有参数,保持不变。:)