7

通常,程序(在 Linux 中)使用 LD_LIBRARY_PATH 来定位它们的共享库,但我想使用自定义路径,而不是永久更改 LD_LIBRARY_PATH。

基本上,一个 bash-wrapper 可以很容易地实现它:

#!/bin/sh
export LD_LIBRARY_PATH=/my_lib_path/
/my_bin_path/myprogram $*

(Bash 仅在此脚本中更改 LD_LIBRARY_PATH,而不是永久更改)

我想知道是否有可能在一个单一的可执行文件中用纯 C 语言做同样的事情而没有丑陋的 bash-hack。所有路径和库的确切名称在编译时都是已知的。

4

4 回答 4

6

-rpath将选项传递给ld,或通过您的编译器-Wl,-rpath。它允许您扩展搜索路径。它通常由希望从某个插件目录加载模块的可执行文件使用。您可以通过此方法添加任意数量的目录。

于 2012-12-30T17:03:07.237 回答
4

您不能LD_LIBRARY_PATH在运行时更改,动态加载程序在程序执行时读取一次并且不再检查它,您可以使用dlopen()代替自己加载共享库:

dlopen("/path/to/shared/lib.so", RTLD_LAZY);

这仅在您加载库并dlsym()在运行时使用来查找符号时才有效,否则如果您调用库中的函数,则必须在加载时解析这些引用,并且 AFAIK 您必须使用类似 bashscript 的东西。

注意:如果您重新执行该过程,可以在运行时更改LD_LIBRARY_PATH,我刚刚测试过它,它似乎工作,但它非常hackish,它可能是唯一的方法C

void *handle;
// first time check if path is not set
if (getenv("LD_LIBRARY_PATH")==NULL) {
    //set it and re-execute the process
    setenv("LD_LIBRARY_PATH", "/path/to/lib/", 1);
    execl(argv[0], argv[0], NULL);
}
// open the shared library the second time
handle = dlopen("test.so", RTLD_LAZY);
printf("%p\n", handle);
dlclose(handle);
于 2012-12-30T17:02:39.910 回答
4

正如其他人所说,链接程序时,您可以使用-Wl,-rpath将特定路径添加到应用程序的库搜索路径。但是,如果您只想对特定库的路径进行硬编码,请在链接时使用该路径,而不是使用该-l选项。例如,代替-lfoo,只需/opt/foo/lib/libfoo.so.1在链接命令行上使用。

于 2012-12-30T17:07:40.143 回答
0

我认为这在执行时是不可能的:在执行程序之前加载库......

但是您可以通过将选项传递-rpath给链接器来在编译时执行此操作

于 2012-12-30T17:03:22.633 回答